Having function errors with a basic script to transfer owners - javascript

I am trying to create a simple script to transfer owners on Google Calendar but one of the functions isn't working properly on the Google Calendar API. The function is the calendar.GetOwner function.
Here is what I tried.
function transferOwnership() {
// Get the calendar to transfer ownership from
var calendar = CalendarApp.getCalendarById("primary");
// Set the email address of the new owner
var newOwner = "new.owner#example.com";
// Define the keywords to match events to transfer
var keywords = ["Project Meeting", "Important Call"];
// Get the current date and time
var now = new Date();
// Get the list of events in the next 7 days
var events = calendar.getEvents(now, new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000));
// Loop through each event
for (var i = 0; i < events.length; i++) {
// Get the current owner of the event
var currentOwner = events[i].getCreators()[0];
// Check if the current owner is you
if (currentOwner == calendar.getOwner().getEmail()) {
// Loop through each keyword
for (var j = 0; j < keywords.length; j++) {
// Check if the event title contains the keyword
if (events[i].getTitle().indexOf(keywords[j]) >= 0) {
// Change the owner to the new owner
events[i].setCreators([newOwner]);
// Break the inner loop
break;
}
}
}
}
}
Omitted person info with basic variables
4:04:22 PM Notice Execution started
4:04:22 PM Error
TypeError: calendar.getOwner is not a function
transferOwnership # Code.gs:25

Related

How do I update the <p> element inside my HTML dialog box on passing of every minute, in javascript?

My HTML :
<dialog id="wait_dialog">
<p style="font-family: cursive;" id="report_data">Downloading, please wait..</p>
<button id="close_wait_dialog">Cancel</button>
</dialog>
My JS :
function generate_complete_input(data){
return $.ajax({
url: '/backend.php',
type: 'POST',
data: {"data": data}
})
}
function geninp(response){
const arr=JSON.parse(response);
for(var j=0; j<arr.length; j++){
//populate table here
}
}
let arr = ["00001","00002","50003"];
(async() => {
document.getElementById("wait_dialog").showModal();
var start = new Date().getMinutes();
for(var i=0; i<arr.length; i++){
response = await generate_complete_input(arr[i]);
geninp(response);
}
var end = new Date().getMinutes();
var remaining_time = end - start; //get the time required to run the for loop (in minutes)
var inst = setInterval(update_dialog(remaining_time),60000); //update dialog with a message
})();
function update_dialog(time){
time -= 1;
document.getElementById("report_data").innerText += "(Remaining time: "+time+" minutes)";
if(time == 0){
clearInterval(inst);
document.getElementById("wait_dialog").close();
}
}
I want to update my dialog with the time that was required to run the for(){} loop. So I call a setInterval() method which will keep on editing the text inside the dialog box every minute, until the time becomes 0. I've checked my console, there are no errors there.
But, upon executing the code, the dialog text never gets edited. It just stays as Downloading, please wait... Where am I going wrong?
OBJECTIVE: Suppose, the for loop takes 5 mins to execute. My dialog box, in this case, should be:
Downloading, please wait..(Remaining time: 5 minutes)
then, after a minute, it should be:
Downloading, please wait..(Remaining time: 4 minutes)
Downloading, please wait..(Remaining time: 3 minutes)...
And so on.
i will assume that everything works fine on your backend response and your functions works well,
the way you update the text input is wrong,
this is how you solve your problem
let arr = ["00001","00002","50003"];
(async() => {
document.getElementById("wait_dialog").showModal();
// var start = new Date().getMinutes();
for(var i=0; i<arr.length; i++){
// response = await generate_complete_input(arr[i]);
// geninp(response);
}
// var end = new Date().getMinutes();
let start = 5, end = 10;
var remaining_time = end - start; //get the time required to run the for loop (in minutes)
update_dialog(remaining_time); //update dialog with a message
})();
function update_dialog(time){
let reportText = document.getElementById("report_data").innerText;
var inst = setInterval(()=> {
document.getElementById("report_data").innerText = reportText + `(Remaining ${time} minutes)`;
time -= 1;
if(time < 0){
clearInterval(inst);
document.getElementById("wait_dialog").close();
}
}, 1000); // am using 1 second just to demonstrate
}
<dialog id="wait_dialog">
<p style="font-family: cursive;" id="report_data">Downloading, please wait..</p>
<button id="close_wait_dialog">Cancel</button>
</dialog>
I expect you have errors in your console. Press F12 and look at the console tab. There will be some red lines showing errors.
The most likely cause is that your setInterval call is formatted incorrectly. You need to pass a function to this, not the result of one.
Change to this:
(async() => {
document.getElementById("wait_dialog").showModal();
var start = new Date().getMinutes();
for(var i=0; i<arr.length; i++){
response = await generate_complete_input(arr[i]);
geninp(response);
}
var end = new Date().getMinutes();
var remaining_time = end - start; //get the time required to run the
for loop (in minutes)
var inst = setInterval(() =>
{
remaining_time -= 1;
update_dialog(remaining_time);
}, 60000); //update dialog with a message
})();
function update_dialog(time){
document.getElementById("report_data").innerText += "(Remaining time: "+time+" minutes)";
if(time == 0){
clearInterval(inst);
document.getElementById("wait_dialog").close();
}
}

