Passing Multiple Values - google-visualization

I have a visualization table that has an event listener on select.
The need: I want the user to be able to delete documents on the google drive without having to leave the webpage
The set up: I added a button so that when clicked, I get a confirm alert box that includes the value. Once I click OK, it runs the scripts from the client-side with an event handler. This works perfectly!
The problem: I can move one document at a time but if I need to move 20+ documents it gets really tedious to click rows one after the other. Is it possible to pass multiple values to the successhandler?
google.visualization.events.addListener(archiveChart.getChart(), 'select', function () {
$("#docArchive").on("click", function() {
var selection = archiveChart.getChart().getSelection();
var dt = archiveChart.getDataTable();
if (selection.length > 0) {
var item = selection[0];
var docurl = dt.getValue(item.row, 2);
var docname = dt.getValue(item.row, 1);
var folder = dt.getValue(item.row, 4);
if(confirm("Are you sure you want to archive " + docname + "?") == true) {
archiveChart.getChart().setSelection([]);
return google.script.run.withSuccessHandler(onSuccessArchive).withFailureHandler(function(err) {
alert(err);
}).archiveDoc(docurl,folder);
} else {
archiveChart.getChart().setSelection([]);
}
}});
})
I feel like I might need to add this:
for (var i = 0; i < selection.length; i++) {
var item = selection[i];
I'm struggling a little with understanding what I might need to change (still learning). Any help or guidance is appreciated!

recommend confirming once, for all documents
then loop the selection to archive each document
google.visualization.events.addListener(archiveChart.getChart(), 'select', function () {
$("#docArchive").on("click", function() {
var selection = archiveChart.getChart().getSelection();
var dt = archiveChart.getDataTable();
var docNames = selection.map(function (item) {
return dt.getValue(item.row, 1);
}).join('\n');
if (selection.length > 0) {
if(confirm("Are you sure you want to archive the following document(s)?\n" + docNames) == true) {
for (var i = 0; i < selection.length; i++) {
var item = selection[i];
var docurl = dt.getValue(item.row, 2);
var docname = dt.getValue(item.row, 1);
var folder = dt.getValue(item.row, 4);
return google.script.run.withSuccessHandler(onSuccessArchive).withFailureHandler(function(err) {
alert(err);
}).archiveDoc(docurl, folder);
}
}
archiveChart.getChart().setSelection([]);
}
});
});

Related

Problem with If/Then code with Google Sheet Script

Someone please help.
I am trying to create a simple script which records button presses in order.
I have:
function P1Buzzer() {
var sheet = SpreadsheetApp.getActiveSheet();
var row = 6;
var col = 1;
var Name = sheet.getRange(row, col).getValue();
var sheet = SpreadsheetApp.getActiveSheet();
var row = 192;
var col = 1;
var AnswerPosition = sheet.getRange(row, col).getValue();
if (AnswerPosition = 1) {
sheet.getRange(199, 1).setValue(Name);
var AnswerPosition = AnswerPosition + 1
sheet.getRange(192, 1).setValue(AnswerPosition);
}
if (AnswerPosition = 2) {
sheet.getRange(200, 1).setValue(Name);
var AnswerPosition = AnswerPosition + 1
sheet.getRange(192, 1).setValue(AnswerPosition);
}
}
The problem I have is that when I run the script it does both the commands, ignoring the if command.
Any ideas?
First, you are setting the value to 1 by using = instead of ==. Second, if it was 1, you add one to it and then check to see if it is 2. I'll bet it is!
if (AnswerPosition == 1) {
sheet.getRange(199, 1).setValue(Name);
var AnswerPosition = AnswerPosition + 1
sheet.getRange(192, 1).setValue(AnswerPosition);
} else if (AnswerPosition == 2) {
...

data-bind if statement on click function in knockout js

I need help on executing an one-liner if statement on my data-bind
this is the HTML
<div data-bind="text: Fields.FieldDescription, click:function() { $root.selectedToListRule.push(Fields.FieldCode());}" onmousedown="this.style.backgroundColor='#4BA6FF'"></div>
this is the js code
var RemovefieldCodeRule = function (parent, data) {
//console.log(parent.InitiatorFields(), data.selectedApproverFields());
var sel = selectedToListRule();
//console.log(sel);
for (var i = 0; i < sel.length; i++) {
var selCat = sel[i];
var result = data.selectedApproverFields.remove(function (item) {
return item.FieldCode() == selCat;
});
if (result && result.length > 0) {
//Add to WorkflowObject - InitiatorFields
var obj = dataservice.getEmptyObjects("WorkFlowObjectFields");
obj.done(function (data) {
var wfo = model.genericObject(data);
wfo.ID(result[0].ID);
wfo.WorkFlowObjects_ID(parent.ID());
wfo.FieldCode(result[0].FieldCode());
wfo.FieldDescription(result[0].FieldDescription());
parent.InitiatorFields.push(wfo);
});
}
}
selectedToListRule.removeAll();
parent.InitiatorFields.sort(function (left, right) { return left.FieldDescription() == right.FieldDescription() ? 0 : (left.FieldDescription() < right.FieldDescription() ? -1 : 1) });
data.selectedApproverFields.sort(function (left, right) { return left.FieldDescription() == right.FieldDescription() ? 0 : (left.FieldDescription() < right.FieldDescription() ? -1 : 1) });
}
on my data-bind, there's a click event wherein i will need to select from the dynamically generated div. what i want to happen is when the user clicks on a certain div (it gets selected) and if the user changes his mind to unselect the div he previously selected.
How can i can achieve this on one-liner if statement using knockout

Google Chart : How do I add select event handler to the pie chart?

I was able to generate pie chart successfully. However, when I was trying to add a select event listener to the pie chart, it is not triggering the function at all.
function handlePieChartResponse(response)
{
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var dataTable = response.getDataTable();
if (dataTable.getNumberOfRows() <= 0) {
document.getElementById('dummyTableRow').innerHTML = '<span>No data found</span>';
return;
}
var chartOptions = DEFAULT_PIE_CHART_OPTIONS;
//var chartOverallPmmLevelCalculated = new google.visualization.ChartWrapper({
// 'chartType': 'PieChart',
// 'containerId': 'chartOverallPmmLevelCalculatedHtml',
// options: chartOptions
//});
var chartRecentPmmLevelCalculated = new google.visualization.PieChart(document.getElementById('chartOverallPmmLevelCalculatedHtml'));
chartRecentPmmLevelCalculated.draw(dataTable, chartOptions);
google.visualization.events.addListener(chartRecentPmmLevelCalculated, 'ready', function () { drawPieChart(); });
google.visualization.events.addListener(chartRecentPmmLevelCalculated, 'select', function () { selectHandler(); });
function drawPieChart() {
var responseDataTable = response.getDataTable();
var chartDataTable = new google.visualization.DataTable();
chartDataTable.addColumn('string', 'LEVEL');
chartDataTable.addColumn('number', 'SCORE');
var chartDataTableRow = new Array();
var rowCounter;
var levelValue;
for (rowCounter = 0; rowCounter < responseDataTable.getNumberOfRows() ; rowCounter++) {
var seek = 0 * 1;
levelValue = responseDataTable.getValue(rowCounter, 0);
chartDataTableRow[seek++] = "LEVEL " + levelValue;
chartDataTableRow[seek++] = responseDataTable.getValue(rowCounter, 1);
chartDataTable.addRow(chartDataTableRow);
}
chartDataTable.sort([{ column: 1 }]);
chartOverallPmmLevelCalculated.setDataTable(chartDataTable);
chartOverallPmmLevelCalculated.draw();
}
handlePieChartResponse.drawPieChart = drawPieChart;
}
function selectHandler() {
alert("This alert triggered from pie chart");
var selectedItem = chartRecentPmmLevelCalculated.getSelection();
if (selectedItem) {
var levelSelected = chartOverallPmmLevelCalculated.getValue(selectedItem.row, 0);
alert(levelSelected);
}
}
I attached 2 images that include before and after the click. I was expecting alert message once select on pie chart slice. But no alert is present and the function call is not triggered.
problem has to do with scope
selectHandler is outside of the function handlePieChartResponse
so it can't be found
just move it inside handlePieChartResponse
then set the event, like so...
...addListener(chartRecentPmmLevelCalculated, 'select', selectHandler);

Applying color to rows in Sharepoint based on if an item is overdue

I'm using Sharepoint to develop an open issues list for my company that will automatically track if an issue is about to be due or overdue based on the color of the row. I have a way to override the default Sharepoint list features and edit the rows, but I think my date comparisons aren't functioning correctly. Here is my code so far:
SP.SOD.executeFunc("clienttemplates.js", "SPClientTemplates", function() {
SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
OnPostRender: function(ctx) {
var statusColors = {
'Almost Due' : '#FFFF00',
'Overdue' : '#FF0000',
};
var rows = ctx.ListData.Row;
for (var i=0;i<rows.length;i++)
{
var due = rows[i]["Due Date"];
var duedate = new Date(due);
var rowId = GenerateIIDForListItem(ctx, rows[i]);
var row = document.getElementById(rowId);
var today = new Date();
if(duedate <= today) {
var status = 'Overdue';
}
Else if (due.toDateString - today.toDateString <= 7 && due.toDateString - today.toDateString >= 0){
var status = 'Almost Due';
}
row.style.backgroundColor = statusColors[status];
}
}
});
});
I need the row to change red if the issue is past due and the issue to change yellow if the issue is due within one week.
Modified example:
SP.SOD.executeFunc("clienttemplates.js", "SPClientTemplates", function() {
SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
OnPostRender: function(ctx) {
var statusColors = {
'Almost Due' : '#FFFF00',
'Overdue' : '#FF0000',
};
var rows = ctx.ListData.Row;
for (var i=0;i<rows.length;i++)
{
var dueDate = new Date(rows[i]["DueDate"]);
var today = new Date();
var status = null;
if(dueDate <= today) {
status = 'Overdue';
}
else if (daysBetween(today,dueDate) <= 7 && daysBetween(today,dueDate) >= 0){
status = 'Almost Due';
}
if (status != null){
var rowId = GenerateIIDForListItem(ctx, rows[i]);
var row = document.getElementById(rowId);
row.style.backgroundColor = statusColors[status];
}
}
}
});
});
function daysBetween(startDate, endDate) {
var timeDiff = Math.abs(endDate.getTime() - startDate.getTime());
var diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24));
return diffDays;
}
The list of changes:
Fixed some typos like Else keyword
Introduced daysBetween function for getting dates difference in
days
due.toDateString - today.toDateString ...
I suspect that due.toDateString is returning a function definition. If you want your code to actually run that function, you'd want due.toDateString().
That said, since you're trying to do math with these dates, it's best to keep them as datetime objects or numbers rather than convert them to strings. Otherwise your subtraction is going to surprise you with NaN and your comparisons are going to be perpetually false.
If you subtract a date object from another date object in JavaScript, you'll get the difference between the dates in milliseconds. Convert that to days and you'll be good to go!

