From fcb589270edc4ebfb56e6b778e486cc38bb2e033 Mon Sep 17 00:00:00 2001 From: Benaka Moorthi Date: Mon, 26 Aug 2013 05:41:25 -0400 Subject: [PATCH] Refs #4077, #4041, separated jqplot specific code from generic series picker code and cleaned up series picker code a bit. --- .../CoreVisualizations/javascripts/jqplot.js | 8 +- .../javascripts/seriesPicker.js | 270 ++++++++++-------- 2 files changed, 160 insertions(+), 118 deletions(-) diff --git a/plugins/CoreVisualizations/javascripts/jqplot.js b/plugins/CoreVisualizations/javascripts/jqplot.js index a521f765633..81bed3ce5d2 100644 --- a/plugins/CoreVisualizations/javascripts/jqplot.js +++ b/plugins/CoreVisualizations/javascripts/jqplot.js @@ -1042,17 +1042,23 @@ RowEvolutionSeriesToggle.prototype.beforeReplot = function () { var dataTable = $('#' + target).closest('.dataTable').data('dataTableInstance'); var seriesPicker = new piwik.SeriesPicker(dataTable); + // handle placeSeriesPicker event var plot = this; $(seriesPicker).bind('placeSeriesPicker', function () { this.domElem.css('margin-left', (plot._gridPadding.left + plot.plugins.canvasLegend.width - 1) + 'px'); plot.baseCanvas._elem.before(this.domElem); }) + // handle seriesPicked event + $(seriesPicker).bind('seriesPicked', function (e, columns, rows) { + $('#' + this.dataTableId + ' .piwik-graph').trigger('changeSeries', [columns, rows]); + }); + this.plugins.seriesPicker = seriesPicker; }); $.jqplot.postDrawHooks.push(function () { - this.plugins.seriesPicker.createElement(this); + this.plugins.seriesPicker.createElement(); }); })(jQuery); diff --git a/plugins/CoreVisualizations/javascripts/seriesPicker.js b/plugins/CoreVisualizations/javascripts/seriesPicker.js index 97e93a69f7f..301451624a6 100644 --- a/plugins/CoreVisualizations/javascripts/seriesPicker.js +++ b/plugins/CoreVisualizations/javascripts/seriesPicker.js @@ -8,7 +8,7 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -(function ($) { +(function ($, doc) { /** * This class creates and manages the Series Picker for certain DataTable visualizations. @@ -16,9 +16,8 @@ * @param {dataTable} The dataTable instance to add a series picker to. */ var SeriesPicker = function (dataTable) { - - // dom element this.domElem = null; + this.dataTableId = dataTable.workingDivId; // the columns that can be selected this.selectableColumns = dataTable.props.selectable_columns; @@ -33,8 +32,6 @@ // can multiple rows we selected? this.multiSelect = !! dataTable.props.allow_multi_select_series_picker; - this.dataTableId = dataTable.workingDivId; - // language strings this.lang = { @@ -42,6 +39,9 @@ metricToPlot: _pk_translate('General_MetricToPlot_js'), recordsToPlot: _pk_translate('General_RecordsToPlot_js') }; + + this._pickerState = null; + this._pickerPopover = null; }; SeriesPicker.prototype = { @@ -49,38 +49,45 @@ /** * TODO */ - createElement: function (plot) { + createElement: function () { if (!this.show) { return; } + var self = this; + // initialize dom element - this.domElem = $(document.createElement('a')) + this.domElem = $(doc.createElement('a')) .addClass('jqplot-seriespicker') - .attr('href', '#').html('+'); - - this.domElem.on('hide', function () { - $(this).css('opacity', .55); - }).trigger('hide'); - - // show picker on hover - var self = this; - this.domElem.hover( - function () { - self.domElem.css('opacity', 1); - if (!self.domElem.hasClass('open')) { - self.domElem.addClass('open'); - self.showPicker(plot._width); // TODO: ??? + .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 (checkPickerLeave()). } - }, - function () { - // do nothing on mouseout because using this event doesn't work properly. - // instead, the timeout check beneath is used (checkPickerLeave()). - } - ).click(function (e) { - e.preventDefault(); - return false; - }); + ) + .click(function (e) { + e.preventDefault(); + return false; + }); $(this).trigger('placeSeriesPicker'); // TODO: document this & other events }, @@ -88,106 +95,68 @@ /** * TODO */ - showPicker: function (plotWidth) { - var pickerLink = this.domElem; - var pickerPopover = $(document.createElement('div')) - .addClass('jqplot-seriespicker-popover'); - - var pickerState = {manipulated: false}; + showPicker: function () { + this._pickerState = {manipulated: false}; + this._pickerPopover = this._createPopover(); - // headline - var title = this.multiSelect ? this.lang.metricsToPlot : this.lang.metricToPlot; - pickerPopover.append($(document.createElement('p')) - .addClass('headline').html(title)); - - if (this.selectableColumns) { - // render the selectable columns - for (var i = 0; i < this.selectableColumns.length; i++) { - var column = this.selectableColumns[i]; - pickerPopover.append(this.createPickerPopupItem(column, 'column', pickerState, pickerPopover, pickerLink)); - } - } - - if (this.selectableRows) { - // "records to plot" subheadline - pickerPopover.append($(document.createElement('p')) - .addClass('headline').addClass('recordsToPlot') - .html(this.lang.recordsToPlot)); - - // render the selectable rows - for (var i = 0; i < this.selectableRows.length; i++) { - var row = this.selectableRows[i]; - pickerPopover.append(this.createPickerPopupItem(row, 'row', pickerState, pickerPopover, pickerLink)); - } - } - - $('body').prepend(pickerPopover.hide()); - var neededSpace = pickerPopover.outerWidth() + 10; - - // try to display popover to the right - var linkOffset = pickerLink.offset(); - if (navigator.appVersion.indexOf("MSIE 7.") != -1) { - linkOffset.left -= 10; - } - var margin = (parseInt(pickerLink.css('marginLeft'), 10) - 4); - if (margin + neededSpace < plotWidth - // make sure it's not too far to the left - || margin - neededSpace + 60 < 0) { - pickerPopover.css('marginLeft', (linkOffset.left - 4) + 'px').show(); - } else { - // display to the left - pickerPopover.addClass('alignright') - .css('marginLeft', (linkOffset.left - neededSpace + 38) + 'px') - .css('backgroundPosition', (pickerPopover.outerWidth() - 25) + 'px 4px') - .show(); - } - pickerPopover.css('marginTop', (linkOffset.top - 5) + 'px').show(); + this._positionPopover(); // hide and replot on mouse leave var self = this; - this.checkPickerLeave(pickerPopover, function () { - var replot = pickerState.manipulated; - self.hidePicker(pickerPopover, pickerLink, replot); + this.checkPickerLeave(function () { + var replot = self._pickerState.manipulated; + self.hidePicker(replot); }); }, /** * TODO */ - createPickerPopupItem: function (config, type, pickerState, pickerPopover, pickerLink) { + 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 && pickerState.oneChecked)) { + if (config.displayed && !(!this.multiSelect && this._pickerState.oneChecked)) { checkbox.prop('checked', true); - pickerState.oneChecked = 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', type == 'column' ? config.column : config.matcher); + checkbox.data('name', columnName); var el = $(document.createElement('p')) .append(checkbox) - .append('') - .addClass(type == 'column' ? 'pickColumn' : 'pickRow'); + .append($('