Skip to content

Commit

Permalink
Merge branch 'lineup-v4' into clehner/203_lineupv4_remove_internal_fr…
Browse files Browse the repository at this point in the history
…om_renderers
  • Loading branch information
thinkh committed Mar 23, 2020
2 parents c6ee30e + 6f83c31 commit 7f9888a
Show file tree
Hide file tree
Showing 10 changed files with 199 additions and 30 deletions.
170 changes: 170 additions & 0 deletions demo/all_column_types.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="./LineUpJS.css" rel="stylesheet">
<link href="./demo.css" rel="stylesheet">
<script src="./LineUpJS.js"></script>
<title>LineUp Columns Demo</title>
</head>

<body>
<script>
window.onload = function () {

// For hierarchical columns
const hierarchy = {
name: '0',
color: 'black',
children: [{
name: 'a1',
color: 'blue',
children: [{
name: 'a2',
color: 'blue'
}, {
name: 'b2',
color: 'red',
children: [{
name: 'a3',
color: 'blue'
}, {
name: 'b3',
color: 'red'
}, {
name: 'c3',
color: 'green'
}]
}]
}]
};
const leaves = [];

function visit(prefix, node) {
if (node.children && node.children.length > 0) {
node.children.forEach(function (n) {
visit(prefix + node.name + '.', n);
});
} else {
leaves.push(prefix + node.name);
}
}

visit('', hierarchy);
const numCats = 5;
const arr = [];
const l = new Array(10).fill(0);
const cats = (new Array(numCats)).fill(0).map((_, i) => `c${i + 1}`);

for (let i = 0; i <= 10; ++i) {
arr.push({
string: 'Row ' + i,
strings: l.map((d) => 'Row ' + i),
boxplot: {min: i , max: i+5, median: i +2, q1: i+5 , q3: i+8},
number: Math.floor(Math.random() * 10),
numbers: l.map((d) => Math.random() * 10),

date: new Date(Date.now() - Math.floor(Math.random() * 1000000000000)),
dates: l.map((d) => new Date(Date.now() - Math.floor(Math.random() * 1000000000000))),

boolean: Math.random() >= 0.5,
booleans: l.map((d) => Math.random() >= 0.5),

categorical: cats[Math.floor(Math.random() * cats.length)],
categoricals: l.map((d) => cats[Math.floor(Math.random() * cats.length)]),

hierarchical: leaves[i % leaves.length],
set: cats.filter(() => Math.random() > 0.3),

numberMap: {
a1: Math.random() * 10,
a2: Math.random() * 10,
},
stringMap: {
a1: `Row ${i}a`,
a2: `Row ${i}b`,
},
dateMap: {
a1: new Date(Date.now() - Math.floor(Math.random() * 1000000000000)),
a2: new Date(Date.now() - Math.floor(Math.random() * 1000000000000)),
},
categoricalMap: {
a1: cats[Math.floor(Math.random() * cats.length)],
a2: cats[Math.floor(Math.random() * cats.length)],
}
})
}
const builder = LineUpJS.builder(arr);
builder
.rowHeight(50, 2) // increase rowHeight due to map columns
.deriveColumns(['number', 'numbers', 'string', 'date', 'dates', 'boolean', 'booleans', 'categorical', 'categoricals', 'set'])

// String
.column(LineUpJS.buildStringColumn('strings').asArray().label('Strings').width(150))
.column(LineUpJS.buildStringColumn('stringMap').asMap(['a1', 'a2']).label('StringMap').width(150).renderer('table'))

// Number
.column(LineUpJS.buildNumberColumn('numberMap').asMap(['a1', 'a2']).label('NumberMap').width(150))

// Date
.column(LineUpJS.buildDateColumn('dateMap').asMap(['a1', 'a2']).label('DateMap').width(150).renderer('table'))

// Link
.column(LineUpJS.buildStringColumn('string').label('Link').pattern('https://duckduckgo.com/?q=${escapedValue}').width(150))
.column(LineUpJS.buildStringColumn('strings').label('Links').pattern('https://duckduckgo.com/?q=${escapedValue}').asArray().width(150)) // no working/meaningful renderer available
.column(LineUpJS.buildStringColumn('stringMap').label('LinkMap').pattern('https://duckduckgo.com/?q=${escapedValue}').asMap(['a1', 'a2']).width(150).renderer('linkMap'))

// Categorical
.column(LineUpJS.buildCategoricalColumn('categoricalMap', cats).asMap(['a1', 'a2']).label('CategoricalMap').width(150).renderer('table')) // other renderer might not work or are not implemented yet

// Hierarchical
.column(LineUpJS.buildHierarchicalColumn('hierarchical', hierarchy).label('Hierarchical').width(150))

// Action
.column(LineUpJS.buildActionsColumn().action({
name: 'Action',
icon: '&#x2713;',
className: 'myClassName',
action: (row) => {
console.log(row);
}
}).label('Actions').width(150))

// Annotate
.column(LineUpJS.buildStringColumn('string').editable().label('Annotate').width(150))

// Ordinal
.column(LineUpJS.buildCategoricalColumn('categorical', cats).label('Ordinal').asOrdinal().width(150))

// BoxPlot
.column(LineUpJS.buildNumberColumn('boxplot').asBoxPlot().label('BoxPlot').width(150))

const ranking = LineUpJS.buildRanking()

// Add support columns
.supportTypes()
.allColumns()
.group()
// Scripted
.scripted('Scripted', `Math.random()`)

// Reduce
.reduce('Reduce', 'max', 'number', 'number')

// Weighted Sum
.weightedSum('Weighted Sum', 'number', .3, 'number', .5)

// Nested
.nested('Nested', 'number', 'categorical')

// Impose Categorical
.impose('Impose Number', 'number', 'categorical')
builder
.ranking(ranking);
const lineup = builder.build(document.body);
};
</script>
</body>