How to use a variable

I have a question / problem about a variable.
I have two page, in the first one I recover data and in the second one I do some operations.
ActivityPage.js (the first one)
recoverActivity() {
// this function check every second if the size of array > 1000
// this call only a function in the other page (Operations)
Operations.write({
arrayTimestamp: this.arrayTimestamp,
// other things
});
}
//this function when the user click a stop button.
stopActivity() {
Actions.Operations({
arrayTimestamp: this.arrayTimestamp,
});
}
And the I have another page
Operations.js:
//this is called from the first page directly
write(objectData) {
//...
this.timestampCheck(objectData.arrayTimestamp);
//...
}
//this is call from the ComponentDidMount of the second page.
stopClick() {
//...
this.timestampCheck(this.props.arrayTimestamp);
//...
}
Now my problem is in this timestampCheck function:
timestampCheck(timestamp) {
var int_max = 65536;
this.base = 0;
var diff = "";
var start = parseInt(this.contatore);
for (let i = 0; i < timestamp.length; i++) {
let timestamp = parseInt(timestamp[i]);
diff = (this.base + timestamp) - start;
if (diffDestro < 0) {
this.base+= int_max;
diff += this.base;
}
this.tempoReale.push(diff);
}
}
This function is called from the two function stopClick and write and there I have a variable this.base. Now I don't want that this variable loose his value when it leaves the functions timestampCheck. For example the arrayTimestamp has a size > 1000 an so it call the write() functions. here calculations are made and the value of this.base is set.
At this point, if the user clicks the stop key, the stopClick () function is called which calls the same timestampCheck function and must resume the previous value of this.base and not start from scratch.
How do you think I can do it?
thank you so much.
Just use a variable outside of the function to store the new value.
So outside of the function:
var countingValue = 0;
function timestampCheck(timestamp) {
var int_max = 65536;
this.base = 0;
var valueToUse = countingValue > 0 ? countingValue : this.base;
var diff = 0;
var start = parseInt(this.contatore);
for (let i = 0; i < timestamp.length; i++) {
let timestamp = parseInt(timestamp[i]);
diff = (valueToUse + timestamp) - start;
if (diffDestro < 0) {
valueToUse += int_max;
diff += valueToUse;
}
this.tempoReale.push(diff);
countingValue = countingValue + diff;
}
}
So what I have done here is create a variable outside of the function named countingValue with an initial value of 0.
Then underneath the initialisation of this.base I have used a type of If statement known as a ternary operator which says if the current countingValue is more than 0 then we will store that value in a variable named valueToUse otherwise we will use the this.base value and store it in the valueToUse variable.
In the rest of the code I have used the valueToUse variable for the computations now instead of this.base.
Note: I changed your variable diff to an integer because it was a string. You may want to review this and swap a couple of variables around if it's not exactly what you want.