How can I calcuate wrapping text height in a famo.us surface?

Within famo.us, I want to place a variable-length wrapping title near the top then have images etc follow. All items must be their own surface as some have click events and animations but all the positioning must be super fast to calculate and place based on the text height and of course must avoid DOM access for the 60fps. This must happen for a series of mini-posts, streaming real time and for infinite scroll.
So far, I came up with an approach that works using an ascii character map to pixel width load off screen on init if isn't already in localStorage. It uses jquery to do the sizing for each character, then determine line height by checking a breaking word and the height of that box. After that I use this map for calculations on the fly so I don't touch DOM again. It seems to work fine but is completely dependent on knowing the style of font going to be used in a very specific way. For each new style, I would have to have a different mapping which sucks.
Is there another approach that is more built in to famo.us?
I'm answering my own question because its frankly been awhile, the new framework is going to come out June 22nd of this month (at the time of the this writing). Just going to put how I'm doing this currently which is the way I described above.
Here's the 0.3.5 way of Famou.us to do this.
This is in a file "utils/lines.js" I whipped up. Hack, yes. Works, yes.
define(function(require) {
'use strict';
var $ = require('jquery');
var cache = require('utils/cache');
function getLineInfo(id) {
var cacheKey = 'lineInfo_' + id;
var savedLineInfo = cache.get(cacheKey);
if (savedLineInfo)
return savedLineInfo;
var charStart = 32; // space
var charEnd = 126; // ~
var $charDump = $('<div>', { id: id });
$('body').append($charDump);
for (var i = charStart; i <= charEnd; i++)
$charDump.append($('<div>', { class: 'char', css: { top: (i-32) * 20 } }).html('&#' + i));
var charMap = {};
$charDump.find('.char').each(function() {
var $this = $(this);
var char = $this.text().charCodeAt(0);
var w = $this.width();
charMap[char] = w;
});
$charDump.html('<div class="line">abc<br>123<br>456</div>');
var lineHeight = $charDump.height() / 3;
$charDump.remove();
savedLineInfo = {
lineHeight: lineHeight,
charMap: charMap
};
cache.set(cacheKey, savedLineInfo);
return savedLineInfo;
}
function getLines(text, width, id, maxLines) {
var lineInfo = getLineInfo(id);
var cleaned = $.trim(text.replace(/\s+/gm, ' '));
var words = cleaned.split(' ');
var lines = 1;
var lineWidth = 0;
var spaceLength = lineInfo.charMap[32];
var allLines = '';
words.forEach(function(word) {
var wordLength = 0;
word.split('').forEach(function(char) {
var charLength = lineInfo.charMap[char.charCodeAt(0)];
if (!charLength)
charLength = spaceLength;
wordLength += charLength;
});
if (lineWidth + wordLength + spaceLength <= width) {
lineWidth += wordLength + spaceLength;
if (maxLines)
allLines += word + ' ';
}
else {
lineWidth = wordLength;
if (maxLines && lines <= maxLines)
allLines += word + ' ';
else if (maxLines)
return {text: allLines.substr(0, allLines.length - 3) + '...', lines: lines};
lines++;
}
});
if (maxLines)
return {text: allLines, lines: lines};
return lines;
}
function getTextHeight(text, width, id, maxLines) {
var lineInfo = getLineInfo(id);
var info;
if (maxLines) {
info = getLines(text, width, id, maxLines);
info.height = lineInfo.lineHeight * info.lines;
return info;
}
return lineInfo.lineHeight * getLines(text, width, id);
}
return {
getLines: getLines,
getLineInfo: getLineInfo,
getTextHeight: getTextHeight
};
});