From 3559d824576417a6a0fef44ce978329d5b99b08b Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Tue, 9 Jan 2018 19:47:52 -0500 Subject: [PATCH 01/13] Clean up hypergrid plugin API. --- .../src/js/fixes.js | 2 +- .../src/js/hypergrid.js | 46 +++++++++++-------- packages/perspective-viewer/src/js/view.js | 4 ++ 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/packages/perspective-viewer-hypergrid/src/js/fixes.js b/packages/perspective-viewer-hypergrid/src/js/fixes.js index bde89c861e..37b2864db5 100644 --- a/packages/perspective-viewer-hypergrid/src/js/fixes.js +++ b/packages/perspective-viewer-hypergrid/src/js/fixes.js @@ -48,7 +48,7 @@ export function GridUIFixPlugin(grid) { this.bounds = new rectangular.Rectangle(0, 0, this.width, this.height); this.component.setBounds(this.bounds); this.resizeNotification(); - this.paintNow(); + await this.paintNow(); } grid._getGridCellFromMousePoint = grid.getGridCellFromMousePoint; diff --git a/packages/perspective-viewer-hypergrid/src/js/hypergrid.js b/packages/perspective-viewer-hypergrid/src/js/hypergrid.js index 702a2e6a52..ef4535d8f6 100644 --- a/packages/perspective-viewer-hypergrid/src/js/hypergrid.js +++ b/packages/perspective-viewer-hypergrid/src/js/hypergrid.js @@ -520,7 +520,7 @@ function CachedRendererPlugin(grid) { if (this.component.grid._lazy_load) { let range = estimate_range(this.component.grid); if ( - this.component.grid._cache_update + !(Number.isNaN(range[0]) || Number.isNaN(range[1])) && ( (this.component.grid._updating_cache && !is_subrange(range, this.component.grid._updating_cache.range)) || (!this.component.grid._updating_cache && !is_subrange(range, this.component.grid._cached_range)) @@ -646,8 +646,12 @@ async function fill_page(view, json, hidden, start_row, end_row) { const LAZY_THRESHOLD = 10000; +const PRIVATE = Symbol("Hypergrid private"); + async function grid(div, view, hidden, redraw, task) { + this[PRIVATE] = this[PRIVATE] || {}; + let [nrows, json, schema] = await Promise.all([ view.num_rows(), view.to_json({end_row: 1}), @@ -656,8 +660,12 @@ async function grid(div, view, hidden, redraw, task) { let visible_rows; - if (!this.grid) { - this.grid = document.createElement('perspective-hypergrid'); + if (!this.hypergrid) { + let grid = document.createElement('perspective-hypergrid'); + this[PRIVATE].grid = grid; + Object.defineProperty(this, 'hypergrid', { + get: () => this[PRIVATE].grid.grid + }); } json.length = nrows; @@ -667,12 +675,12 @@ async function grid(div, view, hidden, redraw, task) { if (!lazy_load) { json = view.to_json().then(json => filter_hidden(hidden, json)); } else { - json = Promise.resolve(json); + json = fill_page(view, json, hidden, 0, 1000); } - if (!(document.contains ? document.contains(this.grid) : false)) { + if (!(document.contains ? document.contains(this[PRIVATE].grid) : false)) { div.innerHTML = ""; - div.appendChild(this.grid); + div.appendChild(this[PRIVATE].grid); await new Promise(resolve => setTimeout(resolve)); } @@ -681,27 +689,27 @@ async function grid(div, view, hidden, redraw, task) { return; } - this.grid.grid._lazy_load = lazy_load; - this.grid.grid._cached_range = undefined; + this.hypergrid._lazy_load = lazy_load; + this.hypergrid._cached_range = undefined; - this.grid.grid._cache_update = async (s, e) => { + this.hypergrid._cache_update = async (s, e) => { json = await fill_page(view, json, hidden, s, e); - let new_range = estimate_range(this.grid.grid); + let new_range = estimate_range(this.hypergrid); if (is_subrange(new_range, [s, e])) { let rows = psp2hypergrid(json, schema, s, Math.min(e, nrows), nrows).rows; - rows[0] = this.grid.grid.behavior.dataModel.viewData[0]; - this.grid.grid.setData({data: rows}); + rows[0] = this.hypergrid.behavior.dataModel.viewData[0]; + this.hypergrid.setData({data: rows}); return true; } else { return false; } } - this.grid.set_data(json, schema); - await this.grid.grid.canvas.resize(); - await this.grid.grid._updating_cache; - await this.grid.grid.canvas.resize(); - await this.grid.grid._updating_cache; + this[PRIVATE].grid.set_data(json, schema); + await this.hypergrid.canvas.resize(); + await this.hypergrid._updating_cache; + await this.hypergrid.canvas.resize(); + await this.hypergrid._updating_cache; } global.registerPlugin("hypergrid", { @@ -709,8 +717,8 @@ global.registerPlugin("hypergrid", { create: grid, selectMode: "toggle", resize: function () { - if (this.grid) { - this.grid.grid.canvas.resize(); + if (this.hypergrid) { + this.hypergrid.canvas.resize(); } }, delete: function () { diff --git a/packages/perspective-viewer/src/js/view.js b/packages/perspective-viewer/src/js/view.js index a07e2cab60..b40f04f347 100644 --- a/packages/perspective-viewer/src/js/view.js +++ b/packages/perspective-viewer/src/js/view.js @@ -317,6 +317,10 @@ registerElement(template, { } }, + worker: { + get: get_worker() + }, + _plugin: { get: function () { return RENDERERS[this._vis_selector.value]; From 4cd780a537dc0331a99b2e09ab15e290d5565425 Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Tue, 16 Jan 2018 13:01:34 -0500 Subject: [PATCH 02/13] Changed column selector to "active" and "inactive" sections --- .../perspective-viewer/src/html/view.html | 4 +- packages/perspective-viewer/src/js/view.js | 139 ++++++++++-------- packages/perspective-viewer/src/less/row.less | 40 ++--- .../perspective-viewer/src/less/view.less | 10 +- 4 files changed, 111 insertions(+), 82 deletions(-) diff --git a/packages/perspective-viewer/src/html/view.html b/packages/perspective-viewer/src/html/view.html index fb8bc88a18..46b0e2296f 100644 --- a/packages/perspective-viewer/src/html/view.html +++ b/packages/perspective-viewer/src/html/view.html @@ -16,7 +16,9 @@ - + +
+
diff --git a/packages/perspective-viewer/src/js/view.js b/packages/perspective-viewer/src/js/view.js index b40f04f347..7555774cc2 100644 --- a/packages/perspective-viewer/src/js/view.js +++ b/packages/perspective-viewer/src/js/view.js @@ -84,11 +84,13 @@ function drop(ev) { // Deselect the dropped column let isToggleMode = this._plugin.selectMode === "toggle"; if (isToggleMode && this._visible_column_count() > 1 && name !== "sort") { - for (let x of this.querySelectorAll("#column_names perspective-row")) { + for (let x of this.querySelectorAll("#active_columns perspective-row")) { if (x.getAttribute('name') === data) { - x.className = 'off'; + this._active_columns.removeChild(x); + break; } } + this._update_column_view(this._view_columns('#active_columns perspective-row')); } this._update(); @@ -101,33 +103,36 @@ function drop(ev) { */ function column_visibility_clicked(ev) { - let isSelect = this._plugin.selectMode === 'select' - let mode = (isSelect && !ev.detail.shiftKey) || (!isSelect && ev.detail.shiftKey); let className = `visible_${this._visible_column_count() + 1}`; let parent = ev.currentTarget; - if (mode) { - for (let x of this.querySelectorAll("#column_names perspective-row")) { - x.className = 'off'; - } - parent.classList.remove('off'); - if (parent.classList.length === 0) { - parent.classList.add(className); - } - } else if (parent.classList.contains("off")) { - parent.classList.remove("off"); - if (parent.classList.length === 0) { - parent.classList.add(className); - } + let is_active = parent.parentElement.getAttribute('id') === 'active_columns';; + if (is_active) { + this._active_columns.removeChild(parent); } else { - parent.className = 'off'; + let row = new_row.call( + this, + parent.getAttribute('name'), + parent.getAttribute('type'), + JSON.parse(this.getAttribute('aggregates')).find(x => x.column === parent.getAttribute('name')).op + ); + this._active_columns.appendChild(row); } - let cols = this._view_columns('#column_names perspective-row:not(.off)'); + let cols = this._view_columns('#active_columns perspective-row:not(.off)'); this.setAttribute('columns', JSON.stringify(cols)); + this._update_column_view(cols); this._update(); } function column_aggregate_clicked() { - this.setAttribute('aggregates', JSON.stringify(this._get_view_aggregates())); + let aggregates = JSON.parse(this.getAttribute('aggregates')); + let new_aggregates = this._get_view_aggregates(); + for (let aggregate of aggregates) { + let updated_agg = new_aggregates.find(x => x.column === aggregate.column); + if (updated_agg) { + aggregate.op = updated_agg.op; + } + } + this.setAttribute('aggregates', JSON.stringify(aggregates)); this._update(); } @@ -174,7 +179,7 @@ async function loadTable(table) { this._table.delete(); } - this._column_names.innerHTML = ""; + this._active_columns.innerHTML = ""; this._table = table; let [cols, schema] = await Promise.all([table.columns(), table.schema()]); @@ -210,28 +215,38 @@ async function loadTable(table) { let aggregate = aggregates .filter(a => a.column === x) .map(a => a.op)[0]; - let row = document.createElement('perspective-row'); - row.setAttribute('type', schema[x]); - row.setAttribute('name', x); - if (aggregate) { - row.setAttribute('aggregate', aggregate); - } - row.addEventListener('visibility-clicked', column_visibility_clicked.bind(this)); - row.addEventListener('aggregate-selected', column_aggregate_clicked.bind(this)); - row.addEventListener('row-drag', () => this.classList.add('dragging')); - row.addEventListener('row-dragend', () => this.classList.remove('dragging')); - if (shown.indexOf(x) === -1) { - row.className = 'off'; - } else { - row.className = 'visible_' + (shown.indexOf(x) + 1); + let row = new_row.call(this, x, schema[x], aggregate); + row.className = 'off'; + this._inactive_columns.appendChild(row); + if (shown.indexOf(x) !== -1) { + row.style.display = 'none'; + let active_row = new_row.call(this, x, schema[x], aggregate); + active_row.className = 'visible_' + (shown.indexOf(x) + 1); + this._active_columns.appendChild(active_row); } - this._column_names.appendChild(row); } this._filter_input.innerHTML = ""; this._update(); } +function new_row(name, type, aggregate) { + let row = document.createElement('perspective-row'); + if (!aggregate) { + aggregate = JSON.parse(this.getAttribute('aggregates')).find(x => x.column === name).op; + } + row.setAttribute('type', type); + row.setAttribute('name', name); + if (aggregate) { + row.setAttribute('aggregate', aggregate); + } + row.addEventListener('visibility-clicked', column_visibility_clicked.bind(this)); + row.addEventListener('aggregate-selected', column_aggregate_clicked.bind(this)); + row.addEventListener('row-drag', () => this.classList.add('dragging')); + row.addEventListener('row-dragend', () => this.classList.remove('dragging')); + return row; +} + function update() { if (!this._table) return; let row_pivots = this._view_columns('#row_pivots perspective-row:not(.off)'); @@ -247,7 +262,7 @@ function update() { let sort = this._view_columns("#sort perspective-row:not(.off)"); for (let s of sort) { if (aggregates.map(function(agg) { return agg.column }).indexOf(s) === -1) { - let all = this._get_view_aggregates('#column_names perspective-row'); + let all = this._get_view_aggregates('#inactive_columns perspective-row'); aggregates.push(all.reduce((obj, y) => y.column === s ? y : obj)); hidden.push(s); } @@ -318,7 +333,7 @@ registerElement(template, { }, worker: { - get: get_worker() + get: get_worker }, _plugin: { @@ -374,7 +389,7 @@ registerElement(template, { value: function () { let filters = []; let filter = this._filter_input.value.trim(); - let cols = this._view_columns('#column_names perspective-row'); + let cols = this._view_columns('#active_columns perspective-row'); for (let col of cols) { filter = filter.split("`" + col.trim() + "`").join(col + "||||"); } @@ -406,7 +421,7 @@ registerElement(template, { _get_view_aggregates: { value: function (selector) { - selector = selector || '#column_names perspective-row:not(.off)'; + selector = selector || '#active_columns perspective-row:not(.off)'; return this._view_columns(selector, true); } }, @@ -414,12 +429,7 @@ registerElement(template, { _view_columns: { value: function (selector, types) { let selection = this.querySelectorAll(selector); - let sorted = Array.prototype.slice.call(selection).sort((x, y) => { - if (x.className === "") return 0; - if (x.className === y.className) return 0; - if (x.className < y.className) return -1; - return 1; - }) + let sorted = Array.prototype.slice.call(selection); return sorted.map(s => { let name = s.getAttribute('name'); if (types) { @@ -434,24 +444,37 @@ registerElement(template, { _visible_column_count: { value: function() { - let cols = Array.prototype.slice.call(this.querySelectorAll("#column_names perspective-row")); - let off_cols = Array.prototype.slice.call(this.querySelectorAll("#column_names perspective-row.off")); + let cols = Array.prototype.slice.call(this.querySelectorAll("#active_columns perspective-row")); + let off_cols = Array.prototype.slice.call(this.querySelectorAll("#active_columns perspective-row.off")); return (cols.length - off_cols.length); } }, _update_column_view: { - value: function (columns) { + value: function (columns, reset = false) { let idx = 1; - const lis = Array.prototype.slice.call(this.querySelectorAll("#column_names perspective-row")); - lis.map((x) => { + const lis = Array.prototype.slice.call(this.querySelectorAll("#inactive_columns perspective-row")); + lis.forEach(x => { const index = columns.indexOf(x.getAttribute('name')); if (index === -1) { - x.className = 'off'; + x.style.display = 'block'; } else { - x.className = 'visible_' + (index + 1); + x.style.display = 'none'; } }); + if (reset) { + this._active_columns.innerHTML = ""; + columns.map(y => { + let ref = lis.find(x => x.getAttribute('name') === y); + if (ref) { + this._active_columns.appendChild(new_row.call( + this, + ref.getAttribute('name'), + ref.getAttribute('type') + )); + } + }); + } } }, @@ -463,7 +486,7 @@ registerElement(template, { columns: { set: function () { let show = JSON.parse(this.getAttribute('columns')); - this._update_column_view(show); + this._update_column_view(show, true); this.dispatchEvent(new Event('config-update')); this._update(); } @@ -482,8 +505,7 @@ registerElement(template, { aggregates: { set: function () { let show = JSON.parse(this.getAttribute('aggregates')); - let lis = Array.prototype.slice.call(this.querySelectorAll("#column_names perspective-row")); - let idx = this._visible_column_count(); + let lis = Array.prototype.slice.call(this.querySelectorAll("#side_panel perspective-row")); lis.map((x, ix) => { let agg = show[x.getAttribute('name')]; if (agg) { @@ -507,7 +529,7 @@ registerElement(template, { view: { set: function () { this._vis_selector.value = this.getAttribute('view'); - let cols = Array.prototype.slice.call(this.querySelectorAll("#column_names perspective-row")); + let cols = Array.prototype.slice.call(this.querySelectorAll("#inactive_columns perspective-row")); if (cols.length > 0) { if (this._plugin.selectMode === 'select') { this.setAttribute('columns', JSON.stringify([cols[0].getAttribute('name')])); @@ -647,7 +669,8 @@ registerElement(template, { this._row_pivots = this.querySelector('#row_pivots'); this._column_pivots = this.querySelector('#column_pivots'); this._datavis = this.querySelector('#pivot_chart'); - this._column_names = this.querySelector('#column_names'); + this._active_columns = this.querySelector('#active_columns'); + this._inactive_columns = this.querySelector('#inactive_columns'); this._inner_drop_target = this.querySelector('#drop_target_inner'); this._drop_target = this.querySelector('#drop_target'); this._config_button = this.querySelector('#config_button'); diff --git a/packages/perspective-viewer/src/less/row.less b/packages/perspective-viewer/src/less/row.less index 963877cea3..004ed93eec 100644 --- a/packages/perspective-viewer/src/less/row.less +++ b/packages/perspective-viewer/src/less/row.less @@ -54,16 +54,16 @@ perspective-row li { float: none !important; } -#column_names perspective-row li { +#side_panel perspective-row li { margin-right: 5px; transition: margin-right 0.2s; } -#column_names perspective-row li:hover{ +#side_panel perspective-row li:hover{ margin-right: 2px; } -#column_names perspective-row div { +#side_panel perspective-row div { color: rgb(51, 51, 51); padding: 2px; font-size: 12px; @@ -71,22 +71,22 @@ perspective-row li { transition: margin 0.2s, padding 0.2s, height 0.2s; } -#column_names perspective-row div:hover { +#side_panel perspective-row div:hover { margin-left: -3px; padding-left: 5px; } -#column_names perspective-row:hover div { +#side_panel perspective-row:hover div { margin-left: -3px; padding-left: 5px; } -#column_names perspective-row:not(.off) div { +#side_panel perspective-row:not(.off) div { .bordered(); background-color: white; } -#column_names perspective-row .is_visible { +#side_panel perspective-row .is_visible { width: 20px; min-width: 20px; margin-left: 5px; @@ -95,11 +95,11 @@ perspective-row li { font-size: 14px; } -#column_names perspective-row.off .is_visible::before { +#side_panel perspective-row.off .is_visible::before { content: "\25CB"; } -#column_names perspective-row .is_visible::before { +#side_panel perspective-row .is_visible::before { content: "\25CF"; } @@ -156,7 +156,7 @@ perspective-row #column_aggregate { height: 20px; } -#column_names perspective-row span#name { +#active_columns perspective-row span#name { width: 100%; white-space: nowrap; } @@ -180,37 +180,37 @@ perspective-row .row_draggable select:focus { outline: none; } -perspective-viewer[view=scatter], perspective-viewer[view=line], perspective-viewer[view=line] { - #column_names { +perspective-viewer[view=scatter], perspective-viewer[view=line] { + #active_columns { .off .is_visible::before { content: "\25CB"; } - .visible_1 .is_visible::before { + :nth-child(1) .is_visible::before { .selected_indicator(); content: "X"; } - .visible_2 .is_visible::before { + :nth-child(2) .is_visible::before { .selected_indicator(); content: "Y"; } - .visible_3 .is_visible::before { + :nth-child(3) .is_visible::before { .selected_indicator(); content: "C"; } - .visible_4 .is_visible::before { + :nth-child(4) .is_visible::before { .selected_indicator(); content: "S"; } } } -perspective-viewer:not([row-pivots='[]']) #column_names perspective-row:not(.off) #column_aggregate, -perspective-viewer:not([column-pivots='[]']) #column_names perspective-row:not(.off) #column_aggregate { +perspective-viewer:not([row-pivots='[]']) #side_panel perspective-row:not(.off) #column_aggregate, +perspective-viewer:not([column-pivots='[]']) #side_panel perspective-row:not(.off) #column_aggregate { display: inline-block; } -perspective-viewer:not([row-pivots='[]']) #column_names, -perspective-viewer:not([column-pivots='[]']) #column_names { +perspective-viewer:not([row-pivots='[]']) #side_panel, +perspective-viewer:not([column-pivots='[]']) #side_panel { perspective-row .row_draggable { height: 41px; } diff --git a/packages/perspective-viewer/src/less/view.less b/packages/perspective-viewer/src/less/view.less index 408e663cec..e7728f9afe 100644 --- a/packages/perspective-viewer/src/less/view.less +++ b/packages/perspective-viewer/src/less/view.less @@ -96,15 +96,20 @@ perspective-viewer { position: static !important; } - #column_names { + #active_columns, #inactive_columns { list-style: none; padding: 5px; width: 100%; border: none !important; - flex-grow: 1; margin-top: 8px; overflow-y: auto; } + #divider { + background-color: #CCC; + height: 2px; + margin: 15px 13px 15px 13px; + margin-bottom: 3px; + } .column { display: flex; list-style: none; @@ -198,7 +203,6 @@ perspective-viewer { padding: 0px 10px 0px 10px; margin: 0; .bordered(); - height: 30px; font-size: 12px; } select { From 30c505ca4c9de657ab523def91b853d41ec930f2 Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Tue, 16 Jan 2018 14:27:59 -0500 Subject: [PATCH 03/13] Drag & drop for column selection. --- .../perspective-viewer/src/html/view.html | 2 +- packages/perspective-viewer/src/js/row.js | 1 + packages/perspective-viewer/src/js/view.js | 45 +++++++++++++++++-- packages/perspective-viewer/src/less/row.less | 5 ++- .../perspective-viewer/src/less/view.less | 2 +- 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/packages/perspective-viewer/src/html/view.html b/packages/perspective-viewer/src/html/view.html index 46b0e2296f..f129bfcb71 100644 --- a/packages/perspective-viewer/src/html/view.html +++ b/packages/perspective-viewer/src/html/view.html @@ -16,7 +16,7 @@
-
    +
        diff --git a/packages/perspective-viewer/src/js/row.js b/packages/perspective-viewer/src/js/row.js index 9d33f99714..55f9f46170 100644 --- a/packages/perspective-viewer/src/js/row.js +++ b/packages/perspective-viewer/src/js/row.js @@ -26,6 +26,7 @@ global.dragEnter = function dragEnter(ev) { global.allowDrop = function allowDrop(ev) { ev.preventDefault(); + ev.dataTransfer.dropEffect = 'move'; ev.currentTarget.classList.add('dropping') } diff --git a/packages/perspective-viewer/src/js/view.js b/packages/perspective-viewer/src/js/view.js index 7555774cc2..d32489ff31 100644 --- a/packages/perspective-viewer/src/js/view.js +++ b/packages/perspective-viewer/src/js/view.js @@ -52,7 +52,6 @@ global.registerPlugin = function registerPlugin(name, plugin) { * */ - function undrag(event) { let div = event.target.parentElement; if (div) { @@ -66,6 +65,33 @@ function undrag(event) { } } +function column_undrag(event) { + let data = event.target.parentElement.parentElement; + if (this._visible_column_count() > 1 && event.dataTransfer.dropEffect !== 'move') { + this._active_columns.removeChild(data); + } + this._update_column_view(); + this._update(); +} + +function column_drop(ev) { + ev.preventDefault(); + ev.currentTarget.classList.remove('dropping'); + let data = ev.dataTransfer.getData('text'); + if (!data) return; + + let index = Math.floor((ev.clientY - this._active_columns.offsetTop) / this._active_columns.children[0].offsetHeight); + let target = this._active_columns.children[index]; + let old = Array.prototype.slice.call(this.querySelectorAll('#active_columns perspective-row')).find(x => x.getAttribute('name') === data); + let newr = new_row.call(this, data); + this._active_columns.insertBefore(newr, target); + if (old) { + this._active_columns.removeChild(old); + } + this._update_column_view(); + this._update(); +} + function drop(ev) { ev.preventDefault(); ev.currentTarget.classList.remove('dropping'); @@ -82,15 +108,14 @@ function drop(ev) { this.setAttribute(name, JSON.stringify(columns.concat([data]))); // Deselect the dropped column - let isToggleMode = this._plugin.selectMode === "toggle"; - if (isToggleMode && this._visible_column_count() > 1 && name !== "sort") { + if (this._visible_column_count() > 1 && name !== "sort") { for (let x of this.querySelectorAll("#active_columns perspective-row")) { if (x.getAttribute('name') === data) { this._active_columns.removeChild(x); break; } } - this._update_column_view(this._view_columns('#active_columns perspective-row')); + this._update_column_view(); } this._update(); @@ -107,6 +132,9 @@ function column_visibility_clicked(ev) { let parent = ev.currentTarget; let is_active = parent.parentElement.getAttribute('id') === 'active_columns';; if (is_active) { + if (this._visible_column_count() === 1 ) { + return; + } this._active_columns.removeChild(parent); } else { let row = new_row.call( @@ -235,6 +263,10 @@ function new_row(name, type, aggregate) { if (!aggregate) { aggregate = JSON.parse(this.getAttribute('aggregates')).find(x => x.column === name).op; } + if (!type) { + let all = Array.prototype.slice.call(this.querySelectorAll('#inactive_columns perspective-row')); + type = all.find(x => x.getAttribute('name') === name).getAttribute('type'); + } row.setAttribute('type', type); row.setAttribute('name', name); if (aggregate) { @@ -452,6 +484,9 @@ registerElement(template, { _update_column_view: { value: function (columns, reset = false) { + if (!columns) { + columns = this._view_columns('#active_columns perspective-row'); + } let idx = 1; const lis = Array.prototype.slice.call(this.querySelectorAll("#inactive_columns perspective-row")); lis.forEach(x => { @@ -684,6 +719,8 @@ registerElement(template, { this._row_pivots.addEventListener('dragend', undrag.bind(this)); this._column_pivots.addEventListener('drop', drop.bind(this)); this._column_pivots.addEventListener('dragend', undrag.bind(this)); + this._active_columns.addEventListener('drop', column_drop.bind(this)); + this._active_columns.addEventListener('dragend', column_undrag.bind(this)); this.setAttribute('settings', true); this._show_config = true; diff --git a/packages/perspective-viewer/src/less/row.less b/packages/perspective-viewer/src/less/row.less index 004ed93eec..18a5769833 100644 --- a/packages/perspective-viewer/src/less/row.less +++ b/packages/perspective-viewer/src/less/row.less @@ -11,7 +11,7 @@ .selected_indicator() { font-family: Arial; - font-weight: 600; + font-weight: 500; font-size: 12px; } @@ -89,10 +89,11 @@ perspective-row li { #side_panel perspective-row .is_visible { width: 20px; min-width: 20px; - margin-left: 5px; + margin-left: 6px; cursor: pointer; color: #999; font-size: 14px; + margin-top: -2px; } #side_panel perspective-row.off .is_visible::before { diff --git a/packages/perspective-viewer/src/less/view.less b/packages/perspective-viewer/src/less/view.less index e7728f9afe..d2ff2b2976 100644 --- a/packages/perspective-viewer/src/less/view.less +++ b/packages/perspective-viewer/src/less/view.less @@ -108,7 +108,7 @@ perspective-viewer { background-color: #CCC; height: 2px; margin: 15px 13px 15px 13px; - margin-bottom: 3px; + margin-bottom: 5px; } .column { display: flex; From 6f96bedfee0bd01ce21ef84e2632437af92d4584 Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Wed, 17 Jan 2018 16:40:19 -0500 Subject: [PATCH 04/13] Added drag & drop indicator animation. --- .../perspective-viewer/src/html/view.html | 2 +- packages/perspective-viewer/src/js/row.js | 7 +-- packages/perspective-viewer/src/js/view.js | 53 +++++++++++++++++-- packages/perspective-viewer/src/less/row.less | 12 +++++ 4 files changed, 65 insertions(+), 9 deletions(-) diff --git a/packages/perspective-viewer/src/html/view.html b/packages/perspective-viewer/src/html/view.html index f129bfcb71..bd2d564cb9 100644 --- a/packages/perspective-viewer/src/html/view.html +++ b/packages/perspective-viewer/src/html/view.html @@ -16,7 +16,7 @@ -
          +
              diff --git a/packages/perspective-viewer/src/js/row.js b/packages/perspective-viewer/src/js/row.js index 55f9f46170..17900da74d 100644 --- a/packages/perspective-viewer/src/js/row.js +++ b/packages/perspective-viewer/src/js/row.js @@ -22,12 +22,13 @@ import "../less/row.less"; global.dragEnter = function dragEnter(ev) { ev.preventDefault(); + ev.currentTarget.classList.add('dropping'); } global.allowDrop = function allowDrop(ev) { ev.preventDefault(); - ev.dataTransfer.dropEffect = 'move'; - ev.currentTarget.classList.add('dropping') + ev.dataTransfer.dropEffect = 'all'; + ev.currentTarget.classList.add('dropping'); } global.disallowDrop = function disallowDrop(ev) { @@ -92,7 +93,7 @@ registerElement(template, { this.dispatchEvent(new CustomEvent('row-drag')); }); li.addEventListener('dragend', ev => { - ev.currentTarget.classList.remove('dropping'); + //ev.currentTarget.classList.remove('dropping'); this.dispatchEvent(new CustomEvent('row-dragend')); }); let visible = this.querySelector('.is_visible'); diff --git a/packages/perspective-viewer/src/js/view.js b/packages/perspective-viewer/src/js/view.js index d32489ff31..6e5a823c86 100644 --- a/packages/perspective-viewer/src/js/view.js +++ b/packages/perspective-viewer/src/js/view.js @@ -59,28 +59,60 @@ function undrag(event) { let idx = Array.prototype.slice.call(parent.children).indexOf(div); let attr_name = parent.getAttribute('id').replace('_', '-'); let pivots = JSON.parse(this.getAttribute(attr_name)); - pivots.splice(idx, 1) + pivots.splice(idx, 1); this.setAttribute(attr_name, JSON.stringify(pivots)); this._update(); } } +function calc_index(event) { + return Math.floor(event.offsetY / this._active_columns.children[0].offsetHeight); +} + function column_undrag(event) { let data = event.target.parentElement.parentElement; - if (this._visible_column_count() > 1 && event.dataTransfer.dropEffect !== 'move') { + Array.prototype.slice.call(this._active_columns.children).map(x => {x.className = '';}); + if (this._visible_column_count() > 1 && event.dataTransfer.dropEffect !== 'all') { this._active_columns.removeChild(data); } this._update_column_view(); this._update(); } +function column_dragleave(event) { + if (!this._skip_drag) { + this._active_columns.classList.remove('dropping'); + } + this._skip_drag = false; +} + +function column_dragover(event) { + event.preventDefault(); + event.dataTransfer.dropEffect = 'all'; + if (event.currentTarget.className !== 'dropping') { + this._skip_drag = true; + event.currentTarget.classList.add('dropping'); + } + let index = calc_index.call(this, event); + if (this._active_columns.children[index]) { + if (this._active_columns.children[index].className !== 'inserting') { + Array.prototype.slice.call(this._active_columns.children).map(x => {x.className = '';}); + this._active_columns.children[index].className = 'inserting'; + } + } else { + Array.prototype.slice.call(this._active_columns.children).map(x => {x.className = '';}); + this._active_columns.children[this._active_columns.children.length - 1].className = "postserting"; + } +} + function column_drop(ev) { ev.preventDefault(); ev.currentTarget.classList.remove('dropping'); + Array.prototype.slice.call(this._active_columns.children).map(x => {x.className = '';}); let data = ev.dataTransfer.getData('text'); if (!data) return; - let index = Math.floor((ev.clientY - this._active_columns.offsetTop) / this._active_columns.children[0].offsetHeight); + let index = calc_index.call(this, ev); let target = this._active_columns.children[index]; let old = Array.prototype.slice.call(this.querySelectorAll('#active_columns perspective-row')).find(x => x.getAttribute('name') === data); let newr = new_row.call(this, data); @@ -108,7 +140,8 @@ function drop(ev) { this.setAttribute(name, JSON.stringify(columns.concat([data]))); // Deselect the dropped column - if (this._visible_column_count() > 1 && name !== "sort") { + let isToggleMode = this._plugin.selectMode === "toggle"; + if (isToggleMode && this._visible_column_count() > 1 && name !== "sort") { for (let x of this.querySelectorAll("#active_columns perspective-row")) { if (x.getAttribute('name') === data) { this._active_columns.removeChild(x); @@ -274,7 +307,12 @@ function new_row(name, type, aggregate) { } row.addEventListener('visibility-clicked', column_visibility_clicked.bind(this)); row.addEventListener('aggregate-selected', column_aggregate_clicked.bind(this)); - row.addEventListener('row-drag', () => this.classList.add('dragging')); + row.addEventListener('row-drag', () => { + this.classList.add('dragging'); + // if (row.parentElement.getAttribute('id') === "active_columns") { + // setTimeout(() => row.parentElement.removeChild(row)); + // } + }); row.addEventListener('row-dragend', () => this.classList.remove('dragging')); return row; } @@ -715,12 +753,17 @@ registerElement(template, { this._sort.addEventListener('drop', drop.bind(this)); this._sort.addEventListener('dragend', undrag.bind(this)); + this._row_pivots.addEventListener('drop', drop.bind(this)); this._row_pivots.addEventListener('dragend', undrag.bind(this)); + this._column_pivots.addEventListener('drop', drop.bind(this)); this._column_pivots.addEventListener('dragend', undrag.bind(this)); + this._active_columns.addEventListener('drop', column_drop.bind(this)); this._active_columns.addEventListener('dragend', column_undrag.bind(this)); + this._active_columns.addEventListener('dragover', column_dragover.bind(this)); + this._active_columns.addEventListener('dragleave', column_dragleave.bind(this)); this.setAttribute('settings', true); this._show_config = true; diff --git a/packages/perspective-viewer/src/less/row.less b/packages/perspective-viewer/src/less/row.less index 18a5769833..a82e3ec627 100644 --- a/packages/perspective-viewer/src/less/row.less +++ b/packages/perspective-viewer/src/less/row.less @@ -43,6 +43,18 @@ perspective-viewer ul { transition: background-color 0.2s, border-color 0.2s; } +.dropping perspective-row.inserting { + margin-top: 25px; +} + +.dropping perspective-row.postserting { + margin-bottom: 25px; +} + +.dropping * { + pointer-events: none; +} + perspective-row li { color: rgb(51, 51, 51); margin-bottom: 2px; From 11fe56512c04601a0af3943fdf1974c7346174c0 Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Wed, 17 Jan 2018 17:39:25 -0500 Subject: [PATCH 05/13] Fixed CSS jitter bug in column drag & drop. --- packages/perspective-viewer/src/less/row.less | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/perspective-viewer/src/less/row.less b/packages/perspective-viewer/src/less/row.less index a82e3ec627..6c16fb254a 100644 --- a/packages/perspective-viewer/src/less/row.less +++ b/packages/perspective-viewer/src/less/row.less @@ -37,6 +37,7 @@ perspective-viewer.dragging #top_panel ul.dropping { perspective-row { display: block; + border: 0px solid rgba(0,0,0,0); } perspective-viewer ul { @@ -44,11 +45,11 @@ perspective-viewer ul { } .dropping perspective-row.inserting { - margin-top: 25px; + border-top: 25px solid rgba(0,0,0,0); } .dropping perspective-row.postserting { - margin-bottom: 25px; + border-bottom: 25px solid rgba(0,0,0,0); } .dropping * { From 92979c0a6a7bafa0ca822ba9e53e11b7216eb855 Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Fri, 19 Jan 2018 18:16:50 -0500 Subject: [PATCH 06/13] Modified drag behavior to remove dragged column when in the active columns list. --- packages/perspective-viewer/src/js/view.js | 124 ++++++++++-------- packages/perspective-viewer/src/less/row.less | 10 ++ 2 files changed, 80 insertions(+), 54 deletions(-) diff --git a/packages/perspective-viewer/src/js/view.js b/packages/perspective-viewer/src/js/view.js index 6e5a823c86..1ff59c82e2 100644 --- a/packages/perspective-viewer/src/js/view.js +++ b/packages/perspective-viewer/src/js/view.js @@ -66,60 +66,68 @@ function undrag(event) { } function calc_index(event) { - return Math.floor(event.offsetY / this._active_columns.children[0].offsetHeight); + return Math.floor((event.offsetY + this._active_columns.scrollTop) / this._active_columns.children[0].offsetHeight); } function column_undrag(event) { let data = event.target.parentElement.parentElement; Array.prototype.slice.call(this._active_columns.children).map(x => {x.className = '';}); - if (this._visible_column_count() > 1 && event.dataTransfer.dropEffect !== 'all') { + if (this._visible_column_count() > 1 && event.dataTransfer.dropEffect !== 'move') { + this._active_columns.removeChild(data); } + this._active_columns.classList.remove('dropping'); this._update_column_view(); this._update(); } function column_dragleave(event) { - if (!this._skip_drag) { - this._active_columns.classList.remove('dropping'); - } - this._skip_drag = false; + let src = event.relatedTarget; + while (src && src !== this._active_columns) { + src = src.parentElement; + } + if (src) { + return; + } + this._active_columns.classList.remove('dropping'); + if (this._drop_target_hover.parentElement === this._active_columns) { + this._active_columns.removeChild(this._drop_target_hover); + } + if (this._original_index !== -1) { + this._active_columns.insertBefore(this._drop_target_hover, this._active_columns.children[this._original_index]); + } + this._drop_target_hover.removeAttribute('drop-target'); } function column_dragover(event) { event.preventDefault(); - event.dataTransfer.dropEffect = 'all'; + event.dataTransfer.dropEffect = 'move'; if (event.currentTarget.className !== 'dropping') { - this._skip_drag = true; event.currentTarget.classList.add('dropping'); } + if (!this._drop_target_hover.hasAttribute('drop-target')) { + this._drop_target_hover.setAttribute('drop-target', true); + } let index = calc_index.call(this, event); if (this._active_columns.children[index]) { - if (this._active_columns.children[index].className !== 'inserting') { - Array.prototype.slice.call(this._active_columns.children).map(x => {x.className = '';}); - this._active_columns.children[index].className = 'inserting'; + if (!this._active_columns.children[index].hasAttribute('drop-target')) { + this._active_columns.insertBefore(this._drop_target_hover, this._active_columns.children[index]); } } else { - Array.prototype.slice.call(this._active_columns.children).map(x => {x.className = '';}); - this._active_columns.children[this._active_columns.children.length - 1].className = "postserting"; + this._active_columns.appendChild(this._drop_target_hover); } } function column_drop(ev) { ev.preventDefault(); ev.currentTarget.classList.remove('dropping'); + if (this._drop_target_hover.parentElement === this._active_columns) { + this._drop_target_hover.removeAttribute('drop-target'); + } Array.prototype.slice.call(this._active_columns.children).map(x => {x.className = '';}); let data = ev.dataTransfer.getData('text'); if (!data) return; - - let index = calc_index.call(this, ev); - let target = this._active_columns.children[index]; - let old = Array.prototype.slice.call(this.querySelectorAll('#active_columns perspective-row')).find(x => x.getAttribute('name') === data); - let newr = new_row.call(this, data); - this._active_columns.insertBefore(newr, target); - if (old) { - this._active_columns.removeChild(old); - } + this._update_column_view(); this._update(); } @@ -293,27 +301,44 @@ async function loadTable(table) { function new_row(name, type, aggregate) { let row = document.createElement('perspective-row'); - if (!aggregate) { - aggregate = JSON.parse(this.getAttribute('aggregates')).find(x => x.column === name).op; - } - if (!type) { - let all = Array.prototype.slice.call(this.querySelectorAll('#inactive_columns perspective-row')); - type = all.find(x => x.getAttribute('name') === name).getAttribute('type'); - } - row.setAttribute('type', type); - row.setAttribute('name', name); - if (aggregate) { - row.setAttribute('aggregate', aggregate); + if (name) { + if (!aggregate) { + let aggregates = JSON.parse(this.getAttribute('aggregates')); + if (aggregates) { + aggregate = aggregates.find(x => x.column === name).op; + } else { + aggregate = ''; + } + } + if (!type) { + let all = Array.prototype.slice.call(this.querySelectorAll('#inactive_columns perspective-row')); + if (all.length > 0) { + type = all.find(x => x.getAttribute('name') === name).getAttribute('type'); + } else { + type = ''; + } + } + row.setAttribute('type', type); + row.setAttribute('name', name); + if (aggregate) { + row.setAttribute('aggregate', aggregate); + } + row.addEventListener('visibility-clicked', column_visibility_clicked.bind(this)); + row.addEventListener('aggregate-selected', column_aggregate_clicked.bind(this)); + row.addEventListener('row-drag', () => { + this.classList.add('dragging'); + this._original_index = Array.prototype.slice.call(this._active_columns.children).indexOf(row); + if (this._original_index !== -1) { + this._drop_target_hover = row; + setTimeout(() => row.setAttribute('drop-target', true)); + } else { + this._drop_target_hover = new_row.call(this, name, type, aggregate); + } + }); + row.addEventListener('row-dragend', () => this.classList.remove('dragging')); + } else { + row.setAttribute('drop-target', true); } - row.addEventListener('visibility-clicked', column_visibility_clicked.bind(this)); - row.addEventListener('aggregate-selected', column_aggregate_clicked.bind(this)); - row.addEventListener('row-drag', () => { - this.classList.add('dragging'); - // if (row.parentElement.getAttribute('id') === "active_columns") { - // setTimeout(() => row.parentElement.removeChild(row)); - // } - }); - row.addEventListener('row-dragend', () => this.classList.remove('dragging')); return row; } @@ -624,10 +649,7 @@ registerElement(template, { this._column_pivots.appendChild(label); } else { pivots.map(function(pivot) { - let row = document.createElement('perspective-row'); - row.setAttribute('name', pivot); - row.addEventListener('row-drag', () => this.classList.add('dragging')); - row.addEventListener('row-dragend', () => this.classList.remove('dragging')); + let row = new_row.call(this, pivot); this._column_pivots.appendChild(row); }.bind(this)); } @@ -646,10 +668,7 @@ registerElement(template, { this._row_pivots.appendChild(label); } else { pivots.map(function(pivot) { - let row = document.createElement('perspective-row'); - row.setAttribute('name', pivot); - row.addEventListener('row-drag', () => this.classList.add('dragging')); - row.addEventListener('row-dragend', () => this.classList.remove('dragging')); + let row = new_row.call(this, pivot); this._row_pivots.appendChild(row); }.bind(this)); } @@ -684,10 +703,7 @@ registerElement(template, { this._sort.appendChild(label); } else { sort.map(function(s) { - let row = document.createElement('perspective-row'); - row.setAttribute('name', s); - row.addEventListener('row-drag', () => this.classList.add('dragging')); - row.addEventListener('row-dragend', () => this.classList.remove('dragging')); + let row = new_row.call(this, s); this._sort.appendChild(row); }.bind(this)); } diff --git a/packages/perspective-viewer/src/less/row.less b/packages/perspective-viewer/src/less/row.less index 6c16fb254a..42d691c08e 100644 --- a/packages/perspective-viewer/src/less/row.less +++ b/packages/perspective-viewer/src/less/row.less @@ -25,6 +25,16 @@ display: inline-block; } +#side_panel perspective-row[drop-target]:not(.off) { + .row_draggable { + background: none; + border: 1px solid rgba(0,0,0,0); + * { + display: none !important; + } + } +} + perspective-viewer.dragging #top_panel ul { border: 1px solid #1078d1 !important; margin-top: -2px; From c6a1ca3c90fd2bab77e8af77c1b2bb49e7f80423 Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Fri, 19 Jan 2018 21:22:32 -0500 Subject: [PATCH 07/13] Cleanup. --- packages/perspective-viewer/src/js/row.js | 1 - packages/perspective-viewer/src/js/view.js | 55 +++++++++---------- packages/perspective-viewer/src/less/row.less | 17 +++--- 3 files changed, 32 insertions(+), 41 deletions(-) diff --git a/packages/perspective-viewer/src/js/row.js b/packages/perspective-viewer/src/js/row.js index 17900da74d..93fa7ac0e9 100644 --- a/packages/perspective-viewer/src/js/row.js +++ b/packages/perspective-viewer/src/js/row.js @@ -93,7 +93,6 @@ registerElement(template, { this.dispatchEvent(new CustomEvent('row-drag')); }); li.addEventListener('dragend', ev => { - //ev.currentTarget.classList.remove('dropping'); this.dispatchEvent(new CustomEvent('row-dragend')); }); let visible = this.querySelector('.is_visible'); diff --git a/packages/perspective-viewer/src/js/view.js b/packages/perspective-viewer/src/js/view.js index 1ff59c82e2..2ee14b57ca 100644 --- a/packages/perspective-viewer/src/js/view.js +++ b/packages/perspective-viewer/src/js/view.js @@ -53,14 +53,14 @@ global.registerPlugin = function registerPlugin(name, plugin) { */ function undrag(event) { - let div = event.target.parentElement; - if (div) { - let parent = div.parentElement.parentElement; - let idx = Array.prototype.slice.call(parent.children).indexOf(div); - let attr_name = parent.getAttribute('id').replace('_', '-'); - let pivots = JSON.parse(this.getAttribute(attr_name)); - pivots.splice(idx, 1); - this.setAttribute(attr_name, JSON.stringify(pivots)); + let div = event.target.parentElement.parentElement; + let parent = div.parentElement; + let idx = Array.prototype.slice.call(parent.children).indexOf(div); + let attr_name = parent.getAttribute('id').replace('_', '-'); + let pivots = JSON.parse(this.getAttribute(attr_name)); + pivots.splice(idx, 1); + this.setAttribute(attr_name, JSON.stringify(pivots)); + if (event.dataTransfer.dropEffect !== 'move') { this._update(); } } @@ -73,12 +73,11 @@ function column_undrag(event) { let data = event.target.parentElement.parentElement; Array.prototype.slice.call(this._active_columns.children).map(x => {x.className = '';}); if (this._visible_column_count() > 1 && event.dataTransfer.dropEffect !== 'move') { - this._active_columns.removeChild(data); + this._update_column_view(); + this._update(); } this._active_columns.classList.remove('dropping'); - this._update_column_view(); - this._update(); } function column_dragleave(event) { @@ -86,17 +85,16 @@ function column_dragleave(event) { while (src && src !== this._active_columns) { src = src.parentElement; } - if (src) { - return; - } - this._active_columns.classList.remove('dropping'); - if (this._drop_target_hover.parentElement === this._active_columns) { - this._active_columns.removeChild(this._drop_target_hover); - } - if (this._original_index !== -1) { - this._active_columns.insertBefore(this._drop_target_hover, this._active_columns.children[this._original_index]); + if (src === null) { + this._active_columns.classList.remove('dropping'); + if (this._drop_target_hover.parentElement === this._active_columns) { + this._active_columns.removeChild(this._drop_target_hover); + } + if (this._original_index !== -1) { + this._active_columns.insertBefore(this._drop_target_hover, this._active_columns.children[this._original_index]); + } + this._drop_target_hover.removeAttribute('drop-target'); } - this._drop_target_hover.removeAttribute('drop-target'); } function column_dragover(event) { @@ -186,7 +184,7 @@ function column_visibility_clicked(ev) { ); this._active_columns.appendChild(row); } - let cols = this._view_columns('#active_columns perspective-row:not(.off)'); + let cols = this._view_columns('#active_columns perspective-row'); this.setAttribute('columns', JSON.stringify(cols)); this._update_column_view(cols); this._update(); @@ -285,12 +283,10 @@ async function loadTable(table) { .filter(a => a.column === x) .map(a => a.op)[0]; let row = new_row.call(this, x, schema[x], aggregate); - row.className = 'off'; this._inactive_columns.appendChild(row); if (shown.indexOf(x) !== -1) { row.style.display = 'none'; let active_row = new_row.call(this, x, schema[x], aggregate); - active_row.className = 'visible_' + (shown.indexOf(x) + 1); this._active_columns.appendChild(active_row); } } @@ -344,8 +340,8 @@ function new_row(name, type, aggregate) { function update() { if (!this._table) return; - let row_pivots = this._view_columns('#row_pivots perspective-row:not(.off)'); - let column_pivots = this._view_columns('#column_pivots perspective-row:not(.off)'); + let row_pivots = this._view_columns('#row_pivots perspective-row'); + let column_pivots = this._view_columns('#column_pivots perspective-row'); let filters = JSON.parse(this.getAttribute('filters')); let aggregates = this._get_view_aggregates(); if (aggregates.length === 0) return; @@ -354,7 +350,7 @@ function update() { column_pivots = []; } let hidden = []; - let sort = this._view_columns("#sort perspective-row:not(.off)"); + let sort = this._view_columns("#sort perspective-row"); for (let s of sort) { if (aggregates.map(function(agg) { return agg.column }).indexOf(s) === -1) { let all = this._get_view_aggregates('#inactive_columns perspective-row'); @@ -516,7 +512,7 @@ registerElement(template, { _get_view_aggregates: { value: function (selector) { - selector = selector || '#active_columns perspective-row:not(.off)'; + selector = selector || '#active_columns perspective-row'; return this._view_columns(selector, true); } }, @@ -540,8 +536,7 @@ registerElement(template, { _visible_column_count: { value: function() { let cols = Array.prototype.slice.call(this.querySelectorAll("#active_columns perspective-row")); - let off_cols = Array.prototype.slice.call(this.querySelectorAll("#active_columns perspective-row.off")); - return (cols.length - off_cols.length); + return cols.length; } }, diff --git a/packages/perspective-viewer/src/less/row.less b/packages/perspective-viewer/src/less/row.less index 42d691c08e..90a2a6c3ea 100644 --- a/packages/perspective-viewer/src/less/row.less +++ b/packages/perspective-viewer/src/less/row.less @@ -25,7 +25,7 @@ display: inline-block; } -#side_panel perspective-row[drop-target]:not(.off) { +#side_panel #active_columns perspective-row[drop-target] { .row_draggable { background: none; border: 1px solid rgba(0,0,0,0); @@ -104,7 +104,7 @@ perspective-row li { padding-left: 5px; } -#side_panel perspective-row:not(.off) div { +#side_panel #active_columns perspective-row div { .bordered(); background-color: white; } @@ -119,7 +119,7 @@ perspective-row li { margin-top: -2px; } -#side_panel perspective-row.off .is_visible::before { +#side_panel #inactive_columns perspective-row .is_visible::before { content: "\25CB"; } @@ -206,9 +206,6 @@ perspective-row .row_draggable select:focus { perspective-viewer[view=scatter], perspective-viewer[view=line] { #active_columns { - .off .is_visible::before { - content: "\25CB"; - } :nth-child(1) .is_visible::before { .selected_indicator(); content: "X"; @@ -228,17 +225,17 @@ perspective-viewer[view=scatter], perspective-viewer[view=line] { } } -perspective-viewer:not([row-pivots='[]']) #side_panel perspective-row:not(.off) #column_aggregate, -perspective-viewer:not([column-pivots='[]']) #side_panel perspective-row:not(.off) #column_aggregate { +perspective-viewer:not([row-pivots='[]']) #side_panel #active_columns perspective-row #column_aggregate, +perspective-viewer:not([column-pivots='[]']) #side_panel #active_columns perspective-row #column_aggregate { display: inline-block; } perspective-viewer:not([row-pivots='[]']) #side_panel, perspective-viewer:not([column-pivots='[]']) #side_panel { - perspective-row .row_draggable { + #active_columns perspective-row .row_draggable { height: 41px; } - perspective-row.off .row_draggable { + #inactive_columns perspective-row .row_draggable { height: 21px; } } From 83f2f19ba68060c7414509a9f976366ff40f7d47 Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Sun, 21 Jan 2018 11:08:27 -0500 Subject: [PATCH 08/13] Refined plugin behavior for new column selector. --- .../src/js/hypergrid.js | 1 + packages/perspective-viewer/src/js/row.js | 2 +- packages/perspective-viewer/src/js/view.js | 63 +++++++++++++------ 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/packages/perspective-viewer-hypergrid/src/js/hypergrid.js b/packages/perspective-viewer-hypergrid/src/js/hypergrid.js index ef4535d8f6..9708800f9a 100644 --- a/packages/perspective-viewer-hypergrid/src/js/hypergrid.js +++ b/packages/perspective-viewer-hypergrid/src/js/hypergrid.js @@ -716,6 +716,7 @@ global.registerPlugin("hypergrid", { name: "Grid", create: grid, selectMode: "toggle", + deselectMode: "pivots", resize: function () { if (this.hypergrid) { this.hypergrid.canvas.resize(); diff --git a/packages/perspective-viewer/src/js/row.js b/packages/perspective-viewer/src/js/row.js index 93fa7ac0e9..6da43bd418 100644 --- a/packages/perspective-viewer/src/js/row.js +++ b/packages/perspective-viewer/src/js/row.js @@ -27,8 +27,8 @@ global.dragEnter = function dragEnter(ev) { global.allowDrop = function allowDrop(ev) { ev.preventDefault(); - ev.dataTransfer.dropEffect = 'all'; ev.currentTarget.classList.add('dropping'); + ev.dataTransfer.dropEffect = 'move'; } global.disallowDrop = function disallowDrop(ev) { diff --git a/packages/perspective-viewer/src/js/view.js b/packages/perspective-viewer/src/js/view.js index 2ee14b57ca..0a88a6d11a 100644 --- a/packages/perspective-viewer/src/js/view.js +++ b/packages/perspective-viewer/src/js/view.js @@ -66,7 +66,8 @@ function undrag(event) { } function calc_index(event) { - return Math.floor((event.offsetY + this._active_columns.scrollTop) / this._active_columns.children[0].offsetHeight); + let height = this._active_columns.children[0].offsetHeight; + return Math.round((event.offsetY + this._active_columns.scrollTop) / height); } function column_undrag(event) { @@ -75,7 +76,6 @@ function column_undrag(event) { if (this._visible_column_count() > 1 && event.dataTransfer.dropEffect !== 'move') { this._active_columns.removeChild(data); this._update_column_view(); - this._update(); } this._active_columns.classList.remove('dropping'); } @@ -127,7 +127,6 @@ function column_drop(ev) { if (!data) return; this._update_column_view(); - this._update(); } function drop(ev) { @@ -146,8 +145,7 @@ function drop(ev) { this.setAttribute(name, JSON.stringify(columns.concat([data]))); // Deselect the dropped column - let isToggleMode = this._plugin.selectMode === "toggle"; - if (isToggleMode && this._visible_column_count() > 1 && name !== "sort") { + if (this._plugin.deselectMode === "pivots" && this._visible_column_count() > 1 && name !== "sort") { for (let x of this.querySelectorAll("#active_columns perspective-row")) { if (x.getAttribute('name') === data) { this._active_columns.removeChild(x); @@ -167,27 +165,32 @@ function drop(ev) { */ function column_visibility_clicked(ev) { - let className = `visible_${this._visible_column_count() + 1}`; let parent = ev.currentTarget; - let is_active = parent.parentElement.getAttribute('id') === 'active_columns';; + let is_active = parent.parentElement.getAttribute('id') === 'active_columns'; if (is_active) { - if (this._visible_column_count() === 1 ) { + if (this._visible_column_count() === 1) { return; } - this._active_columns.removeChild(parent); + if (ev.detail.shiftKey) { + for (let child of Array.prototype.slice.call(this._active_columns.children)) { + if (child !== parent) { + this._active_columns.removeChild(child); + } + } + } else { + this._active_columns.removeChild(parent); + } } else { - let row = new_row.call( - this, - parent.getAttribute('name'), - parent.getAttribute('type'), - JSON.parse(this.getAttribute('aggregates')).find(x => x.column === parent.getAttribute('name')).op - ); + if (ev.detail.shiftKey && this._plugin.selectMode === 'toggle' || !ev.detail.shiftKey && this._plugin.selectMode === 'select') { + for (let child of Array.prototype.slice.call(this._active_columns.children)) { + this._active_columns.removeChild(child); + } + } + let row = new_row.call(this, parent.getAttribute('name'), parent.getAttribute('type')); this._active_columns.appendChild(row); } let cols = this._view_columns('#active_columns perspective-row'); - this.setAttribute('columns', JSON.stringify(cols)); this._update_column_view(cols); - this._update(); } function column_aggregate_clicked() { @@ -404,6 +407,8 @@ function update() { if (this._render_count === 0) { this.removeAttribute('updating'); } + }).catch(() => { + console.debug("View cancelled"); }); } @@ -545,6 +550,7 @@ registerElement(template, { if (!columns) { columns = this._view_columns('#active_columns perspective-row'); } + this.setAttribute('columns', JSON.stringify(columns)); let idx = 1; const lis = Array.prototype.slice.call(this.querySelectorAll("#inactive_columns perspective-row")); lis.forEach(x => { @@ -620,11 +626,30 @@ registerElement(template, { }, view: { - set: function () { + set: async function () { this._vis_selector.value = this.getAttribute('view'); let cols = Array.prototype.slice.call(this.querySelectorAll("#inactive_columns perspective-row")); if (cols.length > 0) { - if (this._plugin.selectMode === 'select') { + if (this._plugin.initial) { + let pref = []; + let count = this._plugin.initial.count || 2; + if (this._plugin.initial.type === 'number') { + for (let col of cols) { + let type = col.getAttribute('type'); + if (['float', 'integer'].indexOf(type) > -1) { + pref.push(col.getAttribute('name')); + } + } + if (pref.length < count) { + for (let col of cols) { + if (pref.indexOf(col.getAttribute('name')) === -1) { + pref.push(col.getAttribute('name')); + } + } + } + } + this.setAttribute('columns', JSON.stringify(pref.slice(0, count))); + } else if (this._plugin.selectMode === 'select') { this.setAttribute('columns', JSON.stringify([cols[0].getAttribute('name')])); } else { this.setAttribute('columns', JSON.stringify(cols.map(x => x.getAttribute('name')))); From 5cd4ba8f9dc8a56e4fc23f7a9985b93dbd3ccadb Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Sun, 21 Jan 2018 11:09:10 -0500 Subject: [PATCH 09/13] Updated tests. --- .../src/js/highcharts.js | 23 +++++++++- .../test/results/results.json | 42 +++++++++---------- .../src/js/hypergrid-tree-cell-renderer.js | 2 +- .../test/js/superstore.spec.js | 4 +- .../test/results/results.json | 20 ++++----- .../test/results/results.json | 16 +++---- 6 files changed, 63 insertions(+), 44 deletions(-) diff --git a/packages/perspective-viewer-highcharts/src/js/highcharts.js b/packages/perspective-viewer-highcharts/src/js/highcharts.js index 0e96a818f0..a3cf86a2c3 100644 --- a/packages/perspective-viewer-highcharts/src/js/highcharts.js +++ b/packages/perspective-viewer-highcharts/src/js/highcharts.js @@ -372,6 +372,9 @@ export function draw(mode) { }); } Object.assign(config, { + colors: [ + colors[0] + ], xAxis: { type: xaxis_type === "date" ? "datetime" : undefined, startOnTick: false, @@ -518,6 +521,10 @@ global.registerPlugin("vertical", { name: "Bar Chart", create: draw("vertical_bar"), resize: resize, + initial: { + "type": "number", + "count": 1 + }, selectMode: "select", delete: delete_chart }); @@ -526,6 +533,10 @@ global.registerPlugin("horizontal", { name: "Bar Chart (inverted)", create: draw("horizontal_bar"), resize: resize, + initial: { + "type": "number", + "count": 1 + }, selectMode: "select", delete: delete_chart }); @@ -534,7 +545,11 @@ global.registerPlugin("line", { name: "Line Chart", create: draw("line"), resize: resize, - selectMode: "select", + initial: { + "type": "number", + "count": 2 + }, + selectMode: "toggle", delete: delete_chart }); @@ -542,7 +557,11 @@ global.registerPlugin("scatter", { name: "Scatter Chart", create: draw('scatter'), resize: resize, - selectMode: "select", + initial: { + "type": "number", + "count": 2 + }, + selectMode: "toggle", delete: delete_chart }); diff --git a/packages/perspective-viewer-highcharts/test/results/results.json b/packages/perspective-viewer-highcharts/test/results/results.json index 33608a084f..63f1bbca76 100644 --- a/packages/perspective-viewer-highcharts/test/results/results.json +++ b/packages/perspective-viewer-highcharts/test/results/results.json @@ -8,27 +8,27 @@ "superstore.html/sorts by an alpha column.": "2643e0b5787b6e8e85f122b1713d01cd", "superstore.html/displays visible columns.": "1da296527f149393be8f3f99e34b3e4a", "scatter.html/shows a grid without any settings applied.": "352854b8fa9466ddf9f884462f1fcfbf", - "scatter.html/pivots by a row.": "d747a811424247f2e82fbd1f3e4b102d", - "scatter.html/pivots by two rows.": "327f10b204fc30b4f09a3c78b0fb0789", - "scatter.html/pivots by a row and a column.": "aefd420b9568e75b2e4aa28fa48e78b2", - "scatter.html/pivots by two rows and two columns.": "5f32d38e1d95c92f29578d18ebd6f917", - "scatter.html/sorts by a numeric column.": "a5cea557d54498d931272f9aba20cb38", - "scatter.html/sorts by an alpha column.": "bcf36f6eaaa17eada7c284e6257cf6a7", - "scatter.html/displays visible columns.": "7f4568381b35950da01a23b7a13fa216", + "scatter.html/pivots by a row.": "c83bb7518a026a223241652958b3dfb0", + "scatter.html/pivots by two rows.": "4f180e399b2e7c0e99df1bffd3326afb", + "scatter.html/pivots by a row and a column.": "06d1400c500d94dcb84d36bf7181bb6e", + "scatter.html/pivots by two rows and two columns.": "8076a1aa797aa57c3e09977bb12a49e3", + "scatter.html/sorts by a numeric column.": "384eea0345e7a35e444f26aa3eb3d208", + "scatter.html/sorts by an alpha column.": "fac0df141d22b3868d87e1ce30c9a045", + "scatter.html/displays visible columns.": "dcffcd6d23534d745ee0816ab11a71ce", "bar.html/shows a grid without any settings applied.": "fa9f33409c8409155b403c30e97b9397", - "bar.html/pivots by a row.": "667024057e32ac7dcff85f714e991345", - "bar.html/pivots by two rows.": "38985a461a70412e91ba04ed08630f56", - "bar.html/pivots by a row and a column.": "d3c12fafa6aa6e48a65fb772633db007", - "bar.html/pivots by two rows and two columns.": "f8541acf149555a07db51b75fe25b3de", - "bar.html/sorts by a numeric column.": "89ca3dd689ac395e44e77520845055f4", - "bar.html/sorts by an alpha column.": "9116319b7b31aed9beba0632e474ddf0", + "bar.html/pivots by a row.": "8848040374bbf4817169054d69b88012", + "bar.html/pivots by two rows.": "d3f8bf092cb96bd753b7a94597f0af8a", + "bar.html/pivots by a row and a column.": "ad663c1e96648ca4fa2efdd1c458e6d1", + "bar.html/pivots by two rows and two columns.": "b1109c198404146f5b24bc85b3169002", + "bar.html/sorts by a numeric column.": "fe61f4c5f7e36e5b44e180b8d59da0ce", + "bar.html/sorts by an alpha column.": "fcbe1b22ab0875ba61969823f096b96a", "line.html/shows a grid without any settings applied.": "5c7d75d2872635968019ef08bc505ff3", - "line.html/pivots by a row.": "a5c448c1f00f22657dae1ce3e059b075", - "line.html/pivots by two rows.": "1944115018252f8dceb03f84fab2ebf4", - "line.html/pivots by a row and a column.": "79c490c3f843b24af104b6681685b82f", - "line.html/pivots by two rows and two columns.": "2199f0cb57cdab991f9a62c5c277e3b3", - "line.html/sorts by a numeric column.": "604f906365754839e95d0c7f01f15241", - "line.html/sorts by an alpha column.": "a9cf05d78de91c435055049ed538d1ad", - "line.html/displays visible columns.": "010890a5ebf5e4bd32557191a6b11c27", - "bar.html/displays visible columns.": "a5662668dffce69048d1823052a83ab6" + "line.html/pivots by a row.": "08a29f9475d0f20cb3d4c222e39bce2d", + "line.html/pivots by two rows.": "30d68c75a3fb96af91958cc5a28f66c2", + "line.html/pivots by a row and a column.": "fa8d53bf92b5eeb9daafcb04d8da07b0", + "line.html/pivots by two rows and two columns.": "87ddd8a09a18f1c15c4a9c7569cbb0cb", + "line.html/sorts by a numeric column.": "5c87dd9ff1f99bc0f050e247bc31b297", + "line.html/sorts by an alpha column.": "81eaf4a5de51953b7ec28250d5b050d9", + "line.html/displays visible columns.": "80d6712db433c15efe24d43d32987b9c", + "bar.html/displays visible columns.": "0a602ffdcb9bb75fcfd0fddf96ce4adc" } \ No newline at end of file diff --git a/packages/perspective-viewer-hypergrid/src/js/hypergrid-tree-cell-renderer.js b/packages/perspective-viewer-hypergrid/src/js/hypergrid-tree-cell-renderer.js index 6fa216c0f7..03bfe58f4f 100644 --- a/packages/perspective-viewer-hypergrid/src/js/hypergrid-tree-cell-renderer.js +++ b/packages/perspective-viewer-hypergrid/src/js/hypergrid-tree-cell-renderer.js @@ -160,7 +160,7 @@ export function treeLineRendererPaint(gc, config) { // render message text var cellTextOffset = xOffset + lineNodeSpace + (2 * nodeRadius) + 3; - config.minWidth = cellTextOffset + gc.getTextWidth(value); + config.minWidth = cellTextOffset + gc.getTextWidth(value) + 15; var metrics = gc.getTextWidthTruncated(value, width - cellTextOffset + (x - 3), true); var yOffset = y + height / 2; diff --git a/packages/perspective-viewer-hypergrid/test/js/superstore.spec.js b/packages/perspective-viewer-hypergrid/test/js/superstore.spec.js index ccb7bf34c8..935dee8bd1 100644 --- a/packages/perspective-viewer-hypergrid/test/js/superstore.spec.js +++ b/packages/perspective-viewer-hypergrid/test/js/superstore.spec.js @@ -14,8 +14,8 @@ const simple_tests = require('@jpmorganchase/perspective-viewer/test/js/simple_t async function set_lazy(page) { const viewer = await page.$('perspective-viewer'); await page.evaluate(element => { - element.grid.grid.properties.repaintIntervalRate = 1; - Object.defineProperty(element.grid.grid, '_lazy_load', { + element.hypergrid.properties.repaintIntervalRate = 1; + Object.defineProperty(element.hypergrid, '_lazy_load', { set: () => {}, get: () => true }); diff --git a/packages/perspective-viewer-hypergrid/test/results/results.json b/packages/perspective-viewer-hypergrid/test/results/results.json index 32d1c9ca23..a63fb2ec94 100644 --- a/packages/perspective-viewer-hypergrid/test/results/results.json +++ b/packages/perspective-viewer-hypergrid/test/results/results.json @@ -1,13 +1,13 @@ { - "superstore.html/shows a grid without any settings applied.": "b09dc5301dbfe6afbfcd2dc58843a475", - "superstore.html/pivots by a row.": "5260127d95553860fcc9ad56768ea427", - "superstore.html/pivots by two rows.": "f53fdf0be253dc4a3c5d86a03c50044f", - "superstore.html/pivots by a row and a column.": "47ea6ae4282c002c2da57d3e2008646d", - "superstore.html/pivots by two rows and two columns.": "c3939b8853d3db3d380fa3936dfb0559", - "superstore.html/sorts by a numeric column.": "2eb4a45b85bedbdd2cef8bb8c712ed5c", - "superstore.html/sorts by an alpha column.": "f99960fb04d633f96a190df6f55ed000", - "superstore.html/displays visible columns.": "95ea7a90e503ed69e4cc87b9f71adbb4", - "superstore.html/resets viewable area when the logical size expands.": "a7933b107656467730a115cec818d625", + "superstore.html/shows a grid without any settings applied.": "45055f06b933226373579c5e3b03608f", + "superstore.html/pivots by a row.": "95ffdf460138b9f2aab4d9e0362d281b", + "superstore.html/pivots by two rows.": "2f5f9fe6a82fca7e5320d9996eeae559", + "superstore.html/pivots by a row and a column.": "4dae593930a024e6e45ae3e902ded425", + "superstore.html/pivots by two rows and two columns.": "0f4423864bb5ac00fb002c386f42327c", + "superstore.html/sorts by a numeric column.": "b1cab634c6f028aadca4cb80d45da0d2", + "superstore.html/sorts by an alpha column.": "75f2524a106af8f9f5a032561cf8ffbd", + "superstore.html/displays visible columns.": "5e92e91cfbfa7dd864e3381bd834dfab", + "superstore.html/resets viewable area when the logical size expands.": "4f9d1618cff5784f37df5b2df59cb6f4", "superstore.html/selecting a column does not log a context deleted error.": "2563581d3556c4576745443c8498bea9", - "superstore.html/resets viewable area when the physical size expands.": "75b1b246d3c2612c45fc6c5bc7c3660a" + "superstore.html/resets viewable area when the physical size expands.": "b5e7dffa2272e6b6daf465a9af34e2bc" } \ No newline at end of file diff --git a/packages/perspective-viewer/test/results/results.json b/packages/perspective-viewer/test/results/results.json index fcdcb22b9b..9ffe312f79 100644 --- a/packages/perspective-viewer/test/results/results.json +++ b/packages/perspective-viewer/test/results/results.json @@ -1,10 +1,10 @@ { - "superstore.html/shows a grid without any settings applied.": "89e50a02a581c0ec0610660b7af67e1e", - "superstore.html/pivots by a row.": "6fd6521a3a908a678629b23ca381c10e", - "superstore.html/pivots by two rows.": "656872f1dfa4fe132376d5a5e9221b35", - "superstore.html/pivots by a row and a column.": "1b693f650b72df5f1f5c164c0c21beb4", - "superstore.html/pivots by two rows and two columns.": "2335011f6dc880625fbfd2f10f5ef855", - "superstore.html/sorts by a numeric column.": "e07143017f6332fb93e3be6e69b1e60c", - "superstore.html/sorts by an alpha column.": "05b1cde9ac31f8bc2c97e58fc8d02db9", - "superstore.html/displays visible columns.": "09a40d453aa64f9149a9a1f84892a619" + "superstore.html/shows a grid without any settings applied.": "62f58d51fe9982d5ca97ec3918ccfe9d", + "superstore.html/pivots by a row.": "f46713763478eecb75c2e54fcf2ee9d4", + "superstore.html/pivots by two rows.": "c21dda81745dfa364ec73d8ee46a074a", + "superstore.html/pivots by a row and a column.": "4d6e52e61fbf43e6e649efaffe272c4d", + "superstore.html/pivots by two rows and two columns.": "d490b3e5152e3f34defb939e757e528d", + "superstore.html/sorts by a numeric column.": "d6c7644f33430b2292d9e8d59eb5604c", + "superstore.html/sorts by an alpha column.": "449a90651fdb2b551a1bf1836c9f4b85", + "superstore.html/displays visible columns.": "5c93ab09c5949037fda5314c56c85295" } \ No newline at end of file From 2c73e09003a0fe2cc17c597b882162a78ff230ba Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Sun, 21 Jan 2018 11:48:30 -0500 Subject: [PATCH 10/13] Fixed performance bug which caused a dragged node to be inserted before itself. --- packages/perspective-viewer/src/js/view.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/perspective-viewer/src/js/view.js b/packages/perspective-viewer/src/js/view.js index 0a88a6d11a..419936fe80 100644 --- a/packages/perspective-viewer/src/js/view.js +++ b/packages/perspective-viewer/src/js/view.js @@ -107,12 +107,14 @@ function column_dragover(event) { this._drop_target_hover.setAttribute('drop-target', true); } let index = calc_index.call(this, event); - if (this._active_columns.children[index]) { - if (!this._active_columns.children[index].hasAttribute('drop-target')) { + if (index < this._active_columns.children.length) { + if (!this._active_columns.children[Math.max(index - 1, 0)].hasAttribute('drop-target') && !this._active_columns.children[index].hasAttribute('drop-target')) { this._active_columns.insertBefore(this._drop_target_hover, this._active_columns.children[index]); } } else { - this._active_columns.appendChild(this._drop_target_hover); + if (!this._active_columns.children[this._active_columns.children.length - 1].hasAttribute('drop-target')) { + this._active_columns.appendChild(this._drop_target_hover); + } } } From 64bf6f4a56f503c123b87bba5cf2b720a6ac82aa Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Sun, 21 Jan 2018 11:48:43 -0500 Subject: [PATCH 11/13] Added drag animation. --- packages/perspective-viewer/src/less/row.less | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/perspective-viewer/src/less/row.less b/packages/perspective-viewer/src/less/row.less index 90a2a6c3ea..18d7cfdd87 100644 --- a/packages/perspective-viewer/src/less/row.less +++ b/packages/perspective-viewer/src/less/row.less @@ -25,10 +25,22 @@ display: inline-block; } +@keyframes fadein { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + #side_panel #active_columns perspective-row[drop-target] { .row_draggable { - background: none; - border: 1px solid rgba(0,0,0,0); + animation-duration: 0.5s; + animation-name: fadein; + background-color: rgb(240, 240, 255) !important; + border: 1px solid #1078d1 !important; * { display: none !important; } From ffa17bb6e592e42315c87c89ab12da9bb6569d80 Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Sun, 21 Jan 2018 21:51:14 -0500 Subject: [PATCH 12/13] Update test regression. --- .../perspective-viewer-highcharts/test/results/results.json | 2 +- packages/perspective-viewer-hypergrid/src/js/hypergrid.js | 2 -- .../perspective-viewer-hypergrid/test/results/results.json | 4 ++-- packages/perspective-viewer/test/js/simple_tests.js | 2 ++ 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/perspective-viewer-highcharts/test/results/results.json b/packages/perspective-viewer-highcharts/test/results/results.json index 63f1bbca76..97beabef67 100644 --- a/packages/perspective-viewer-highcharts/test/results/results.json +++ b/packages/perspective-viewer-highcharts/test/results/results.json @@ -14,7 +14,7 @@ "scatter.html/pivots by two rows and two columns.": "8076a1aa797aa57c3e09977bb12a49e3", "scatter.html/sorts by a numeric column.": "384eea0345e7a35e444f26aa3eb3d208", "scatter.html/sorts by an alpha column.": "fac0df141d22b3868d87e1ce30c9a045", - "scatter.html/displays visible columns.": "dcffcd6d23534d745ee0816ab11a71ce", + "scatter.html/displays visible columns.": "7a919ee86624d9b91c6c494214a9f3f1", "bar.html/shows a grid without any settings applied.": "fa9f33409c8409155b403c30e97b9397", "bar.html/pivots by a row.": "8848040374bbf4817169054d69b88012", "bar.html/pivots by two rows.": "d3f8bf092cb96bd753b7a94597f0af8a", diff --git a/packages/perspective-viewer-hypergrid/src/js/hypergrid.js b/packages/perspective-viewer-hypergrid/src/js/hypergrid.js index 9708800f9a..0579bd36cb 100644 --- a/packages/perspective-viewer-hypergrid/src/js/hypergrid.js +++ b/packages/perspective-viewer-hypergrid/src/js/hypergrid.js @@ -707,9 +707,7 @@ async function grid(div, view, hidden, redraw, task) { this[PRIVATE].grid.set_data(json, schema); await this.hypergrid.canvas.resize(); - await this.hypergrid._updating_cache; await this.hypergrid.canvas.resize(); - await this.hypergrid._updating_cache; } global.registerPlugin("hypergrid", { diff --git a/packages/perspective-viewer-hypergrid/test/results/results.json b/packages/perspective-viewer-hypergrid/test/results/results.json index a63fb2ec94..d534713179 100644 --- a/packages/perspective-viewer-hypergrid/test/results/results.json +++ b/packages/perspective-viewer-hypergrid/test/results/results.json @@ -2,8 +2,8 @@ "superstore.html/shows a grid without any settings applied.": "45055f06b933226373579c5e3b03608f", "superstore.html/pivots by a row.": "95ffdf460138b9f2aab4d9e0362d281b", "superstore.html/pivots by two rows.": "2f5f9fe6a82fca7e5320d9996eeae559", - "superstore.html/pivots by a row and a column.": "4dae593930a024e6e45ae3e902ded425", - "superstore.html/pivots by two rows and two columns.": "0f4423864bb5ac00fb002c386f42327c", + "superstore.html/pivots by a row and a column.": "8b46d8d101f643e1caeb21286bb88e32", + "superstore.html/pivots by two rows and two columns.": "570d8ffd63c3c2c7ebdd0b13e0aa5543", "superstore.html/sorts by a numeric column.": "b1cab634c6f028aadca4cb80d45da0d2", "superstore.html/sorts by an alpha column.": "75f2524a106af8f9f5a032561cf8ffbd", "superstore.html/displays visible columns.": "5e92e91cfbfa7dd864e3381bd834dfab", diff --git a/packages/perspective-viewer/test/js/simple_tests.js b/packages/perspective-viewer/test/js/simple_tests.js index 3a00a317e9..2689f12ad6 100644 --- a/packages/perspective-viewer/test/js/simple_tests.js +++ b/packages/perspective-viewer/test/js/simple_tests.js @@ -28,6 +28,7 @@ exports.default = function() { await page.click('#config_button'); const viewer = await page.$('perspective-viewer'); await page.evaluate(element => element.setAttribute('row-pivots', '["State"]'), viewer); + await page.waitForSelector('perspective-viewer:not([updating])'); await page.evaluate(element => element.setAttribute('column-pivots', '["Category"]'), viewer); }); @@ -35,6 +36,7 @@ exports.default = function() { await page.click('#config_button'); const viewer = await page.$('perspective-viewer'); await page.evaluate(element => element.setAttribute('row-pivots', '["Region","State"]'), viewer); + await page.waitForSelector('perspective-viewer:not([updating])'); await page.evaluate(element => element.setAttribute('column-pivots', '["Category","Sub-Category"]'), viewer); }); From 2d07b2d50804f95fcf1e5ec830bd8ee6e8bac3a7 Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Sun, 21 Jan 2018 22:51:23 -0500 Subject: [PATCH 13/13] Fix CSS issues for large column sets which trigger scroll. --- .../src/js/hypergrid-tree-cell-renderer.js | 8 ++++---- .../test/results/results.json | 10 +++++----- packages/perspective-viewer/src/html/view.html | 2 +- packages/perspective-viewer/src/js/view.js | 10 ++++++++++ packages/perspective-viewer/src/less/view.less | 11 +++++++++++ packages/perspective-viewer/test/results/results.json | 8 ++++---- 6 files changed, 35 insertions(+), 14 deletions(-) diff --git a/packages/perspective-viewer-hypergrid/src/js/hypergrid-tree-cell-renderer.js b/packages/perspective-viewer-hypergrid/src/js/hypergrid-tree-cell-renderer.js index 03bfe58f4f..46c8ccf31a 100644 --- a/packages/perspective-viewer-hypergrid/src/js/hypergrid-tree-cell-renderer.js +++ b/packages/perspective-viewer-hypergrid/src/js/hypergrid-tree-cell-renderer.js @@ -159,16 +159,16 @@ export function treeLineRendererPaint(gc, config) { gc.closePath(); // render message text - var cellTextOffset = xOffset + lineNodeSpace + (2 * nodeRadius) + 3; - config.minWidth = cellTextOffset + gc.getTextWidth(value) + 15; - var metrics = gc.getTextWidthTruncated(value, width - cellTextOffset + (x - 3), true); - var yOffset = y + height / 2; gc.globalAlpha = 1.0; gc.fillStyle = config.isSelected ? config.foregroundSelectionColor : config.color; gc.textAlign = 'start'; gc.textBaseline = 'middle'; gc.font = config.isSelected ? config.foregroundSelectionFont : config.treeHeaderFont; + var cellTextOffset = xOffset + lineNodeSpace + (2 * nodeRadius) + 3; + config.minWidth = cellTextOffset + gc.getTextWidth(value) + 15; + var metrics = gc.getTextWidthTruncated(value, width - cellTextOffset + (x - 3), true); + var yOffset = y + height / 2; gc.fillText(metrics.string ? metrics.string : value, cellTextOffset, yOffset); gc.restore(); } diff --git a/packages/perspective-viewer-hypergrid/test/results/results.json b/packages/perspective-viewer-hypergrid/test/results/results.json index d534713179..cb75c484aa 100644 --- a/packages/perspective-viewer-hypergrid/test/results/results.json +++ b/packages/perspective-viewer-hypergrid/test/results/results.json @@ -1,13 +1,13 @@ { "superstore.html/shows a grid without any settings applied.": "45055f06b933226373579c5e3b03608f", - "superstore.html/pivots by a row.": "95ffdf460138b9f2aab4d9e0362d281b", - "superstore.html/pivots by two rows.": "2f5f9fe6a82fca7e5320d9996eeae559", - "superstore.html/pivots by a row and a column.": "8b46d8d101f643e1caeb21286bb88e32", - "superstore.html/pivots by two rows and two columns.": "570d8ffd63c3c2c7ebdd0b13e0aa5543", + "superstore.html/pivots by a row.": "02d1622170029c721ef995904e13330c", + "superstore.html/pivots by two rows.": "fd0b7398c8d49d790ffcf04f9902f3a8", + "superstore.html/pivots by a row and a column.": "88656add4d88bd3abf76496f4ec2f9d7", + "superstore.html/pivots by two rows and two columns.": "e987eee39602ed26060cbb60f7de0618", "superstore.html/sorts by a numeric column.": "b1cab634c6f028aadca4cb80d45da0d2", "superstore.html/sorts by an alpha column.": "75f2524a106af8f9f5a032561cf8ffbd", "superstore.html/displays visible columns.": "5e92e91cfbfa7dd864e3381bd834dfab", - "superstore.html/resets viewable area when the logical size expands.": "4f9d1618cff5784f37df5b2df59cb6f4", + "superstore.html/resets viewable area when the logical size expands.": "cde73369571f2d991f683add8b894ae3", "superstore.html/selecting a column does not log a context deleted error.": "2563581d3556c4576745443c8498bea9", "superstore.html/resets viewable area when the physical size expands.": "b5e7dffa2272e6b6daf465a9af34e2bc" } \ No newline at end of file diff --git a/packages/perspective-viewer/src/html/view.html b/packages/perspective-viewer/src/html/view.html index bd2d564cb9..43de5b07fb 100644 --- a/packages/perspective-viewer/src/html/view.html +++ b/packages/perspective-viewer/src/html/view.html @@ -11,7 +11,7 @@
              -
              +
              diff --git a/packages/perspective-viewer/src/js/view.js b/packages/perspective-viewer/src/js/view.js index 419936fe80..de0221858f 100644 --- a/packages/perspective-viewer/src/js/view.js +++ b/packages/perspective-viewer/src/js/view.js @@ -295,6 +295,11 @@ async function loadTable(table) { this._active_columns.appendChild(active_row); } } + if (cols.length === shown.length) { + this._inactive_columns.style.display = 'none'; + } else { + this._inactive_columns.style.display = 'block'; + } this._filter_input.innerHTML = ""; this._update(); @@ -555,6 +560,11 @@ registerElement(template, { this.setAttribute('columns', JSON.stringify(columns)); let idx = 1; const lis = Array.prototype.slice.call(this.querySelectorAll("#inactive_columns perspective-row")); + if (columns.length === lis.length) { + this._inactive_columns.style.display = 'none'; + } else { + this._inactive_columns.style.display = 'block'; + } lis.forEach(x => { const index = columns.indexOf(x.getAttribute('name')); if (index === -1) { diff --git a/packages/perspective-viewer/src/less/view.less b/packages/perspective-viewer/src/less/view.less index d2ff2b2976..681b38e5d7 100644 --- a/packages/perspective-viewer/src/less/view.less +++ b/packages/perspective-viewer/src/less/view.less @@ -104,8 +104,15 @@ perspective-viewer { margin-top: 8px; overflow-y: auto; } + + #inactive_columns { + min-height: 20%; + flex-shrink: 1000; + } + #divider { background-color: #CCC; + min-height: 2px; height: 2px; margin: 15px 13px 15px 13px; margin-bottom: 5px; @@ -266,6 +273,10 @@ perspective-viewer { display: flex; } + #vis_selector_container { + min-height: 29px; + } + #vis_selector { flex-grow: 1; margin-top: 5px; diff --git a/packages/perspective-viewer/test/results/results.json b/packages/perspective-viewer/test/results/results.json index 9ffe312f79..632596eb9c 100644 --- a/packages/perspective-viewer/test/results/results.json +++ b/packages/perspective-viewer/test/results/results.json @@ -1,9 +1,9 @@ { "superstore.html/shows a grid without any settings applied.": "62f58d51fe9982d5ca97ec3918ccfe9d", - "superstore.html/pivots by a row.": "f46713763478eecb75c2e54fcf2ee9d4", - "superstore.html/pivots by two rows.": "c21dda81745dfa364ec73d8ee46a074a", - "superstore.html/pivots by a row and a column.": "4d6e52e61fbf43e6e649efaffe272c4d", - "superstore.html/pivots by two rows and two columns.": "d490b3e5152e3f34defb939e757e528d", + "superstore.html/pivots by a row.": "9d90435fb0038fd5c7b937add1b3daef", + "superstore.html/pivots by two rows.": "ffed18e53b9fa0037968f10995711644", + "superstore.html/pivots by a row and a column.": "551f259b4960e2a4bcb067396d59666a", + "superstore.html/pivots by two rows and two columns.": "94eb636829716456a6f3d578b66d5ab6", "superstore.html/sorts by a numeric column.": "d6c7644f33430b2292d9e8d59eb5604c", "superstore.html/sorts by an alpha column.": "449a90651fdb2b551a1bf1836c9f4b85", "superstore.html/displays visible columns.": "5c93ab09c5949037fda5314c56c85295"