Unable to loop over table rows to animate respective progress bars

Ok, for brevity's sake, I'm just including the javascript code itself. If the HTML or CSS is really needed, I'll update the post.
The objective: I've got a table with rows (displaying tasks), and I have a progress bar to the right of each task showing how much time has elapsed.
The problem: only the first progress bar works. All subsequent progress bars just show a completely filled-up bar. Upon looking at the console log, the program isn't looping at all. It performs no calculations for any rows other than the first. I've tried moving various variables inside and outside the loop, but no cigar.
Please forgive me if the code looks terrible and/or the answer is obvious. This is essentially my first real javascript 'program.'
var Table = document.getElementsByTagName("table");
var Row = document.getElementsByTagName("tr");
var rowDisplay = document.getElementsByTagName("td");
function fillBar(timeElapsedPercent) {
for (i = 0; i < rowDisplay.length; i++) {
var eachRow = rowDisplay.item(i);
const interval = setInterval(() => {
// Grabbing the needed info from the cells
var taskName = rowDisplay[0].innerText;
var rawDeadline = rowDisplay[1].innerText;
var rawStartTime = rowDisplay[2].innerText;
var bar = document.querySelector('.bar');
//calculations for the progress bar
var now = new Date();
var startTime = new Date(rawStartTime.replace(/(am|pm)/, ''));
var deadline = new Date(rawDeadline.replace(/(am|pm)/, ''));
var timeTotal = Math.abs(deadline - startTime);
var timeTotalPercent = Math.abs(timeTotal / 60000);
console.log('value for total time in minutes of', taskName, 'is', timeTotalPercent);
var nowTillDeadline = Math.abs(deadline - now);
var nowTillDeadlinePercent = Math.abs(nowTillDeadline / 60000);
var timeElapsed = Math.abs(timeTotalPercent - nowTillDeadlinePercent);
var timeElapsedPercent = Math.abs((timeElapsed / timeTotalPercent) * 100);
// moving the progress bar
bar.style.width = timeElapsedPercent + '%';
if (timeElapsedPercent >= 99) {
bar.style.width = '100%';
clearInterval(interval);
}
}, (1*1000))
}
}
fillBar();
All right then, time to answer my own question again.
I'll include the HTML for the row, then the Javascript to manipulate it:
<td class="col-sm-4">
<div id="progressBarBackground">
<div class="bar" id="progressBar"></div>
</div>
</td>
function fillBar() {
const interval = setInterval(() => {
var i;
for (i = 1; i < Table.rows.length; i++) {
// grabbing relevant info from DOM
var taskName = Table.rows[i].cells[0].innerText;
var rawDeadline = Table.rows[i].cells[1].innerText;
var rawStartTime = Table.rows[i].cells[2].innerText;
var bar = Table.rows[i].cells[6].getElementsByClassName("bar").item(0);
// calculations for progress bar
var now = new Date();
var startTime = new Date(rawStartTime.replace(/(am|pm)/, ''));
var deadline = new Date(rawDeadline.replace(/(am|pm)/, ''));
var timeTotal = Math.abs(deadline - startTime);
var timeTotalPercent = Math.abs(timeTotal / 60000);
var nowTillDeadline = Math.abs(deadline - now);
var nowTillDeadlinePercent = Math.abs(nowTillDeadline / 60000);
var timeElapsed = Math.abs(timeTotalPercent - nowTillDeadlinePercent);
var timeElapsedPercent = Math.abs((timeElapsed / timeTotalPercent) * 100);
// manipulating the necessary DOM element
bar.style.width = timeElapsedPercent + '%';
if (timeElapsedPercent >= 99) {
bar.style.width = '100%';
clearInterval(interval);
}
}
}, (1*1000))
}
So my problems were as follows:
1) The for-loop needs to be inside the interval, not the other way around. I read somewhere that an interval is basically just a timed for-loop. That was a light bulb moment for me.
2) Using .querySelector() to get the progress bar only gets the first one, even if it's in the for-loop; to get the progress bar for each row, the .getElementsByClassName() method was needed in addition to the .item() method with its index position, which you would never know from the error code you get if you leave it out. Since I only had one element within the cell to get, its index position is 0.
3) At the start of my for-loop, I changed from displayRows.length to Table.rows.length, but in order to do that, I had to change the way I defined var Table. Instead of .getElementsByTagName(), I used get .getElementById() -- for my fellow noobs, note it's just one Element, not Elements.
I think those were the three main issues. There were probably other minor issues, but I tried about 100 different things between now and when I first posted the problem, so it's hard to know.
I also made use of console.log at various points while I was troubleshooting everything. I deleted those lines here for the sake of code neatness, but they were immensely helpful.

