Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move drag/drop into separate file, clean up row, move detectIE/detectChrome from perspective into perspective-viewer #293

Merged
merged 1 commit into from
Nov 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions packages/perspective-viewer-highcharts/src/js/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ import {COLORS_10, COLORS_20} from "./externals.js";
import {color_axis} from "./color_axis.js";
import {make_tree_data, make_y_data, make_xy_data, make_xyz_data, make_xy_column_data} from "./series.js";
import {set_boost, set_category_axis, set_both_axis, default_config, set_tick_size} from "./config.js";
import {bindTemplate} from "../../../perspective-viewer/src/js/utils";
import {detectIE} from "../../../perspective/src/js/utils";
import {bindTemplate, detectIE} from "../../../perspective-viewer/src/js/utils";

export const PRIVATE = Symbol("Highcharts private");

Expand Down
4 changes: 2 additions & 2 deletions packages/perspective-viewer/src/html/computed_column.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<div class="psp-cc__container" style="margin-top:-7px;">
<div class="psp-cc__content">
<div id="psp-cc-computation__type"></div>
<span contentEditable=true type="text" required maxlength="25" size="10" autocomplete="off" id="psp-cc-name" ondragover="disallowDrop(event)"></span>
<span contentEditable=true type="text" required maxlength="25" size="10" autocomplete="off" id="psp-cc-name"></span>
</div>
<div class="psp-cc__content psp-cc__content--nomargin">
<span class="psp-cc__label psp-cc__error" id="psp-cc__error--name"></span>
Expand All @@ -30,7 +30,7 @@
</div>
<div class="psp-cc__container" style="margin-top:-12px;">
<div id="psp-cc-computation-inputs">
<!--<div class="psp-cc-computation__input-column" drop-target ondragenter="dragEnter(event)"></div>-->
<!--<div class="psp-cc-computation__input-column" drop-target></div>-->
</div>
</div>
</div>
Expand Down
12 changes: 6 additions & 6 deletions packages/perspective-viewer/src/html/view.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
</select>
</div>
<div id="columns_container" style="visibility: hidden">
<ul id='active_columns' ondragenter="dragEnter(event)"></ul>
<ul id='active_columns'></ul>
<div id='divider'></div>
<div id="sub_columns">
<ul id='inactive_columns'></ul>
Expand All @@ -30,7 +30,7 @@
<div class="column noselect">
<div id='top_panel'>
<div class="rrow">
<div id="row_pivots" ondragover="allowDrop(event)" ondragleave="disallowDrop(event)" ondragenter="dragEnter(event)">
<div id="row_pivots">
<div class="psp-text-field">
<ul class="psp-text-field__input" for="row-pivots"></ul>
<label for="row_pivots"></label>
Expand All @@ -39,23 +39,23 @@
</div>
<span id="transpose_button" class="rrow centered">&#x2715;</span>
<div class="rrow">
<div id="column_pivots" ondragover="allowDrop(event)" ondragleave="disallowDrop(event)" ondragenter="dragEnter(event)">
<div id="column_pivots">
<div class="psp-text-field">
<ul class="psp-text-field__input" for="column-pivots"></ul>
<label for="column_pivots"></label>
</div>
</div>
</div>
<div class="rrow">
<div id="sort" ondragover="allowDrop(event)" ondragleave="disallowDrop(event)" ondragenter="dragEnter(event)">
<div id="sort">
<div class="psp-text-field">
<ul class="psp-text-field__input" for="sort"></ul>
<label for="sort"></label>
</div>
</div>
</div>
<div class="rrow" style='flex-grow:3;height:auto;flex:1 1 400px;max-width:none'>
<div id="filters" ondragover="allowDrop(event)" ondragleave="disallowDrop(event)" ondragenter="dragEnter(event)">
<div id="filters">
<div class="psp-text-field">
<ul class="psp-text-field__input" for='filters'></ul>
<label for="filters"></label>
Expand All @@ -70,7 +70,7 @@

<div id="config_button" class="noselect"></div>

<div id='drop_target' ondragover="allowDrop(event)">
<div id='drop_target'>
<div id='drop_target_inner'>

</div>
Expand Down
3 changes: 3 additions & 0 deletions packages/perspective-viewer/src/js/computed_column.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import template from "../html/computed_column.html";

import style from "../less/computed_column.less";

import {disallow_drop} from "./dragdrop.js";

polyfill({});

