/** * Piwik - Web Analytics * * Series Picker control addition for DataTable visualizations. * * @link http://piwik.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ (function ($, doc, require) { /** * This class creates and manages the Series Picker for certain DataTable visualizations. * * To add the series picker to your DataTable visualization, create a SeriesPicker instance * and after your visualization has been rendered, call the 'init' method. * * To customize SeriesPicker placement and behavior, you can bind callbacks to the following * events before calling 'init': * * 'placeSeriesPicker': Triggered after the DOM element for the series picker link is created. * You must use this event to add the link to the dataTable. YOu can also * use this event to position the link however you want. * * Callback Signature: function () {} * * 'seriesPicked': Triggered when the user selects one or more columns/rows. * * Callback Signature: function (eventInfo, columns, rows) {} * * Events are triggered via jQuery, so you bind callbacks to them like this: * * var picker = new SeriesPicker(dataTable); * $(picker).bind('placeSeriesPicker', function () { * $(this.domElem).doSomething(...); * }); * * @param {dataTable} dataTable The dataTable instance to add a series picker to. * @constructor */ var SeriesPicker = function (dataTable) { this.domElem = null; this.dataTableId = dataTable.workingDivId; // the columns that can be selected this.selectableColumns = dataTable.props.selectable_columns; // the rows that can be selected this.selectableRows = dataTable.props.selectable_rows; // render the picker? this.show = !! dataTable.props.show_series_picker && (this.selectableColumns || this.selectableRows); // can multiple rows we selected? this.multiSelect = !! dataTable.props.allow_multi_select_series_picker; // language strings this.lang = { metricsToPlot: _pk_translate('General_MetricsToPlot'), metricToPlot: _pk_translate('General_MetricToPlot'), recordsToPlot: _pk_translate('General_RecordsToPlot') }; this._pickerState = null; this._pickerPopover = null; }; SeriesPicker.prototype = { /** * Initializes the series picker by creating the element. Must be called when * the datatable the picker is being attached to is ready for it to be drawn. */ init: function () { if (!this.show) { return; } var self = this; // initialize dom element this.domElem = $(doc.createElement('a')) .addClass('jqplot-seriespicker') .attr('href', '#') .html('+') // set opacity on 'hide' .on('hide', function () { $(this).css('opacity', .55); }) .trigger('hide') // show picker on hover .hover( function () { var $this = $(this); $this.css('opacity', 1); if (!$this.hasClass('open')) { $this.addClass('open'); self._showPicker(); } }, function () { // do nothing on mouseout because using this event doesn't work properly. // instead, the timeout check beneath is used (_bindCheckPickerLeave()). } ) .click(function (e) { e.preventDefault(); return false; }); $(this).trigger('placeSeriesPicker'); }, /** * Returns the translation of a metric that can be selected. * * @param {String} metric The name of the metric, ie, 'nb_visits' or 'nb_actions'. * @return {String} The metric translation. If one cannot be found, the metric itself * is returned. */ getMetricTranslation: function (metric) { for (var i = 0; i != this.selectableColumns.length; ++i) { if (this.selectableColumns[i].column == metric) { return this.selectableColumns[i].translation; } } return metric; }, /** * Creates the popover DOM element, binds event handlers to it, and then displays it. */ _showPicker: function () { this._pickerState = {manipulated: false}; this._pickerPopover = this._createPopover(); this._positionPopover(); // hide and replot on mouse leave var self = this; this._bindCheckPickerLeave(function () { var replot = self._pickerState.manipulated; self._hidePicker(replot); }); }, /** * Creates a checkbox and related elements for a selectable column or selectable row. */ _createPickerPopupItem: function (config, type) { var self = this; if (type == 'column') { var columnName = config.column, columnLabel = config.translation, cssClass = 'pickColumn'; } else { var columnName = config.matcher, columnLabel = config.label, cssClass = 'pickRow'; } var checkbox = $(document.createElement('input')).addClass('select') .attr('type', this.multiSelect ? 'checkbox' : 'radio'); if (config.displayed && !(!this.multiSelect && this._pickerState.oneChecked)) { checkbox.prop('checked', true); this._pickerState.oneChecked = true; } // if we are rendering a column, remember the column name // if it's a row, remember the string that can be used to match the row checkbox.data('name', columnName); var el = $(document.createElement('p')) .append(checkbox) .append($('