How do I get daily step count in a gear fit 2 pro web based watchface?

I am building a html/js powered watchface for the gear fit 2 pro and I'm having trouble accomplishing what seems like a simple task: getting the daily step count.
I have poured over the documentation, but it only describes how to count either steps since the watchface has started, or steps since the device has been booted. Other watchfaces immediately detect the system-wide step count and display it, but I don't see how this is possible!
Does anyone have an example of how to do this? I suspect the stepdifference or readrecorderdata functions might be involved, but the first is impossible to use due to inadequate documentation and the second does not seem to actually be present in the device.
You can setAccumulativePedometerListener() for the time period sensor data required. In you case you can reset the listener at end of the day. I've written a pseudo_code for you to show daily step count.
var sensor_data = document.getElementById("sensor-data");
var step_count=0,
offset=0, // to reduce yesterday's data
currentDailyStep=0;
function updateTime() {
var datetime = tizen.time.getCurrentDateTime(),
hour = datetime.getHours(),
minute = datetime.getMinutes(),
second = datetime.getSeconds();
if(hour === 23 && minute === 59 && second === 59){ // at the end of the day
tizen.humanactivitymonitor.unsetAccumulativePedometerListener();
tizen.humanactivitymonitor.stop("PEDOMETER");
offset = step_count; // store today's count
pedometer_init(); //reset
}
/*
* Other Codes
* ............
* .........
*/
}
function onchangedCB(pedometerInfo) {
step_count = pedometerInfo.accumulativeTotalStepCount;
currentDailyStep = step_count - offset; // totl count - total count till yesterday
sensor_data.innerHTML = currentDailyStep;
}
function pedometer_init(){
tizen.humanactivitymonitor.start("PEDOMETER");
tizen.humanactivitymonitor.setAccumulativePedometerListener(onchangedCB);
}
function init(){
pedometer_init();
}
window.onload = init();
You need to reduce offset manually as stop() function don't reset the count. Store the daily step data If you are interested to show statistics.
In addition, In Tizen Developers API References there's a Code Sample using HumanActivityRecorder to record Step count daily, Please Check If it helps:
function onerror(error){
console.log(error.name + ": " + error.message);
}
function onread(data){
for (var idx = 0; idx < data.length; ++idx)
{
console.log("*** " + idx);
console.log('totalStepCount: ' + data[idx].totalStepCount);
}
}
var type = 'PEDOMETER';
var now = new Date();
var startTime = now.setDate(now.getDate() - 7);
var anchorTime = (new Date(2000, 1, 2, 6)).getTime();
var query ={
startTime: startTime / 1000,
anchorTime: anchorTime / 1000,
interval: 1440 /* 1 day */
};
try{
tizen.humanactivitymonitor.readRecorderData(type, query, onread, onerror);
}
catch (err){
console.log(err.name + ': ' + err.message);
}

AngularJS Countdown within an ng-repeat

