', { "class": 'glyphicon glyphicon-remove' })
.click(function() { self.removeBenchmark(doc) })
.appendTo(item)
if (this.isAuthor() || (doc.sessionBenchmark && !doc.sessionOverride))
removeButton.show()
else
removeButton.hide()
return item
},
/* Remove item for this doc if its already rendered */
removeItem: function(doc) {
this.benchmarkSearchContainer.find('.benchmarkitem[uid="'+ doc.uid +'"]').remove();
},
reload: function(){
this.activeBenchmarks.empty()
this.mostPlottedBenchmarks.empty()
this.recentBenchmarks.empty()
this.removeAllFromChart();
// delete the array
this.activeBenchmarkState.length = 0;
this.fetchPinsAndPlots()
},
/* Checks if the given period is plottable (it is compatible with the chart period type) */
addPlottablePeriodInfo: function(doc,periodType){
// TODO: might not need to be an option passed in, and could be accessed
// this.options.chartWrapper.getPeriods()
// if getCurrentPeriodType isnt defined we cant do much here, all charts will be plottable
var currentPeriodType;
if (!this.options.getCurrentPeriodType)
return true
// either a passed in periodType, or the actual current in the chart
if (periodType === false || periodType === null || periodType === undefined){
currentPeriodType = this.options.getCurrentPeriodType()
} else {
currentPeriodType = periodType
}
// trefisData is json stored as a string in solr, here we parse the string back to json
var itemChartData = $.parseJSON(doc.trefisData).chartData[0]
// getCountMap returns the amt of plottable poitns for a series of data
var itemPeriodTypes = tf.period.getCountMap(itemChartData.array)
// metaData is some additional information about the data in relation to a period
// whether it is plottable in that period, the label, the counts
var periodPlottingData = {
'isPlottable': itemPeriodTypes[currentPeriodType] > 0,
'label': tf.period.typeAbbrevs[currentPeriodType],
'counts': itemPeriodTypes[currentPeriodType],
'periodDataMap':itemPeriodTypes.toString()
};
/*
plottablePeriodData {
isPlottable: boolean // plottable in period type (ann/quarterly)
label: string // ann / quarterly
counts: int // amount of data points in the period type
*/
return periodPlottingData;
},
/**
* Checks if the benchmark has ANY plottable period types.
* in the advanced ui, a benchmark that has a different period type than the current
* chart's period type, it will switch the chart to that period
* @param doc
* @returns {*}
*/
addAllPlottablePeriodInfo: function(doc){
// if getCurrentPeriodType isnt defined we cant do much here, all charts will be plottable
if (!this.options.getCurrentPeriodType)
return true
var self = this;
var chartPeriodTypes = this.options.chartWrapper.getPeriods();
var periods = [];
// data here is some additional 'plottable' info
// data.periods will be an array of objects representing a period abbreviation, and a boolean:
// ie: 'ann':true
// if any match true - data.plottable will be set as true
var series = {};
series.isPlottable = false;
// If it's reducted then it's not plottable
if (doc.reducted !== true) {
chartPeriodTypes.forEach(function(period){
var periodMetaData = this.addPlottablePeriodInfo(doc,period);
periods.push(periodMetaData);
if(periodMetaData.isPlottable) {
series.isPlottable = true;
if(period == self.options.getCurrentPeriodType()) {
series.hasCurrentPlottable = true;
}
}
},this);
}
series.periods = periods;
return series;
},
isItemDisplayed: function(doc) {
var isDisplayed = false;
// skip if this item is actually already displayed
if(this.isInActiveBenchmarkStateList(doc.uid)){
isDisplayed = true;
}
// TODO: we used to check if the item could be plotted in the current chart's plottype
// however, this could lead to what would appear to a user as a bug. IF i add
// someting in the advanced ui, where it can be of any available types
// and then close the advanced, switch to another period, then refresh the page
// it wouldn't appear in the benchmarks, unless you open the advanced ui again.
return isDisplayed;
},
/* * * * * * * * * * *
* Server Benchmarks *
* * * * * * * * * * */
storeServerBenchmarks: function(docs) {
if (!this.serverBenchmarks[this.forecastId()])
this.serverBenchmarks[this.forecastId()] = {}
docs.forEach(function(doc) {
this.serverBenchmarks[this.forecastId()][doc.uid] = doc
}, this)
},
getServerBenchmark: function(doc) {
if (!this.serverBenchmarks[this.forecastId()])
return undefined
return this.serverBenchmarks[this.forecastId()][doc.uid]
},
/* * * * * * * * * * * *
* Session Benchmarks *
* * * * * * * * * * * */
getSessionBenchmarks: function() {
var sessionBenchmarks = JSON.parse(localStorage.getItem('sessionBenchmarks')) || {}
this.initPath([tf.modelId, this.forecastId()], sessionBenchmarks)
return sessionBenchmarks
},
addSessionBenchmark: function(doc) {
doc.sessionBenchmark = true
doc.sessionDriver = this.options.chartWrapper.getDriver()
var sessionBenchmarks = this.getSessionBenchmarks()
sessionBenchmarks[tf.modelId][this.forecastId()][doc.uid] = doc
localStorage.setItem('sessionBenchmarks', JSON.stringify(sessionBenchmarks))
return doc
},
updateSessionBenchmark: function(doc) { return this.addSessionBenchmark(doc) },
removeSessionBenchmark: function(doc) {
var sessionBenchmarks = this.getSessionBenchmarks()
delete sessionBenchmarks[tf.modelId][this.forecastId()][doc.uid]
localStorage.setItem('sessionBenchmarks', JSON.stringify(sessionBenchmarks))
},
addSessionBenchmarks: function(serverBenchmarks) {
var currentDriver = this.options.chartWrapper.getDriver()
var sessionBenchmarks = this.getSessionBenchmarks()
var forecastBenchmarks = sessionBenchmarks[tf.modelId][this.forecastId()]
for (key in forecastBenchmarks) {
var benchmark = forecastBenchmarks[key]
if (benchmark.sessionDriver == currentDriver) {
benchmark.sessionOverride = serverBenchmarks.some(function(doc) {
// if the benchmark exists on the server, then this session benchmark is overriding it
return doc.uid === benchmark.uid
})
this.addBenchmark(null, benchmark, true)
}
}
},
/* * * * * * * *
* Plot States *
* * * * * * * */
initPlotState: function() {
if (!window.tf.plotStates)
window.tf.plotStates = {}
var currentDriver = this.options.chartWrapper.getDriver()
if(!window.tf.plotStates[currentDriver])
window.tf.plotStates[currentDriver] = {}
},
/** Get the pin/plot information for one single doc (using currentDriver). */
getPlotInfo: function(doc) {
var currentDriver = this.options.chartWrapper.getDriver()
if(!window.tf.plotStates[currentDriver]) {
window.tf.plotStates[currentDriver] = {}
}
return window.tf.plotStates[currentDriver][doc.uid]
},
/** Get the pin/plot information for all docs (using currentDriver). */
getPlots: function() {
var currentDriver = this.options.chartWrapper.getDriver()
return window.tf.plotStates[currentDriver]
},
/** Save the plot state for the current doc
* @param doc - current SOLR-style doc
* @param type - PlotType from PlottedController, USER_PLOT, UNIVERSAL_PLOT, UNIVERSAL_PIN or UNIVERSAL_PIN_USER_PLOT
* @param visible - is currently visible?. */
savePlotInfo: function(doc, type, visible) {
var currentDriver = this.options.chartWrapper.getDriver()
window.tf.plotStates[currentDriver][doc.uid] = { plotType: type, visible: visible, doc: doc }
},
clearPlotInfo: function(doc) {
var currentDriver = this.options.chartWrapper.getDriver()
window.tf.plotStates[currentDriver][doc.uid] = {}
},
saveAllPlotInfo: function(docs) {
docs.forEach(function(doc) {
if (doc.plotType == 'UNIVERSAL_PLOT') {
this.savePlotInfo(doc, doc.plotType, true)
}
else if (doc.plotType == 'UNIVERSAL_PIN') {
this.savePlotInfo(doc, doc.plotType, false)
}
this.addBenchmark(null, doc)
}, this)
},
/* * * * * * *
* API Calls *
* * * * * * */
/* Handles some of the error cases where a 200 status code (OK) is returned but it's actually an error */
otherAjaxError: function(data) {
// if it's not returning a Json, it's probably returning an HTML error page
if (data.status === 200 && !data.responseJSON){
}
},
/* *
* build the common request parameters
* that are required to be sent to server
* when (un)pinning/autoplotting various benchmarks
*/
buildRequestData: function(doc){
var requestData = {}
requestData.modelInfo=window.tf.modelId;
requestData.plottedCode=doc.uid;
requestData.refModelInfo=doc.model_id;
if(!this.isBaseModel())
requestData.derivedModel=this.forecastId();
return requestData;
},
persistPlot: function(doc) {
if (!window.tf.modelId || !doc.model_id) return
var self = this;
var requestData = self.buildRequestData(doc);
requestData.autoPlot=true;
$.ajax({
type: 'POST',
url: getHost() +'/plot/admin/add/'+ this.options.chartWrapper.getDriver() ,
data: requestData,
dataType: 'json',
error: function(){
self.showAlert('something has gone wrong, try another');
},
complete: self.otherAjaxError
})
},
persistUnplot: function(doc) {
if (!window.tf.modelId || !doc.model_id) return
var self = this;
var requestData = self.buildRequestData(doc);
requestData.autoPlot=true
$.ajax({
type: 'POST',
url: getHost() +'/plot/admin/remove/'+ this.options.chartWrapper.getDriver(),
data: requestData,
dataType: 'json',
error: function(){
self.showAlert('something has gone wrong, try another');
},
complete: self.otherAjaxError
})
},
persistPin: function(doc) {
if (!window.tf.modelId || !doc.model_id) return
var self = this;
var requestData = self.buildRequestData(doc);
requestData.autoPlot=false
$.ajax({
type: 'POST',
url: getHost() +'/plot/admin/add/'+ this.options.chartWrapper.getDriver(),
data: requestData,
dataType: 'json',
error: function(){
self.showAlert('something has gone wrong, try another');
},
complete: self.otherAjaxError
})
},
fetchPinsAndPlots: function() {
var self = this;
if (!window.tf.modelId) return
var driver = self.options.chartWrapper.getDriver()
if (driver === null) return
var requestData = {}
requestData.modelVersion=window.tf.modelId
if(!self.isBaseModel())
requestData.derivedModel=self.forecastId()
$.ajax({
type: 'GET',
url: getHost() +'/plotted/'+ driver +'/lookup',
data:requestData,
dataType: 'json',
success: function(docs) {
// The endpoint may return something that isn't an array, for example it might be a number
// indicating the status code like: 403
if (docs instanceof Array) {
// Session benchmarks have higher precedence than server benchmarks so they get loaded first
self.addSessionBenchmarks(docs)
self.addBenchmarks(null, docs)
}
else {
self.showAlert('Cannnot fetch right now, try again later');
}
},
error: function(){
self.showAlert('Cannnot fetch right now, try again later');
},
})
},
/* * * * * * * * * * * * *
* Recent Local Storage *
* * * * * * * * * * * * */
/* Get or initialize local storage's recent plots. */
getPeriodToRecentPlots: function() {
var periodToRecentPlots;
if (!localStorage.getItem('periodToRecentPlots')) {
localStorage.setItem('periodToRecentPlots', JSON.stringify({}))
}
try {
periodToRecentPlots = JSON.parse(localStorage.getItem('periodToRecentPlots'))
}
catch(err) {
localStorage.setItem('periodToRecentPlots', JSON.stringify({}))
periodToRecentPlots = JSON.parse(localStorage.getItem('periodToRecentPlots'))
}
return periodToRecentPlots
},
/* Add doc to local storage by period type. */
addToLocalStorage: function(doc) {
var periodToRecentPlots = this.getPeriodToRecentPlots()
var periodType = this.options.chartWrapper.getCurrentPeriodType()
if(!periodToRecentPlots[periodType])
periodToRecentPlots[periodType] = {}
doc.addedToLocalStorage = new Date()
periodToRecentPlots[periodType][doc.uid] = doc
localStorage.setItem('periodToRecentPlots', JSON.stringify(periodToRecentPlots))
},
/* Get array of most recent docs, limited by max variable size. */
getLocalStorageRecordsByPeriod: function() {
var max = 10
var periodToRecentPlots = this.getPeriodToRecentPlots()
var periodType = this.options.chartWrapper.getCurrentPeriodType()
if(!periodToRecentPlots[periodType]) {
periodToRecentPlots[periodType] = {}
localStorage.setItem('periodToRecentPlots', JSON.stringify(periodToRecentPlots))
}
var recordsMap = periodToRecentPlots[periodType]
var recordsArray = [];
for (var key in recordsMap) {
recordsArray.push(recordsMap[key])
}
recordsArray.sort(function(a, b) {
var d1 = a.addedToLocalStorage
, d2 = b.addedToLocalStorage
return d1 > d2 ? -1 : d1 < d2 ? 1 : 0
});
var records = [];
for (var i = 0; i < recordsArray.length; i++) {
if (max && records.length >= max)
break
records.push(recordsArray[i])
}
return records
},
/* Place the current time on the plot, then add to periodType->uid map. */
saveRecent: function(doc) {
this.addToLocalStorage(doc)
},
/* Get the recent plots of the same period type from local storage via methods on chart wrapper. */
getRecent: function() {
var recent = new Array
var periodType = this.options.chartWrapper.getCurrentPeriodType()
if (periodType === undefined) { return [] }
return this.getLocalStorageRecordsByPeriod()
},
/* * * * * * * * * * * *
* Autocomplete Search *
* * * * * * * * * * * */
initSearchField: function() {
// benchmarkSearchDiv == custom.benchmarksearchdiv,
// ie: $().benchmarksearchdiv();
// this file.
// this == custom.benchmarksearch
// ie: $()..benchmarksearch
// benchmarkSearchField.js
var benchmarkSearchDiv = this;
var defaults = {
appendTo: this.benchmarkResults,
position: {
my: 'bottom',
at: 'bottom',
of: this.benchmarkResults
},
/**
* This is a standard autocomplete event/method.
* keyword This = the actual input, not the widget.
* Good for performing actions when a response (data or not) has been achieved
* It is not suitable for trying to manipulate the data prior to rendering
* Use the filterResults method instead.
* also can be used $(el).on('benchmarksearchresponse',handler)
* @param event benchmarksearchresponse
*/
response: function(event,results){
if (results.length === 0){
benchmarkSearchDiv.updateSearchResultSummary(0);
}
if (event.target.value){
benchmarkSearchDiv.options.searchTerm = $(event.target).val();
}
// clear out the list
benchmarkSearchDiv.benchmarkResults.find('ul').empty()
},
/**
* This allows for the keyboard navigation to work. In lightweight, we allow it
* in advanced, we don't.
* Preventing default keeps jquery ui from populating the searchbox with text/value of the item
*
* We style the jquery ui element now - so this is actually in use for the advanced ui
* only hidden to the user based on css
*
*
*
* @param event
* @param ui
*/
focus: function(event,ui){
event.preventDefault();
},
sourceUrl: getHost() + '/autocomplete/benchmark',
getSourceParams: function() {
var result = {}
if (benchmarkSearchDiv.options.freeAccess) {
result.freeAccessToken = benchmarkSearchDiv.options.freeAccessToken
result.freeAccessModel = benchmarkSearchDiv.options.freeAccessModel
}
result.modelId = benchmarkSearchDiv.options.freeAccessModel;
return result
},
/**
* determine the period plottability of the data in the benchmark.
* - can it be plotted in the current period
* - can it be plotted in any period in the chart
*/
processResults: function(searchResults){
searchResults.forEach(function(result, index){
result.doc.periodData = benchmarkSearchDiv.addAllPlottablePeriodInfo(result.doc);
})
return searchResults;
},
/**
*
* Filter out displayable results based on our criteria of:
* has it already been added to the chart?
* Does the user want to see all data - regardless of wether it can be plotted or not
* - user can control this via checkbox in advanced
* - advanced ui defaults to true - show all data
* Do we want to only show data for the charts current period (lightweight UI vs advanced)
*
* @param ui = array of response data
* @returns sortedResults = [] of items that don't match our display criteria
*/
/**
* Criteria for being filtered:
* 1. is it an active benchmark (has the user clicked it)?
* 2. Does it have any plottable data Regardless of charts _current_ period
* is there data to allow it to be added.
* 2.a has the user chosen to see it regardless of its plottability
* benchmarkSearchDiv.options.showAllData
* if none of the period types in the search result are plottable, it
* isPlottable = false
* we may still want to show them in the search results (showAllPeriodTYpes)
* showAllPeriodTypes is false in hover ui, true in advanced
*
* 3. are we in lightweight or advanced
* 3.a Does it have data for current period
*
* - in advancedUi we allow users to add and change the chart based on the
* perferred periodTYpe in the benchmark data
* ie, chart is in annual, but has quarterly period as well,
* the benchmark is quarterly, it will add to the chart and change its period
* - when not in advancedUi, we only show results that match the current period type
* of the chart
*/
filterResults: function(searchResults){
return searchResults.filter(function(result) {
return !benchmarkSearchDiv.isInActiveBenchmarkStateList(result.doc.uid)
&& (!benchmarkSearchDiv.options.showAllData ? result.doc.periodData.isPlottable : true)
&& (!benchmarkSearchDiv.options.isAdvancedUi ? result.doc.periodData.hasCurrentPlottable : true)
})
},
/**
* Sort THE REMAINING
* curent sorting is able to plot, then not able to plot
*/
sortResults: function(searchResults){
var sortedResults = _.sortBy(searchResults, function(item) {
// if the item is not plottabled, sort to top
return !item.doc.periodData.isPlottable
});
return sortedResults
},
selectItemCallback: function(event, doc, item) {
var self = this;
function triggerAlert(type,msg){
benchmarkSearchDiv.showAlert(msg)
$(item).trigger('benchmarkSearch.selectItem:alert', [{ alertType: type, alertMsg: msg }])
}
if (doc.reducted) {
triggerAlert('reducted','You must subscribe to '+ ui.item.doc.providerString.toUpperCase() +' to get access to this item.')
} else if ($(item).hasClass('disabled')) {
triggerAlert('disabled','This data cannot be added');
} else {
var isSession = !benchmarkSearchDiv.isAuthor()
benchmarkSearchDiv.addBenchmark(event, doc, isSession);
}
},
preRenderItemCallback: function(doc) {
return true;
},
postRenderItemCallback: function(doc, item) {
// For the advanced UI - we need the ability to allow the user to add:
// items that have at least a plot in any periodType of the chart
// display a message if they have no plottable data for ANY of the period
// when they do, the chart needs to switch to that period type.
// the preRenderItemCallback excludes some items
// disable those that don't have any data in the charts periods
if (!doc.periodData.isPlottable){
item.addClass('label-warning disabled');
}
item.data('doc',doc);
benchmarkSearchDiv.addItemHover(item);
var hovertext = getBenchmarkTooltip(doc);
hovertext +=' '+ getItemPeriodsToDisplay(doc);
item.attr('title', hovertext)
},
preRenderCallback: function() {
benchmarkSearchDiv.benchmarkResults.empty()
},
postRenderCallback: function(ul, searchFieldWidget) {
benchmarkSearchDiv.benchmarkResults.find('.ui-autocomplete').show()
// update the search results
var searchType = benchmarkSearchDiv.options.searchType;
ul.removeClass('ancillaryOn').removeClass('ancillaryOff').addClass(searchType); //re-add ancillaryOn or ancillaryOff class
var results = this.searchResults.filter(function(r){return r.searchType==searchType});
benchmarkSearchDiv.updateSearchResultSummary(results.length, results.filter(function(benchmark) {
return !benchmark.doc.periodData.isPlottable
}).length);
}
}
var opts = $.extend(true,{},defaults,this.options.searchWidgetOpts);
// initialize widget
this.benchmarkSearch.benchmarksearch(opts);
// access widget
this.searchInput = this.benchmarkSearch.data('customBenchmarksearch');
// widget to add a clear button inside/next too the input
this.benchmarkSearchContainer.find('[data-clearinput]').clearInput();
},
loadAdvancedUI: function(){
// pass the chart to the advanced ui, it will take it from here...
radio('benchmarkSearchAdvanced:open').broadcast({
cw: this.options.chartWrapper,
chartOptions:this.options.chartWrapper.options,
forecastModel: this.options.forecastModel,
searchOptions: this.options,
searchTerm: this.options.searchTerm
});
this.hide();
// we name this so that we can unsubscribe it. when we load a new instance of advanced
// it will re-bind.
var reload = function(data){
this.options.chartWrapper.setActivePeriodType(data.activePeriod);
this.reload();
// come back to a visible benchmarks menu in sankey
if (!this.options.chartWrapper.options.gridviewChart){
this.show();
}
// TODO: figure out gridview state..
// the button bar which holds the open/close functionality for the benchmarks is shown on hover
// this actual ui is opened/closed with a click. After going into advanced, we want the user
// to re-see their state, so we trigger a mousenter to show the whole button bar, including the open state
// however if we open this dynamically, we need to then close it when the user hovers
// onto another gridviewchart, without the user having to re-mouseleave...
radio('benchmarkSearchAdvanced:close').unsubscribe(reload)
}
radio('benchmarkSearchAdvanced:close').subscribe([reload,this]);
}
})
}
})
;;
// lib/jquery-1.10.2.min.js
// @include lib/jquery.cookie.js
// @include widgetCommon/checkboxDropdown.js
// @include infrastructure/competitionManager.js
// @include widgetCommon/benchmarkSearchDiv.js
function ChartButtonBar(buttonBarDiv, competitionPopupDiv, chartWrapper, largeFormat, ignoreSmoothingCookie) {
var smoothingDiv, resetDiv, competitionDiv;
smoothingDiv = buttonBarDiv.find(".cwSmoothing");
resetDiv = buttonBarDiv.find(".cwReset");
competitionDiv = buttonBarDiv.find(".cwCompetition");
var competitionDropdown = new CheckboxDropdown(
competitionPopupDiv,
chartWrapper.setSeriesVisible,
largeFormat),
competitionManager = new CompetitionManager(
chartWrapper,
competitionDropdown.setOptions,
function() { return false; },
largeFormat,
largeFormat
),
smoothing,
competitionPopupOpen,
competitionPopupRendered;
var smoothingValueFromCookie = $.cookie('smoothing');
if(smoothingValueFromCookie !== undefined && smoothingValueFromCookie !== null && !ignoreSmoothingCookie)
smoothing = (smoothingValueFromCookie == 'true');
else if(window.tf && window.tf.modelPreferences)
smoothing = window.tf.modelPreferences.defaultSmoothing;
else
smoothing = true;
var benchmarks = buttonBarDiv.find(".cwBenchmarks");
var counter=2;
/*//NO BENCHMARKS ON OLD CHARTS
if(benchmarks.benchmarksearchdiv) {
benchmarks.benchmarksearchdiv({
chartWrapper: chartWrapper,
selectItemCallback: [
function(event, data){ //apply plot callback
var currentPeriodType = chartWrapper.getCurrentPeriodType();
var trefisChartData = chartWrapper.createChartData(data);
chartWrapper.registerSeries(data.uid, data.title, trefisChartData, counter++);
chartWrapper.setSeriesVisible(data.uid, true)
},
function(event, data){//callback to increment for most popular plots
//add
if(!chartWrapper.isSeriesVisible(data.uid)) {
var trefisChartData = chartWrapper.createChartData(data);
chartWrapper.registerSeries(data.uid, data.title, trefisChartData, 1);
chartWrapper.setSeriesVisible(data.uid, true);
}
// Return if there is no model id to store
if(!window.tf.modelId || !data.model_id) {
return;
}
$.ajax({
type: 'POST',
url: getHost()+'/plot/' + chartWrapper.getDriver() + '?modelInfo=' +
window.tf.modelId + "&plottedCode=" + data.uid + "&refModelInfo=" + data.model_id + "&pin=true",
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function(resp) {
benchmarks.benchmarksearchdiv('processPinsAndPlots', resp);
}
});
}
],
removeItemCallback: function(event, data){
chartWrapper.setSeriesVisible(data.uid, false);
//Remove from the saved plots
// Return if there is no model id to store
if(!window.tf.modelId || !data.model_id) {
return;
}
$.ajax({
type: 'POST',
url: getHost()+'/unplot/' + chartWrapper.getDriver() + '?modelInfo=' +
window.tf.modelId + "&plottedCode=" + data.uid + "&refModelInfo=" + data.model_id,
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function(resp) {
benchmarks.benchmarksearchdiv('processPinsAndPlots', resp);
}
});
},
getCurrentPeriodType: function(){
return chartWrapper.getCurrentPeriodType();
},
//todo wire up free access token here
freeAccess: window.tf && window.tf.modelContext && window.tf.modelContext.freeAccessToken,
freeAccessToken: (window.tf && window.tf.modelContext) ? window.tf.modelContext.freeAccessToken: null,
freeAccessModel: (window.tf && window.tf.modelContext) ? window.tf.modelContext.model: null,
provider:(window.tf && window.tf.modelContext) ? window.tf.modelContext.provider: null,
modelGroupId: benchmarks.data('modelgroupid')
});
}*/
updateSmoothingElmt();
smoothingDiv.click(function() {
smoothing = !smoothing;
$.cookie('smoothing', ''+smoothing, {path: '/'});
updateSmoothingElmt();
$(this).blur();
return false;
});
resetDiv.click(function(e) {
chartWrapper.reset();
$(this).blur();
e.preventDefault();
return false;
});
competitionDiv.click(function() {
toggleCompetitionPopup();
$(this).blur();
return false;
});
chartWrapper.addDriverListener(function() {
competitionPopupRendered = 0;
hidePopups();
//NO BENCHMARKS ON OLD CHARTS
//if(benchmarks && benchmarks.benchmarksearchdiv)
// benchmarks.benchmarksearchdiv('reset');
});
function updateSmoothingElmt(){
smoothingDiv.toggleClass("cwSmoothingActive", smoothing);
chartWrapper.setSmoothing(smoothing);
}
/*
* Methods
*/
function toggleCompetitionPopup() {
competitionPopupOpen = !competitionPopupOpen;
competitionPopupDiv.toggle(competitionPopupOpen);
competitionDiv.toggleClass("cwCompetitionActive", competitionPopupOpen);
$("body")[competitionPopupOpen ? "bind" : "unbind"]("click", competitionPopupWidgetClick);
if(competitionPopupOpen && !competitionPopupRendered) {
competitionDropdown.showLoading();
competitionManager.prepForDriver(
chartWrapper.getCompanyData(),
chartWrapper.getDriver(),
true,
false);
competitionPopupRendered = 1;
}
return false;
}
function competitionPopupWidgetClick(e) {
var x = e.target;
if(!competitionPopupDiv.has(x).length && x != competitionDiv[0])
toggleCompetitionPopup();
}
function hidePopups() {
if(competitionPopupOpen)
toggleCompetitionPopup();
}
function getSmoothing(){
return smoothing
}
$.extend(this, {
hidePopups: hidePopups,
getSmoothing: getSmoothing
});
}
;
;;
// lib/jquery-1.10.2.min.js
// @include lib/jquery-ui-1.10.3.min.js
// @include chart/trefisChart.js
// @include widgetCommon/chartButtonBar.js
// @include widgetCommon/benchmarkSearchDiv.js
// @include infrastructure/orangePrompt.js
// @include lib/jquery.hoverIntent.minified.js
// @include infrastructure/period.js
// @include properties.js
/***
-drop down menu on top of each chart, retrieves properties from a chart, and hides/shows/sets-css on menu items to make the menu reflect the state of the chart
The structure of the menu is determined by a template /trefis/src-docroot/WEB-INF/tags/widget/chartMenuTemplate.tag, therefor this template should be included on
any pages that uses the menu. Since this menu is strictly parts of charts, its initialized from modelChart.js and the template is currently included with other
chart components
*/
;$(function() {
if($.widget) {
$.widget( 'custom.chartMenu', {
//widget defaults
options:{
chart: null, //the parent model chart object
growthModeClass:'.js-growthmode',
smoothingControlOnClass:'.js-smoothingControl',
ignoreSmoothingCookie:false
},
_create: function(){//widget 'constructor'
this.smoothing = this.getDefaultStateOfSmoothing();
this.attachHandlers();
this.update();
this.toggleOpen()
},
_destroy:function(){
},
// Bootstrap dropdown gets toggled twice and so doesn't open for some reason in view mode (edit mode ok)
// so this is a hacky workaround
toggleOpen: function() {
var self = this.element
this.element.click(function() {
$(this).toggleClass('open')
})
$('body').click(function(event) {
if (!$.contains(self[0], event.target))
self.removeClass('open')
})
},
/**
* attach click handlers
**/
attachHandlers : function(){
var chart = this.options.chart;
var _this = this;
var originComponentIsValueOutput = false;
try {
originComponentIsValueOutput = _this.options.chart.options.originComponent == "valueOutput";
} catch (e) {
}
// These events update the store if in editMode, which in turn calls an update method in chart.js, which calls an update in modelChart
this.element.on("click", ".plottype", function(event){
if(!$(this).hasClass("active")){
if (!originComponentIsValueOutput) {
chart.updateStoreComponent('seriesType',$(this).data("plottype"))
} else {
chart.updateSeriesType($(this).data("plottype"));
}
_this.update();
}
event.preventDefault();
})
this.element.on('click',this.options.growthModeClass, function(event){
if(!$(this).hasClass("active")){
if (!originComponentIsValueOutput) {
chart.updateStoreComponent('growthModeEnabled',$(this).data("growthmode"))
} else {
chart.setGrowthModeEnabled($(this).data("growthmode"));
}
_this.update();
}
event.preventDefault();
})
this.element.on('click',this.options.smoothingControlClass,function(event){
if ($(this).hasClass('js-smoothing-on')){
_this.smoothing = true;
} else {
_this.smoothing = false;
}
if (_this.options.editMode){
chart.updateStoreComponent('smoothing',_this.smoothing)
} else {
$.cookie('smoothing', ''+_this.smoothing, {path: '/'});
chart.setSmoothing(_this.smoothing);
}
_this.update();
event.preventDefault();
})
},
/**
* update ui state
*/
update: function(){
this.updatePlotTypes();
this.updateGrowthMode();
this.updateSmoothing();
},
/**
* updates the ui state of the plot-type entries, line, bar, stacked, area etc...
* hides unavailable plot types, marks the currently active type
*/
updatePlotTypes : function(){
var chart = this.options.chart;
$(this.element).find(".plottype").removeClass("active").hide();
var types = chart.getAvailablePlotTypes();
var isAlphaTester = properties.loggedInUser() && properties.loggedInUser().userId === 1
if (!isAlphaTester) {
types = types.filter(function(type) {
return type !== 'sankey'
})
}
for(var i = 0; i
").append($('').append($('