// Computations
Expand Down Expand Up @@ -486,6 +488,7 @@ class ComputedColumn extends HTMLElement {
_register_callbacks() {
this._close_button.addEventListener("click", this._close_computed_column.bind(this));
this._computation_selector.addEventListener("change", this._update_computation.bind(this));
this._column_name_input.addEventListener("dragover", disallow_drop.bind(this));
this._column_name_input.addEventListener("keyup", event => {
this.state["name_edited"] = this._column_name_input.innerText && this._column_name_input.innerText.length > 0;
this._set_column_name(event);
Expand Down
171 changes: 171 additions & 0 deletions packages/perspective-viewer/src/js/dragdrop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/******************************************************************************
*
* Copyright (c) 2018, the Perspective Authors.
*
* This file is part of the Perspective library, distributed under the terms of
* the Apache License 2.0. The full license can be found in the LICENSE file.
*
*/

import {detectIE} from "./utils.js";

function calc_index(event) {
if (this._active_columns.children.length == 0) {
return 0;
} else {
for (let cidx in this._active_columns.children) {
let child = this._active_columns.children[cidx];
if (child.offsetTop + child.offsetHeight > event.offsetY + this._active_columns.scrollTop) {
return parseInt(cidx);
}
}
return this._active_columns.children.length;
}
}

export function undrag(event) {
let div = event.target.getRootNode().host;
let parent = div;
if (parent.tagName === "PERSPECTIVE-VIEWER") {
parent = event.target.parentElement;
} else {
parent = div.parentElement;
}
let idx = Array.prototype.slice.call(parent.children).indexOf(div.tagName === "PERSPECTIVE-ROW" ? div : event.target);
let attr_name = parent.getAttribute("for");
let pivots = JSON.parse(this.getAttribute(attr_name));
pivots.splice(idx, 1);
this.setAttribute(attr_name, JSON.stringify(pivots));

if (detectIE()) {
window.ShadyCSS.styleDocument();
}
}

export function drop(ev) {
ev.preventDefault();
ev.currentTarget.classList.remove("dropping");
if (this._drop_target_hover) {
this._drop_target_hover.removeAttribute("drop-target");
}
let data = ev.dataTransfer.getData("text");
if (!data) return;
data = JSON.parse(data);

// Update the columns attribute
let name = ev.currentTarget.querySelector("ul").getAttribute("for") || ev.currentTarget.getAttribute("id").replace("_", "-");
let columns = JSON.parse(this.getAttribute(name) || "[]");
let data_index = columns.indexOf(data[0]);
if (data_index !== -1) {
columns.splice(data_index, 1);
}
if (name.indexOf("filter") > -1) {
this.setAttribute(name, JSON.stringify(columns.concat([data])));
} else if (name.indexOf("sort") > -1) {
this.setAttribute(name, JSON.stringify(columns.concat([[data[0], "asc"]])));
} else {
this.setAttribute(name, JSON.stringify(columns.concat([data[0]])));
}

// Deselect the dropped column
if (this._plugin.deselectMode === "pivots" && this._visible_column_count() > 1 && name !== "sort" && name !== "filter") {
for (let x of this.shadowRoot.querySelectorAll("#active_columns perspective-row")) {
if (x.getAttribute("name") === data[0]) {
this._active_columns.removeChild(x);
break;
}
}
this._update_column_view();
}

this._debounce_update();
}

// Handle column actions
export 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._active_columns.classList.remove("dropping");
}

export function column_dragleave(event) {
let src = event.relatedTarget;
while (src && src !== this._active_columns) {
src = src.parentElement;
}
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");
}
}

export function column_dragover(event) {
event.preventDefault();
event.dataTransfer.dropEffect = "move";
if (event.currentTarget.className !== "dropping") {
event.currentTarget.classList.add("dropping");
}
if (!this._drop_target_hover.hasAttribute("drop-target")) {
this._drop_target_hover.setAttribute("drop-target", true);
}
let new_index = calc_index.call(this, event);
let current_index = Array.prototype.slice.call(this._active_columns.children).indexOf(this._drop_target_hover);
if (current_index < new_index) new_index += 1;
if (new_index < this._active_columns.children.length) {
if (!this._active_columns.children[new_index].hasAttribute("drop-target")) {
this._active_columns.insertBefore(this._drop_target_hover, this._active_columns.children[new_index]);
}
} else {
if (!this._active_columns.children[this._active_columns.children.length - 1].hasAttribute("drop-target")) {
this._active_columns.appendChild(this._drop_target_hover);
}
}
}

export 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;

this._update_column_view();
}

export function drag_enter(ev) {
ev.stopPropagation();
ev.preventDefault();
ev.currentTarget.classList.add("dropping");
}

export function allow_drop(ev) {
ev.stopPropagation();
ev.preventDefault();
ev.currentTarget.classList.add("dropping");
ev.dataTransfer.dropEffect = "move";
}

export function disallow_drop(ev) {
if (ev.currentTarget == ev.target) {
ev.stopPropagation();
ev.preventDefault();
ev.currentTarget.classList.remove("dropping");
}
}
94 changes: 51 additions & 43 deletions packages/perspective-viewer/src/js/row.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,17 @@ class Row extends HTMLElement {
// computed_input_column.textContent = data.input_column;
}

_get_computed_data() {
const data = JSON.parse(this.getAttribute("computed_column"));
return {
column_name: data.column_name,
input_columns: data.input_columns,
input_type: data.input_type,
computation: data.computation,
type: data.type
};
}

_update_filter(event) {
let filter_operand = this.shadowRoot.querySelector("#filter_operand");
let filter_operator = this.shadowRoot.querySelector("#filter_operator");
Expand All @@ -178,64 +189,56 @@ class Row extends HTMLElement {
this.dispatchEvent(new CustomEvent("filter-selected", {detail: event}));
}

_get_computed_data() {
const data = JSON.parse(this.getAttribute("computed_column"));
return {
column_name: data.column_name,
input_columns: data.input_columns,
input_type: data.input_type,
computation: data.computation,
type: data.type
};
_set_data_transfer(event) {
if (this.hasAttribute("filter")) {
let {operator, operand} = JSON.parse(this.getAttribute("filter"));
event.dataTransfer.setData("text", JSON.stringify([this.getAttribute("name"), operator, operand, this.getAttribute("type"), this.getAttribute("aggregate")]));
} else {
event.dataTransfer.setData(
"text",
JSON.stringify([this.getAttribute("name"), perspective.FILTER_DEFAULTS[this.getAttribute("type")], undefined, this.getAttribute("type"), this.getAttribute("aggregate")])
);
}
this.dispatchEvent(new CustomEvent("row-drag"));
}

connectedCallback() {
let li = this.shadowRoot.querySelector(".row_draggable");
li.addEventListener("dragstart", ev => {
if (this.hasAttribute("filter")) {
let {operator, operand} = JSON.parse(this.getAttribute("filter"));
ev.dataTransfer.setData("text", JSON.stringify([this.getAttribute("name"), operator, operand, this.getAttribute("type"), this.getAttribute("aggregate")]));
} else {
ev.dataTransfer.setData(
"text",
JSON.stringify([this.getAttribute("name"), perspective.FILTER_DEFAULTS[this.getAttribute("type")], undefined, this.getAttribute("type"), this.getAttribute("aggregate")])
);
}
this.dispatchEvent(new CustomEvent("row-drag"));
});
li.addEventListener("dragend", () => {
_register_ids() {
this._li = this.shadowRoot.querySelector(".row_draggable");
this._visible = this.shadowRoot.querySelector(".is_visible");
this._row_close = this.shadowRoot.querySelector("#row_close");
this._agg_dropdown = this.shadowRoot.querySelector("#column_aggregate");
this._sort_order = this.shadowRoot.querySelector("#sort_order");
this._filter_operand = this.shadowRoot.querySelector("#filter_operand");
this._filter_operator = this.shadowRoot.querySelector("#filter_operator");
this._edit_computed_column_button = this.shadowRoot.querySelector("#row_edit");
}

_register_callbacks() {
this._li.addEventListener("dragstart", this._set_data_transfer.bind(this));
this._li.addEventListener("dragend", () => {
this.dispatchEvent(new CustomEvent("row-dragend"));
});
let visible = this.shadowRoot.querySelector(".is_visible");
visible.addEventListener("mousedown", event => this.dispatchEvent(new CustomEvent("visibility-clicked", {detail: event})));
this.shadowRoot.querySelector("#row_close").addEventListener("mousedown", event => this.dispatchEvent(new CustomEvent("close-clicked", {detail: event})));

let agg_dropdown = this.shadowRoot.querySelector("#column_aggregate");
agg_dropdown.addEventListener("change", event => {
this.setAttribute("aggregate", agg_dropdown.value);
this._visible.addEventListener("mousedown", event => this.dispatchEvent(new CustomEvent("visibility-clicked", {detail: event})));
this._row_close.addEventListener("mousedown", event => this.dispatchEvent(new CustomEvent("close-clicked", {detail: event})));
this._agg_dropdown.addEventListener("change", event => {
this.setAttribute("aggregate", this._agg_dropdown.value);
this.dispatchEvent(new CustomEvent("aggregate-selected", {detail: event}));
});

let sort_order = this.shadowRoot.querySelector("#sort_order");
sort_order.addEventListener("click", event => {
this._sort_order.addEventListener("click", event => {
const current = this.getAttribute("sort-order");
const order = (perspective.SORT_ORDERS.indexOf(current) + 1) % 5;
this.setAttribute("sort-order", perspective.SORT_ORDERS[order]);
this.dispatchEvent(new CustomEvent("sort-order", {detail: event}));
});

let filter_operand = this.shadowRoot.querySelector("#filter_operand");
let filter_operator = this.shadowRoot.querySelector("#filter_operator");
let debounced_filter = _.debounce(event => this._update_filter(event), 50);
filter_operator.addEventListener("change", () => {
filter_operator.style.width = get_text_width(filter_operator.value);
const debounced_filter = _.debounce(event => this._update_filter(event), 50);
this._filter_operator.addEventListener("change", () => {
this._filter_operator.style.width = get_text_width(this._filter_operator.value);
const filter_input = this.shadowRoot.querySelector("#filter_operand");
filter_input.style.width = get_text_width("" + filter_operand.value, 30);
filter_input.style.width = get_text_width("" + this._filter_operand.value, 30);
debounced_filter();
});

const edit_computed_column_button = this.shadowRoot.querySelector("#row_edit");
edit_computed_column_button.addEventListener("click", () => {
this._edit_computed_column_button.addEventListener("click", () => {
this.dispatchEvent(
new CustomEvent("perspective-computed-column-edit", {
bubbles: true,
Expand All @@ -244,4 +247,9 @@ class Row extends HTMLElement {
);
});
}

connectedCallback() {
this._register_ids();
this._register_callbacks();
}
}
Loading