I have a small AngularJS app which searches and retrieves a listing of users and their next scheduled meeting (assuming one is scheduled in the next 8 hours) brought back from the server using JSON with the time format in UTC for ease of calculation to local times. Each user could have a different status (busy until x time, free until x time).
What I would like to accomplish is to be able to update the DOM with time remaining until the meeting scheduled has completed or time left until the meeting starts. I have some code working sort of, but because I am apparently not doing this correctly with only a few entries in the result set it brings the browser to a near standstill. Any suggestions would be appreciated!
My current code consists of the following snippets:
[Main Page]
<tr ng-repeat="item in pagedItems[currentPage-1] | orderBy:sortingOrder:reverse" ng-class="{success:item._freeBusy=='Free', error:item._freeBusy=='Busy'}">
<td>{{item._firstName}}</td>
<td>{{item._lastName}}</td>
<td>{{item._facilityName}}</td>
<td>{{item._extension}}</td>
<td>{{item._description}}</td>
<td><a ng-hide="!item._extension" ng-click="dial(item)">Dial</a></td>
<td><button class="btn btn-primary" ng-click="openDetails(item)">Details</button></td>
<td>{{item._freeBusy}} {{item._timeLeft}} {{calculateTime(item._freeBusyTime,$index)}}</td>
</tr>
[Controller]
$scope.timeUntil = function(s) {
function isoToObj(s) {
var b = s.split(/[-T+:]/i);
return new Date(Date.UTC(b[0], --b[1], b[2], b[3], b[4], b[5]));
}
// Utility to add leading zero
function z(n) {
return (n < 10 ? '0' : '') + n;
}
// Convert string to date object
var d = isoToObj(s);
var diff = d - new Date();
// Allow for previous times
var sign = diff < 0 ? '-' : '';
diff = Math.abs(diff);
// Get time components
var hours = diff / 3.6e6 | 0;
var mins = diff % 3.6e6 / 6e4 | 0;
var secs = Math.round(diff % 6e4 / 1e3);
// Return formatted string
return sign + z(hours) + ' Hours ' + z(mins) + ' Min' + ':' + z(secs);// + ':' + z(secs)
}
$scope.calculateTime = function(s, idx) {
timeoutID = $timeout(function() {
$scope.items[idx]._timeLeft = $scope.timeUntil(s);
$scope.calculateTime(s, idx);
}, 1000);
};
EDIT
I understand the issues as mentioned below, what I am struggling with is how to register this corretly. As it could be up to 15+ separate times updating to a single tick that's where I am getting lost.
You are registering way more timeouts than you think. Every time angular renders your view, you register new timeout handlers. Add a counter of your callback and watch the count go:
$scope.called = 0;
$scope.calculateTime = function(s, idx) {
timeoutID = $timeout(function() {
$scope.items[idx]._timeLeft = $scope.timeUntil(s);
$scope.calculateTime(s, idx);
console.log(++$scope.called);
}, 1000);
};
See this plunk where I reproduced the bug: http://plnkr.co/edit/qJ4zDl6gc5C7Edg0T0gB. Just run it and watch the counter.
Why do you want to update your _timeLeft in the rendering cycle? Why not do this:
$scope.called = 0;
setInterval(function() {
angular.forEach($scope.items, function function_name(item) {
item._timeLeft = $scope.timeUntil(item._freeBusyTime);
});
console.log(++$scope.called);
$scope.$apply();
}, 1000);
See new plunk: http://plnkr.co/edit/rVJ6p4VXDQvt7rjT6eka
You are calling $scope.calculateTime recursively! And you are modifying the list of items during the ng-repeat, which also causes and endless loop.
How about this: http://plnkr.co/edit/0JqK96irV4ETdWZYxO3P?p=preview
changed the html to refer to a separate array that doesn't affect ng-repeat:
<td>in {{_timeLeft[$index]}}</td>
which is updated as follows:
$scope._timeLeft = [];
var intervalID = window.setInterval(function() {
for (var i=0; i<$scope.items.length; i++) {
$scope._timeLeft[i] = $scope.timeUntil($scope.items[i]._freeBusyTime);
}
$scope.$apply();
}, 1000);
Note that $scope.$apply() is required to let Angular know that '_timeLeft' has been modified, which updates all references to it.
I do not think you should call $timeout every view update.
Instead, you can count down time within your controller and let view show the timer.
http://plnkr.co/edit/OUVdJyllzmVmPC0FhqYF?p=preview

Categories

Resources