</html>
21 changes: 2 additions & 19 deletions src/model/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,15 +214,7 @@ export function chooseUIntByDataLength(dataLength?: number | null) {
return ECompareValueType.UINT32;
}


// side effect
const cache = new Map<string, string[]>();


export function getAllToolbarActions(col: Column) {
if (cache.has(col.desc.type)) {
return cache.get(col.desc.type)!;
}
const actions = new OrderedSet<string>();

// walk up the prototype chain
Expand All @@ -237,17 +229,11 @@ export function getAllToolbarActions(col: Column) {
}
obj = Object.getPrototypeOf(obj);
} while (obj);
const arr = Array.from(actions);
cache.set(col.desc.type, arr);
return arr;
return Array.from(actions);
}


export function getAllToolbarDialogAddons(col: Column, key: string) {
const cacheKey = `${col.desc.type}@${key}`;
if (cache.has(cacheKey)) {
return cache.get(cacheKey)!;
}
const actions = new OrderedSet<string>();

// walk up the prototype chain
Expand All @@ -262,8 +248,5 @@ export function getAllToolbarDialogAddons(col: Column, key: string) {
}
obj = Object.getPrototypeOf(obj);
} while (obj);
cache.set(cacheKey, Array.from(actions));
const arr = Array.from(actions);
cache.set(cacheKey, arr);
return arr;
return Array.from(actions);
}
5 changes: 3 additions & 2 deletions src/renderer/HistogramCellRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {normalizedStatsBuilder, IStatistics, round, getNumberOfBins} from '../internal';
import {normalizedStatsBuilder, IStatistics, getNumberOfBins} from '../internal';
import {Column, IDataRow, IOrderedGroup, INumberColumn, INumbersColumn, isNumberColumn, isNumbersColumn, IMapAbleColumn, isMapAbleColumn} from '../model';
import InputNumberDialog from '../ui/dialogs/InputNumberDialog';
import {colorOf} from './impose';
Expand Down Expand Up @@ -145,13 +145,14 @@ function createFilterInfo(col: IMapAbleColumn): IFilterInfo<number> {

function createFilterContext(col: IMapAbleColumn, context: IRenderContext): IFilterContext<number> {
const domain = col.getMapping().domain;
const format = col.getNumberFormat();
const percent = (v: number) => Math.round(100 * (v - domain[0]) / (domain[1] - domain[0]));
const unpercent = (v: number) => ((v / 100) * (domain[1] - domain[0]) + domain[0]);
return {
percent,
unpercent,
domain: <[number, number]>domain,
format: (v) => round(v, 2).toString(),
format,
setFilter: (filterMissing, minValue, maxValue) => col.setFilter({
filterMissing,
min: minValue === domain[0] ? NaN : minValue,
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/histogram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export function histogramUpdate<T>(n: HTMLElement, stats: IHistogramLike<T>, unf
}

export function mappingHintTemplate(range: [string, string]) {
return `<span class="${cssClass('mapping-hint')}">${range[0]}</span><span class="${cssClass('mapping-hint')}">${range[1]}</span>`;
return `<span class="${cssClass('mapping-hint')}" title="${range[0]}">${range[0]}</span><span class="${cssClass('mapping-hint')}" title="${range[1]}">${range[1]}</span>`;
}

export function mappingHintUpdate(n: HTMLElement, range: [string, string]) {
Expand Down
5 changes: 5 additions & 0 deletions src/styles/_vars.scss
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ $lu_taggle_border_color: #6d6c6c !default;
$lu_assets: './assets' !default;
$lu_use_font_awesome: false !default;

/**
* Width of the drag handler text of the histogram filter
*/
$lu_histogram_drag_hint_width: 7em !default;

@mixin user_select_none() {
-moz-user-select: none;
-webkit-user-select: none;
Expand Down
4 changes: 2 additions & 2 deletions src/styles/renderer/_histogram.scss
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ span.#{$lu_css_prefix}-mapping-hint {
content: attr(data-value);
position: absolute;
bottom: -15px;
width: 5em;
width: $lu_histogram_drag_hint_width;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
Expand All @@ -110,7 +110,7 @@ span.#{$lu_css_prefix}-mapping-hint {
.#{$lu_css_prefix}-histogram-min.#{$lu_css_prefix}-swap-hint,
.#{$lu_css_prefix}-histogram-max:not(.#{$lu_css_prefix}-swap-hint) {
&::before {
left: -5em;
left: -$lu_histogram_drag_hint_width;
text-align: right;
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/ui/EngineRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,11 @@ export default class EngineRenderer extends AEventDispatcher {
};
},
getPossibleRenderer: (col: Column) => getPossibleRenderer(col, this.options.renderers, this.options.canRender),
colWidth: (col: Column) => !col.isVisible() ? 0 : col.getWidth()
colWidth: (col: Column) => !col.isVisible() ? 0 : col.getWidth(),
caches: {
toolbar: new Map(),
toolbarAddons: new Map()
}
};

this.table = new MultiTableRowRenderer(this.node, this.idPrefix);
Expand Down
6 changes: 4 additions & 2 deletions src/ui/header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ export function updateHeader(node: HTMLElement, col: Column, minWidth = MIN_LABE
const label = <HTMLElement>node.getElementsByClassName(cssClass('label'))[0]!;
label.innerHTML = col.getWidth() < minWidth ? '&nbsp;' : col.label;
const summary = col.getMetaData().summary;
const sublabel = <HTMLElement>node.getElementsByClassName(cssClass('sublabel'))[0]!;
sublabel.innerHTML = col.getWidth() < minWidth || !summary ? '&nbsp;' : summary;
const sublabel = <HTMLElement>node.getElementsByClassName(cssClass('sublabel'))[0];
if (sublabel) {
sublabel.innerHTML = col.getWidth() < minWidth || !summary ? '&nbsp;' : summary;
}

let title = col.label;
if (summary) {
Expand Down
5 changes: 5 additions & 0 deletions src/ui/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ export interface IRankingHeaderContextContainer {
getPossibleRenderer(col: Column): {item: IRenderInfo[], group: IRenderInfo[], summary: IRenderInfo[]};

summaryRenderer(co: Column, interactive: boolean, imposer?: IImposer): ISummaryRenderer;

readonly caches: {
toolbar: Map<string, IToolbarAction[]>,
toolbarAddons: Map<string, IToolbarDialogAddon[]>
};
}

export interface IRankingBodyContext extends IRankingHeaderContextContainer, IRenderContext {
Expand Down
5 changes: 2 additions & 3 deletions src/ui/toolbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,10 +319,8 @@ function sortActions(a: IToolbarAction, b: IToolbarAction) {
return (a.options.order || 50) - (b.options.order || 50);
}

const cache = new Map<string, IToolbarAction[]>();
const cacheAddon = new Map<string, IToolbarDialogAddon[]>();

function getFullToolbar(col: Column, ctx: IRankingHeaderContext) {
const cache = ctx.caches.toolbar;
if (cache.has(col.desc.type)) {
return cache.get(col.desc.type)!;
}
Expand Down Expand Up @@ -377,6 +375,7 @@ export function getToolbar(col: Column, ctx: IRankingHeaderContext) {
/** @internal */
export function getToolbarDialogAddons(col: Column, key: string, ctx: IRankingHeaderContext) {
const cacheKey = `${col.desc.type}@${key}`;
const cacheAddon = ctx.caches.toolbarAddons;
if (cacheAddon.has(cacheKey)) {
return cacheAddon.get(cacheKey)!;
}
Expand Down

0 comments on commit 7f9888a

Please sign in to comment.