/*! DO NOT EDIT steelcaseesm concatenated javascript 2018-07-11 */
/*
* App.js
*/
/**
* Javascript used for all pages
* @param {string[]} chart_ids the IDs of all charts on this page or null for all charts
* @param {string} scale '100' if line charts should be scaled from 0-100, or 'auto' if they should be scaled automatically
*/
function App(chart_ids, scale) {
var sessionFiltersValue = document.getElementById("selectedFilters").value;
sessionDateFrom = add_days(new Date(), -29);
sessionDateTo = new Date();
var hasSessionRegions = false;
var sessionRegions;
if (sessionFiltersValue) {
var sessionFilters = JSON.parse(sessionFiltersValue);
sessionDateFrom = new Date(sessionFilters.startDate);
sessionDateTo = new Date(sessionFilters.endDate);
if (sessionFilters.regions != null) {
hasSessionRegions = true;
sessionRegions = sessionFilters.regions;
}
}
var filter = {};
filter.startDate = dateFormat(sessionDateFrom, 'isoDate');
filter.endDate = dateFormat(sessionDateTo, 'isoDate');
if (hasSessionRegions) {
filter.regions = sessionRegions;
}
// Create and draw charts.
charts = new ChartCollection(chart_ids);
charts.update_filter(filter);
//
// All filters
//
// Open a filter menu
$('.filter-menu-button').click(function () {
// Position this and menu above overlay
var $menu = $(this).siblings('.filter-menu');
$menu.css('z-index', 6);
$(this).css('z-index', 6);
// Show menu and overlay
var $siblings = $(this).siblings();
$siblings.css('display', 'initial');
});
// Close a filter menu
$('.filter-overlay').click(function () {
// Close menu
var $menu = $(this).siblings('.filter-menu');
$menu.css('display', 'none');
$(this).css('display', 'none');
// Reset z-index
$(this).siblings().css('z-index', 'auto');
update_filter();
});
// Enable filter tabs
$('.filter-tab').click(function () {
var content_id = this.getAttribute('id') + '-content';
$(this).parent().siblings('.filter-content').hide();
$(this).parent().siblings('#' + content_id).show();
});
function update_filter() {
var filter = {};
filter.startDate = dateFormat($('#date-from').datepicker('getDate'), 'isoDate');
filter.endDate = dateFormat($('#date-to').datepicker('getDate'), 'isoDate');
// Do not add regions and departments if all are selected
if (!$('#filter-regions .ms-select-all').hasClass('selected')) {
filter.regions = $('#region-select').multipleSelect('getSelects');
}
charts.update_filter(filter);
}
//
// Date filter
//
// Prepare datepickers
var _getCurrentYear = new Date().getFullYear();
var _yearsRange = '2012:'+_getCurrentYear;
var _datePickerYearObject = {changeMonth: true, changeYear: true, yearRange: _yearsRange};
//Initialize
$('#date-from, #date-to').datepicker(_datePickerYearObject);
//Jive/Igloo data test alert
function jive_data_alert(get_dateText)
{
//Jive Data
var datepicker_date = dateFormat(get_dateText, 'longDate');
var jive_date = 2016;
if(datepicker_date.length)
{
_getYear = datepicker_date.split(' ');
if(_getYear)
{
if(parseInt(_getYear[2]) < 2017)
{
alert('You are about to view Jive data. Igloo data applies after 31/12/2016.');
}
}
}
}
// Enable 'single day' button
$('#single-day').change(function () {
var $to = $('#date-to');
if (this.checked) {
$to.datepicker('option', 'minDate', null);
$to.datepicker('setDate', $('#date-from').datepicker('getDate'));
$to.datepicker('option', 'disabled', true);
$to.addClass('disabled');
} else {
$to.datepicker('option', 'minDate', $('#date-from').datepicker('getDate'));
$to.datepicker('option', 'disabled', false);
$to.removeClass('disabled');
}
update_date_text($('#date-from').datepicker('getDate'), $('#date-to').datepicker('getDate'));
});
// End date should be == (start date) if single day selected, otherwise >= (start date)
$('#date-from').datepicker('option', 'onSelect', function (dateText, inst) {
if ($('#single-day')[0].checked) {
$('#date-to').datepicker('setDate', new Date(dateText));
} else {
$('#date-to').datepicker('option', 'minDate', new Date(dateText));
}
update_date_text($('#date-from').datepicker('getDate'), $('#date-to').datepicker('getDate'));
//alert user for jive/igloo
jive_data_alert(dateText);
});
$('#date-to').datepicker('option', 'onSelect', function (dateText, inst) {
update_date_text($('#date-from').datepicker('getDate'), $('#date-to').datepicker('getDate'));
//alert user for jive/igloo
jive_data_alert(dateText);
});
// Reflect selected dates in date filter button
function update_date_text(dateFrom, dateTo) {
// var from = $('#date-from').datepicker('getDate');
// var to = $('#date-to').datepicker('getDate');
var text = "";
text += dateFormat(dateFrom, 'longDate');
if (+dateTo != +dateFrom) {
text += " - " + dateFormat(dateTo, 'longDate');
}
$('#date-button .filter-text').text(text);
}
// Get a date which is offset from a given date by some number of days
function add_days(date, offset) {
var result = new Date(date);
result.setDate(result.getDate() + offset);
return result;
}
// Set the filter dates
function set_filter_dates(dateFrom, dateTo) {
$('#date-from').datepicker('setDate', dateFrom);
// Update single day checkbox
if (+dateFrom == +dateTo) {
$('#single-day').prop('checked', true).change();
} else {
$('#single-day').prop('checked', false).change();
}
$('#date-to').datepicker('setDate', dateTo);
update_date_text(dateFrom, dateTo);
}
function initialize_date_pickers()
{
var dateFrom = Date();
var dateTo = Date();
var sessionFiltersValue = document.getElementById("selectedFilters").value;
if (sessionFiltersValue) {
var sessionFilters = JSON.parse(sessionFiltersValue);
dateFrom = new Date(sessionFilters.startDate);
dateTo = new Date(sessionFilters.endDate);
set_filter_dates(dateFrom, dateTo);
if (sessionFilters.regions != null) {
var element = document.getElementById('region-select');
for (var i = 0; i < element.options.length; i++) {
element.options[i].selected = sessionFilters.regions.indexOf(element.options[i].value) >= 0;
}
update_region_text();
}
}
else {
dateFrom = add_days(new Date(), -29);
dateTo = new Date();
set_filter_dates(dateFrom, dateTo);
}
}
// Set the filter to the past n days, including today
function filter_past_n_days(n) {
var from = add_days(new Date(), 1 - n);
var to = new Date();
set_filter_dates(from, to);
}
$('#date-preset-today').click(function () {
filter_past_n_days(1);
});
$('#date-preset-yesterday').click(function () {
var date = add_days(new Date(), -1);
set_filter_dates(date, date);
});
$('#date-preset-past-7').click(function () {
filter_past_n_days(7);
});
$('#date-preset-past-30').click(function () {
filter_past_n_days(30);
});
$('#date-preset-past-90').click(function () {
filter_past_n_days(90);
});
$('#date-preset-past-365').click(function () {
filter_past_n_days(365);
});
$('#date-preset-month').click(function () {
var from = new Date();
from.setDate(1);
var to = new Date();
set_filter_dates(from, to);
});
$('#date-preset-quarter').click(function () {
var from = new Date();
var month = from.getMonth();
from.setMonth(month - month % 3);
from.setDate(1);
var to = new Date();
set_filter_dates(from, to);
});
$('#date-preset-year').click(function () {
var from = new Date();
from.setMonth(0);
from.setDate(1);
var to = new Date();
set_filter_dates(from, to);
});
// Initialize dates to past week
//filter_past_n_days(30)
initialize_date_pickers()
//
// Region filter
//
$('#region-select').multipleSelect({
allSelected: 'All regions',
isOpen: true,
keepOpen: true,
width: '100%',
onClick: update_region_text,
onCheckAll: update_region_text
});
// Reflect selected regions in region filter button
function update_region_text() {
//var text = $('#filter-regions .multiple-select-text').text();
var text = $('#filter-regions option:selected').toArray().map(item => item.text).join();
$('#region-button .filter-text').text(text = '' ? 'All regions' : text);
}
//
// Line chart scale option
//
// Scale can be 0-100% or 0-auto
var scale_options = {
'100': {
html: 'Line chart scale: 0-100',
val: '100',
title: 'Charts showing percentages will be scaled from 0-100%.'
},
'auto': {
html: 'Line chart scale: auto',
val: 'auto',
title: 'Charts showing percentages will be scaled automatically.'
}
};
var $scale = $('#option-line-chart-scale');
// Set the scale to the given option
function set_scale(option) {
$scale.html(option.html);
$scale.val(option.val);
$scale.attr('title', option.title);
}
// Toggle the scale to the other option
function toggle_scale() {
if ($scale.val() === 'auto') {
set_scale(scale_options['100']);
} else {
set_scale(scale_options['auto']);
}
charts.redraw_all();
}
$scale.click(toggle_scale);
set_scale(scale_options[scale])
}
/*
* Dashboard.js
*/
/**
* Javascript for all pages except login and report
* @param {string[]} chart_ids the IDs of all charts on this page or null for all charts
*/
function Dashboard(chart_ids) {
new App(chart_ids, 'auto');
// Resize charts when window is finished resizing
var resizeTimer;
window.onresize = (function () {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function () {
charts.resize_all();
}, 25);
});
}
/*
* Report.js
*/
/**
* Javascript for the report page
*/
function Report() {
new App(null, '100');
// Fix size of container.
$('.container').css('width', '1070px');
// Properly size all charts.
$('.report-chart').each(function (index) {
var size = charts.charts[$(this).attr('id')].size;
$(this).parent().parent().attr('data-sizex', size.x);
$(this).parent().parent().attr('data-sizey', size.y);
});
init();
}
// Start gridster and install button listeners.
function init() {
// Activate gridster.
gridster = $(".gridster > ul").gridster({
widget_margins: [20, 20],
widget_base_dimensions: [155, 70],
min_cols: 6,
max_cols: 6,
resize: {
enabled: true,
max_size: [6, 12],
resize: function (e, ui, $widget) {
resize(this.$resized_widget);
},
stop: function (e, ui, $widget) {
resize(this.$resized_widget);
}
}
}).data('gridster');
install_remove_listeners();
// Add listener for text box button
$('#insert-text-box').click(function () {
gridster.add_widget('
' +
'
' +
'' +
'
' +
'' +
'
', 2, 1);
install_remove_listeners();
});
// Add listener for remove-all button
$('#remove-all').click(function () {
$('.gridster li').each(function (index) {
gridster.remove_widget($(this));
});
$.ajax({
url: '/Report/RemoveAll' + name,
method: 'POST',
error: function (jqXHR, textStatus, errorThrown) {
alert('Failed to remove all charts from the report:\n' + jqXHR.status + ": " + jqXHR.responseText);
}
});
});
// Add listener for print button
$('#print-report').click(function () {
var html = document.body.innerHTML;
document.body.innerHTML = $('#report').html();
charts.redraw_all();
window.print();
document.body.innerHTML = html;
charts.redraw_all();
init();
});
}
// Update a widget on resize
function resize(widget) {
// Draw chart if necessary
charts.resize(widget.find('[id^=chart]').attr('id'));
// Reorient label of doughnut chart
var doughnut_chart_div = widget.find('[id^=chart][label]');
if (widget.attr('data-sizey') > widget.attr('data-sizex') * 2) {
doughnut_chart_div.attr('label', 'bottom');
} else {
doughnut_chart_div.attr('label', 'right');
}
}
// Add listener for remove buttons
function install_remove_listeners() {
$('.gs-remove').click(function () {
gridster.remove_widget($(this).parent());
var name = $(this).siblings('.box').find('.report-chart').attr('id');
$.ajax({
url: '/Report/RemoveFromReport/?Name=' + name,
method: 'POST',
error: function (jqXHR, textStatus, errorThrown) {
alert('Failed to remove chart from the report:\n' + jqXHR.status + ": " + jqXHR.responseText);
}
});
});
}
/*
* BaseChart.js
*/
BaseChart = {
// Number of API calls made by this chart which have not yet returned a response
api_calls: 0,
// Add and enable "Add to report" button if specified
add_button: function (container) {
if (container.attr('add-button') === 'true') {
// Ensure there is a button
var $parent = container.parent();
if ($parent.find('.add-to-report').length === 0) {
var html =
'';
$parent.append(html);
}
// Use ajax to add chart to the report on click
var that = this;
$parent.find('.add-to-report').click(function () {
$.ajax({
url: '/Report/AddToReport/?Name=' + that.id,
method: 'POST',
error: function (jqXHR, textStatus, errorThrown) {
alert('Failed to add chart to the report:\n' + jqXHR.status + ": " + jqXHR.responseText);
}
});
// Hide add icon briefly
$(this).find('.add').css('opacity', '0');
// Display and animate success icon briefly
$(this).find('.added')
.css('opacity', '1')
.animate({
opacity: '0',
'background-size': '100%'
}, 400, 'linear', function () {
$(this).parent().children().css({
'opacity': '',
'background-size': ''
});
});
});
}
},
// Draw spinner while waiting for updated data
spin: function () {
var container = $('#' + this.id);
var html =
'
' + this.title + '...
';
container.html(html);
},
// Update the data behind this chart and redraw it.
update: function () {
// Do not update charts that aren't on this page.
if ($('#' + this.id).length === 0) {
return;
}
var that = this;
var settings = {
"url": "/api/" + that.id,
"method": "GET",
success: function (response) {
that.api_calls--;
// Only update data when we have received a response from the most recent api call
if (that.api_calls == 0) {
that.set_data(JSON.parse(response));
that.draw();
}
},
error: function (jqXHR, textStatus, errorThrown) {
that.api_calls--;
console.log(jqXHR.status + ": " + jqXHR.responseText);
}
};
$.ajax(settings);
this.api_calls++;
},
set_data: function (data) {
this.data = data;
}
}
BaseChart.colorDict = {
// misc
'misc': '#e11731',
// categories
'find': '#a8f1c7',
'ask': '#4f5352',
'share': '#3db4ad',
// find activity types
'BOOKMARK': '#f6958e',
//'VIEW': '#F6B48E',
'SEARCH': '#F6B48E',
'TAG': '#F6E38E',
//'RESOLVED': '#BBE9F6',
//'DOWNLOADATTACHMENT': '#DFB6F6',
'DOWNLOAD': '#BF9ED2',
//'BOOKMARKUPDATE': '#EB9569',
'FOLLOW': '#d1d3d3',
'CREATEOUTCOME': '#aeb1b0',
'ENDORSE': '#BBE9F6',
// ask activity types
//'SEND': '#DAD5EA',
//'SENT': '#B8ECF2',
//'RSVP': '#3A9998',
'CREATE_QUESTION': '#DAD5EA',
'CREATE_POLL': '#B8ECF2',
'CREATE_THREAD': '#3A9998',
'CREATE_MESSAGE': '#256261',
// share activity types
//'ACCLAIM': '#FF8685',
'VOTE': '#EDB699',
//'UPDATE': '#EBD3A9',
'UPDATECONTENT': '#EBD3A9',
'SHARE': '#154e6b',
//'RATE': '#99AFB8',
//'MOVE': '#3282A6',
'MENTION': '#077db6',
'LIKE': '#cceaf8',
//'FOLLOW': '#d1d3d3',
'ADDATTACHMENT': '#1c3745',
'COMMENT': '#99d5f1',
//'COMMENTUPDATE': '#3baee4',
'CREATE': '#66bfe9',
//'CREATEOUTCOME': '#aeb1b0',
//'UPDATEOUTCOME': '#0e6690',
'UPDATEPROFILE': '#aeb1b0',
// types of sentiment
'positive': '#fadee2',
'negative': '#e11731',
'neutral': '#b1b4b5',
// types of boundary spanning
'Representation': '#f5eedb',
'Coordination': '#a6a336',
'Scouting': '#e0dd7d',
'Other': '#b1b4b5',
// types of creativity
'Combination-expansion': '#cceaf8',
'Reframing': '#0095db'
};
/*
* ChartCollection.js
*/
google.charts.load('current', { 'packages': ['corechart'] });
Chart.defaults.global.animation.duration = 0;
/**
* A ChartCollection object tracks, draws, and updates all of the charts on a page.
* @param {string[]} chart_ids the IDs of all charts on this page or null for all charts
* eg. ['doughnut_find', 'doughnut_share', 'line_percent_finding']
*/
function ChartCollection(chart_ids) {
// Order in which charts should request new data - fastest charts are first
this.update_order = [
"doughnut_ask",
"doughnut_share",
"text_sentiment",
"text_polls",
"text_total_activities",
"doughnut_find",
"doughnut_find_ask_share",
"doughnut_all_activities",
"map_find",
"map_ask",
"map_share",
"line_sentiment",
"line_boundary_spanning",
"line_creativity",
"doughnut_conversations",
"doughnut_boundary_spanning",
"doughnut_creativity",
"text_boundary_spanning",
"text_creativity",
"pb_txt_creativity_today",
"pb_txt_creativity_week",
"line_percent_sharing",
"line_percent_asking",
"line_percent_finding",
"text_active_users",
"line_active_users_per_day"
]
// If no chart ids specified, use all possible.
if (!chart_ids) {
chart_ids = [];
for (id in ChartFactories) {
chart_ids.push(id);
}
}
// Create dictionary of charts
this.charts = {};
for (var i = 0; i < chart_ids.length; i++) {
var chart_id = chart_ids[i];
var factory = ChartFactories[chart_id];
this.charts[chart_id] = new factory();
}
// Create add all button
var container = $('#add-all-container');
if (container.length !== 0) {
// Build JSON list of chart ids
var chart_list = [];
for (var chart_id in this.charts) {
chart_list.push(chart_id);
}
var names = JSON.stringify(chart_list);
html = '';
container.append(html);
container.find('#add-all').click(function () {
$.ajax({
url: '/Report/AddAll/?Name=' + names,
method: 'POST',
error: function (jqXHR, textStatus, errorThrown) {
alert('Failed to add all charts to the report:\n' + jqXHR.status + ": " + jqXHR.responseText);
}
});
});
}
// Resize a specified chart if necessary
this.resize = function (id) {
if (id in this.charts && this.charts[id].resize) {
this.charts[id].resize();
}
};
// Resize all charts where necessary
this.resize_all = function () {
for (var id in this.charts) {
if (this.charts[id].resize) {
this.charts[id].resize();
}
}
};
// Draw all charts where necessary (used after setting html on print)
this.redraw_all = function () {
for (var id in this.charts) {
this.charts[id].draw();
}
};
// Send filter data to the server and update charts when done
this.update_filter = function (filter) {
// Build form data
var form = new FormData();
form.append('filterString', JSON.stringify(filter));
var that = this;
var settings = {
url: '/api',
method: 'POST',
processData: false,
contentType: false,
mimeType: 'multipart/form-data',
data: form,
success: function (response) {
that.update_charts();
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR.status + ": " + jqXHR.responseText);
}
}
$.ajax(settings);
};
// Update all of the charts, from fastest to slowest
this.update_charts = function () {
for (id in this.charts) {
this.charts[id].spin();
}
var that = this;
var i = 0;
function update_next() {
var id = that.update_order[i];
if (id in that.charts) {
that.charts[id].update();
}
i++;
if (i < that.update_order.length) {
setTimeout(update_next, 100);
}
}
update_next();
}
}
/*
* ChartFactories.js
*/
// Factories functions to create each type of chart used on the site
ChartFactories = {
//---------- doughnut charts ----------//
doughnut_find_ask_share: function () {
return new DoughnutChart(
'doughnut_find_ask_share',
'Find/Ask/Share'
);
},
doughnut_all_activities: function () {
return new DoughnutChart(
'doughnut_all_activities',
'All Activities'
);
},
doughnut_find: function () {
return new DoughnutChart(
'doughnut_find',
'Finding Activities'
);
},
doughnut_ask: function () {
return new DoughnutChart(
'doughnut_ask',
'Asking Activities'
);
},
doughnut_share: function () {
return new DoughnutChart(
'doughnut_share',
'Sharing Activities'
);
},
doughnut_conversations: function () {
return new DoughnutChart(
'doughnut_conversations',
'Types of Conversations'
);
},
doughnut_boundary_spanning: function () {
return new DoughnutChart(
'doughnut_boundary_spanning',
'Types of Boundary Spanning'
);
},
doughnut_creativity: function () {
return new DoughnutChart(
'doughnut_creativity',
'Types of Creative Dialog'
);
},
//---------- line charts ----------//
line_active_users_per_day: function () {
return new LineChart(
'line_active_users_per_day',
'Active Users Per Day',
'Active Users',
false,
false,
[BaseChart.colorDict['misc']]
);
},
line_percent_finding: function () {
return new LineChart(
'line_percent_finding',
'Finding as a proportion of all activities',
'Percent Finding',
false,
true,
[BaseChart.colorDict['find']]
);
},
line_percent_asking: function () {
return new LineChart(
'line_percent_asking',
'Asking as a proportion of all activities',
'Percent Asking',
false,
true,
[BaseChart.colorDict['ask']]
);
},
line_percent_sharing: function () {
return new LineChart(
'line_percent_sharing',
'Sharing as a proportion of all activities',
'Percent Sharing',
false,
true,
[BaseChart.colorDict['share']]
);
},
line_sentiment: function () {
return new LineChart(
'line_sentiment',
'Sentiment over time',
'Posts',
true,
false,
['#e11731', '#b1b4b5', '#fadee2']
);
},
line_boundary_spanning: function () {
return new LineChart(
'line_boundary_spanning',
'Boundary Spanning over time',
'Posts',
true,
false,
['#e0dd7d', '#a6a336', '#f5eedb', '#b1b4b5']
);
},
line_creativity: function () {
return new LineChart(
'line_creativity',
'Creative posts over time',
'Posts',
true,
false,
['#66bfe9', '#0095db', '#b1b4b5']
);
},
//---------- text charts ----------//
text_active_users: function () {
return new TextChart(
'text_active_users',
'Active Users',
false,
"text-chart-text",
'/images/active-users.svg'
)
},
text_total_activities: function () {
return new TextChart(
'text_total_activities',
'Total Activities',
false,
"text-chart-text",
'/images/total-activities.svg'
);
},
text_sentiment: function () {
return new TextChart(
'text_sentiment',
'Sentiment',
false,
"text-chart-text",
'/images/sentiment.svg'
);
},
text_polls: function () {
return new TextChart(
'text_polls',
'Polls and Responses',
false,
"text-chart-text",
'/images/polls-responses.svg'
);
},
text_boundary_spanning: function () {
return new TextChart(
'text_boundary_spanning',
'Boundary Spanning',
false,
"text-chart-text",
null
);
},
text_creativity: function () {
return new TextChart(
'text_creativity',
'Creativity',
false,
"text-chart-text",
null
);
},
pb_txt_creativity_today: function () {
return new TextChart(
'pb_txt_creativity_today',
'Today',
true,
"text-collaborate-ideas",
null
);
},
pb_txt_creativity_week: function () {
return new TextChart(
'pb_txt_creativity_week',
'This Week',
true,
"text-collaborate-ideas",
null
);
},
//---------- map charts ----------//
map_find: function () {
return new MapChart(
'map_find',
'Finding activities by region',
'finding',
{
'All Regions': '#e8e8e8',
'Americas': '#4f5352',
'Europe-ME-Africa': '#aeb1b0',
'Asia-Pacific': '#313535'
}
);
},
map_ask: function () {
return new MapChart(
'map_ask',
'Asking activities by region',
'asking',
{
'All Regions': '#f5eedb',
'Americas': '#8f8900',
'Europe-ME-Africa': '#e0dd7d',
'Asia-Pacific': '#615e15'
}
);
},
map_share: function () {
return new MapChart(
'map_share',
'Sharing activities by region',
'sharing',
{
'All Regions': '#cceaf8',
'Americas': '#077db6',
'Europe-ME-Africa': '#33aae2',
'Asia-Pacific': '#0e6690'
}
);
}
};
/*
* DoughnutChart.js
*/
/**
* A DoughnutChart object draws and updates a single doughnut chart.
* @param {string} id Identifier string used as the id of a div that should contain this chart.
* @param {string} title Descriptive title to be displayed above this chart.
*/
function DoughnutChart(id, title) {
this.id = id;
this.title = title;
}
// Inherit from BaseChart
Object.assign(DoughnutChart.prototype, BaseChart);
DoughnutChart.prototype.size = { x: 2, y: 3 };
DoughnutChart.prototype.draw = function () {
// Prepare the container for this chart
var container = $('#' + this.id);
if (container.length === 0) {
return;
}
// Display message if empty data set
if (this.data == null || this.data.counts.length == 0 || this.data.counts[0] == 0 && this.data.counts[1] == 0 && this.data.counts[2] == 0) {
var html = '
' + this.title + '
' +
'
No activities to display
';
container.html(html);
return;
}
var html = '
' + this.title + '
' +
'
' +
'' +
'
' +
'
' +
'
';
container.html(html);
this.add_button(container);
var that = this;
// Draw chart
var definition = {
type: 'doughnut',
data: {
labels: this.data['labels'],
datasets: [
{
data: this.data['counts'],
backgroundColor: this.colors,
borderColor: '#ffffff',
borderWidth: 2
}
]
},
options: {
legend: {
display: false
},
tooltips: {
callbacks: {
label: function (tooltipItem, data) {
return that.tooltips[tooltipItem.index];
}
}
}
}
}
var chart_display = new Chart(container.find('canvas')[0].getContext('2d'), definition);
// Draw legend
var legend = '';
var labels = chart_display.legend.legendItems;
for (var i = 0; i < labels.length; i++) {
var label = labels[i];
legend += '
' +
' ' +
label.text +
'
';
}
$('#' + this.id + ' .doughnut-chart-legend').html(legend);
};
DoughnutChart.prototype.set_data = function (data) {
this.data = data;
// Build array of colors for each actiontype.
var labels = data['labels'];
this.colors = [];
for (var i = 0; i < labels.length; i++) {
this.colors.push(this.colorDict[labels[i]]);
}
// Calculate sum of data
var sum = 0;
for (var i = 0; i < data.labels.length; i++) {
sum += data.counts[i];
}
// Create tooltip text for each element.
this.tooltips = [];
for (var i = 0; i < data.labels.length; i++) {
var label = data.labels[i];
var count = data.counts[i];
var percent = (100 * count / sum).toFixed(2);
this.tooltips.push(label + ': ' + count + ' (' + percent + '%)');
}
};
/*
* LineChart.js
*/
/**
* A LineChart object draws and updates a single line chart.
* @param {string} id Identifier string used as the id of a div that should contain this chart.
* @param {string} title Descriptive title to be displayed above this chart.
* @param {string} axis Text for the y-axis of this chart.
* @param {bool} area If true, this will display as a stacked area chart instead of a line chart.
* @param {bool} percent If true, scale will be capped at 100 when the global line chart scale is toggled to 100.
* @param {string[]} colors colors for each data series on this chart.
*/
function LineChart(id, title, axis, area, percent, colors) {
this.id = id;
this.title = title;
this.axis = axis;
this.area = area;
this.percent = percent;
// Format color data properly for line chart
this.series = [];
for (var i = 0; i < colors.length; i++) {
this.series.push({
color: colors[i]
});
}
}
// Inherit from BaseChart
Object.assign(LineChart.prototype, BaseChart);
LineChart.prototype.size = { x: 4, y: 4 };
LineChart.prototype.draw = function () {
// Prepare the container for this chart
var container = $('#' + this.id);
if (container.length === 0) {
return;
}
// Display message if empty data set
if (this.data == null || this.data.length == 1) {
var html = '
' + this.title + '
' +
'
No data
';
container.html(html);
return;
}
container.css('width', '100%');
container.css('height', '100%');
var html = '';
container.html(html);
this.add_button(container);
var $div = container.find('div');
$div.css('width', '100%');
$div.css('height', '100%');
var div = $div[0];
// Draw chart
var chart_display;
if (this.area) {
chart_display = new google.visualization.AreaChart(div);
} else {
chart_display = new google.visualization.LineChart(div);
}
var options = {
title: this.title,
titleTextStyle: {
fontSize: 16,
bold: true
},
legend: {},
pointSize: 6,
fontName: 'Arial',
series: this.series,
hAxis: {
title: 'Date',
titleTextStyle: {
fontSize: 14,
italic: false
},
},
vAxis: {
title: this.axis,
titleTextStyle: {
fontSize: 14,
italic: false
},
minValue: 0,
}
};
if ($('#option-line-chart-scale').val() == '100' && this.percent) {
options.vAxis.maxValue = 100;
}
if (this.area) {
options.isStacked = true;
options.areaOpacity = .1;
options.legend.position = 'top';
} else {
options.legend.position = 'none';
}
var data = google.visualization.arrayToDataTable(this.data);
chart_display.draw(data, options);
// Used to quickly redraw the chart during resizing
this.resize = function () {
chart_display.draw(data, options);
}
};
/*
* MapChart.js
*/
/**
* A MapChart object draws and updates a single map chart.
* @param {string} id Identifier string used as the id of a div that should contain this chart.
* @param {string} title Descriptive title to be displayed above this chart.
* @param {string} type The type of activity for this map ('finding', 'asking', or 'sharing')
* @param {object} color_scheme colors for each region, including 'All Regions'
*/
function MapChart(id, title, type, color_scheme) {
this.id = id;
this.title = title;
this.type = type;
this.color_scheme = color_scheme;
this.selected = null;
}
// Inherit from BaseChart
Object.assign(MapChart.prototype, BaseChart);
MapChart.prototype.size = { x: 4, y: 5 };
MapChart.prototype.draw = function () {
// Find the container for this chart
var container = $('#' + this.id);
if (container.length === 0) {
return;
}
// Remove existing map and map tip
if (this.map) {
this.map.remove();
$('.jvectormap-tip').remove();
}
// Prepare div html
var html =
'
' +
'
' + this.title + '
' +
'' +
'
' +
'
';
var region_list = ['All Regions', 'Americas', 'Europe-ME-Africa', 'Asia-Pacific'];
for (var i = 0; i < region_list.length; i++) {
var region = region_list[i];
var percent = this.data[region].percent;
html +=
'
' + region + '
' +
'
' +
'' +
'
' +
'
' + percent.toFixed(2) + '% ' + this.type + '
' +
' ';
}
html +=
'
';
container.html(html);
// Draw map
this.map = $('#' + this.id + ' .map-container').vectorMap({
map: 'world_mill',
backgroundColor: 'transparent',
zoomOnScroll: false,
zoomButtons: false,
regionStyle: {
initial: {
'stroke-width': '2px',
'stroke': null
},
hover: {
'fill-opacity': 1 // Don't dim country on hover
}
}
});
// Add region class to each country
for (var region in this.regions) {
for (var i = 0; i < this.regions[region].length; i++) {
$('path[data-code="' + this.regions[region][i] + '"]').attr('region', region);
}
}
// Set country colors
this.deselect_all();
var that = this;
$('#' + this.id + ' path').click(function () {
var region = $(this).attr('region');
that.toggle_select(region);
});
}
// Deselect regions and set all to their correct colors.
MapChart.prototype.deselect_all = function () {
for (var region in this.regions) {
var color = this.color_scheme[region];
$('#' + this.id + ' path[region="' + region + '"]').css('fill', color).attr('stroke', color);
}
this.selected = null;
// Remove tooltips
var container = $('#' + this.id + ' .map-container');
container.find('.map-tooltip').remove();
}
// Select a region and give it visual emphasis.
MapChart.prototype.select_region = function (region) {
// Gray out all regions
var neutral_color = this.color_scheme['All Regions'];
$('#' + this.id + ' path').css('fill', neutral_color).attr('stroke', neutral_color);
this.selected = region;
// Give this region the correct color
var region_color = this.color_scheme[region];
$('#' + this.id + ' path[region="' + region + '"]').css('fill', region_color).attr('stroke', region_color);
// Remove tooltips
var container = $('#' + this.id + ' .map-container');
container.find('.map-tooltip').remove();
// Create current tooltip
var left = this.tooltip_positions[region];
var count = this.data[region].count;
var percent = this.data[region].percent;
//var percent = Math.floor(100 * count / this.data["All Regions"].count);
var tooltip_html =
'
' +
'
' + region + ' | ' + count + '
' +
'
(' + percent.toFixed(2) + '% of all ' + this.type + ')
' +
'
';
container.append(tooltip_html);
}
// Select the given region, or deselect it if it is already selected.
MapChart.prototype.toggle_select = function (region) {
if (this.selected === region) {
this.deselect_all();
} else {
this.select_region(region);
}
}
// Divide country codes into three regions
MapChart.prototype.regions = {
'Americas': ['AG', 'AI', 'AN', 'AR', 'AW', 'BB', 'BL', 'BM', 'BO', 'BQ', 'BR', 'BS', 'BZ', 'CA', 'CL', 'CO', 'CR',
'CU', 'CW', 'DM', 'DO', 'EC', 'FK', 'GD', 'GF', 'GL', 'GP', 'GT', 'GY', 'HN', 'HT', 'JM', 'KN', 'KY', 'LC',
'MF', 'MQ', 'MS', 'MX', 'NI', 'PA', 'PE', 'PM', 'PR', 'PY', 'SR', 'SV', 'SX', 'TC', 'TT', 'UM', 'US', 'UY',
'VC', 'VE', 'VG', 'VI'],
'Europe-ME-Africa': ['AD', 'AE', 'AL', 'AM', 'AO', 'AT', 'AX', 'AZ', 'BA', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ',
'BW', 'BY', 'CD', 'CF', 'CG', 'CH', 'CI', 'CM', 'CV', 'CY', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DZ', 'EE', 'EG',
'EH', 'ER', 'ES', 'ET', 'FI', 'FO', 'FR', 'GA', 'GB', 'GE', 'GG', 'GH', 'GI', 'GM', 'GN', 'GQ', 'GR', 'GW',
'HR', 'HU', 'IE', 'IL', 'IM', 'IQ', 'IR', 'IS', 'IT', 'JE', 'JO', 'KE', 'KM', 'KW', 'KZ', 'LB', 'LI', 'LR',
'LS', 'LT', 'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'ME', 'MG', 'MK', 'ML', 'MR', 'MT', 'MU', 'MW', 'MZ', 'NA',
'NE', 'NG', 'NL', 'NO', 'OM', 'PL', 'PS', 'PT', 'QA', 'RE', 'RO', 'RS', 'RU', 'RW', 'SA', 'SC', 'SD', 'SE',
'SH', 'SI', 'SJ', 'SK', 'SL', 'SM', 'SN', 'SO', 'SS', 'ST', 'SY', 'SZ', 'TD', 'TG', 'TN', 'TR', 'TR', 'TZ',
'UA', 'UG', 'VA', 'XE', 'XS', 'YE', 'YT', 'ZA', 'ZM', 'ZW'],
'Asia-Pacific': ['AF', 'AM', 'AS', 'AU', 'AZ', 'BD', 'BN', 'BT', 'CC', 'CK', 'CN', 'CX', 'FJ', 'FM', 'GE', 'GU',
'HK', 'ID', 'IN', 'IO', 'JP', 'KG', 'KH', 'KI', 'KP', 'KR', 'KZ', 'LA', 'LK', 'MH', 'MM', 'MN', 'MO', 'MP',
'MV', 'MY', 'NC', 'NF', 'NP', 'NR', 'NU', 'NZ', 'PF', 'PG', 'PH', 'PK', 'PN', 'PW', 'RU', 'SB', 'SG', 'TH',
'TJ', 'TK', 'TL', 'TM', 'TO', 'TV', 'TW', 'UM', 'UZ', 'VN', 'VU', 'WF', 'WS', 'XD']
}
MapChart.prototype.tooltip_positions = {
'Americas': '19%',
'Europe-ME-Africa': '49%',
'Asia-Pacific': '70%'
}
/*
* TextChart.js
*/
/**
* A TextChart object draws and updates a text box with a small piece of data.
* @param {string} id Identifier string used as the id of a div that should contain this chart.
* @param {string} title Title to display before data
* @param {boolean} titleTop Title before or after value
* @param {string} className Class for text
* @param {string} src Source file for icon
*/
function TextChart(id, title, titleTop, className, src) {
this.id = id;
this.title = title;
this.titleTop = titleTop;
this.className = className;
this.src = src
}
// Inherit from BaseChart
Object.assign(TextChart.prototype, BaseChart);
TextChart.prototype.size = { x: 2, y: 1 };
TextChart.prototype.draw = function () {
// Find the container for this chart
var container = $('#' + this.id);
if (container.length === 0) {
return;
}
var html =
''
if (this.titleTop) {
html = html + '