Skip to content

Commit d25dc51

Browse files
committed
additional ui changes - more mouse events, options tab in modal
1 parent fa7d3f5 commit d25dc51

File tree

5 files changed

+188
-31
lines changed

5 files changed

+188
-31
lines changed

css/style.css

Lines changed: 66 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,38 +19,48 @@ svg text {
1919
#header {
2020
position:fixed;
2121
z-index:100;
22-
background:#555;
2322
width:100%;
24-
height:40px;
23+
padding:10px 20px;
24+
background-image:linear-gradient(to top, rgba(255,255,255,0),rgba(255,255,255,0.8), white, white);
25+
/*background:rgba(255,255,255,0.5);*/
2526
top:0;
27+
color:#777;
2628
font: 14px/1.5em helvetica, arial, sans-serif;
2729
}
2830

2931
header > div {
3032
float:right;
3133
display:inline-block;
3234
background:inherit;
33-
color:white;
3435
position:relative;
3536
}
3637
#dataset,
3738
header > button {
38-
color:white;
39-
height:40px;
40-
padding: 0 20px;
39+
color:inherit;
4140
background: none;
4241
outline:none;
4342
cursor:pointer;
4443
font:inherit;
4544
border:none;
45+
padding:0;
46+
margin:10px;
4647
}
47-
header > button {
48-
border: 1px solid #999;
49-
border-width:0 0 0 1px;
50-
border-radius:0;
48+
#dataset {
49+
display:inline-block;
50+
height:40px;
51+
background-color:white;
52+
border:1px solid #ddd;
53+
transition:background 200ms ease;
54+
}
55+
#dataset:hover {
56+
background:#fafafa;
57+
}
58+
header > button:hover {
59+
border-bottom:1px solid grey;
5160
}
5261

5362
.modal {
63+
color:#222;
5464
background:rgba(0,0,0,0.5);
5565
width:100%;
5666
height:100%;
@@ -64,36 +74,72 @@ header > button {
6474
display:block;
6575
}
6676
.modal > div {
67-
padding:2em;
6877
background:hsl(5,5%,98%);
6978
margin: 10vh auto;
7079
width:80%;
7180
max-width:700px;
7281
height:80vh;
73-
overflow-y:auto;
7482
border-radius:6px;
7583
box-shadow: 0 0 20px black;
7684
font-size:14px;
7785
line-height:1.5em;
7886
}
79-
.modal > div > ul {
87+
.modal header {
88+
padding: 0 1em;
89+
background:white;
90+
white-space: nowrap;
91+
overflow-x:auto;
92+
cursor:move;
93+
box-shadow: 0 0 1em rgba(0,0,0, 0.15);
94+
}
95+
.modal header .tab {
96+
background: hsl(5, 5%, 85%);
97+
display:inline-block;
98+
margin-top:0.8em;
99+
padding: 0.5em 1em;
100+
cursor:pointer;
101+
border-radius: 3px 3px 0 0;
102+
border:1px solid hsl(5, 5%, 85%);
103+
border-bottom:none;
104+
text-transform: uppercase;
105+
font-size:0.85em;
106+
letter-spacing:0.03em;
107+
color:#555;
108+
}
109+
.modal header .tab.active {
110+
color:#222;
111+
background: hsl(5, 5%, 98%);
112+
}
113+
114+
.modal .page {
115+
padding: 2em;
116+
padding-top: 0.5em;
117+
display:none;
118+
height:calc(100% - 5.6em);
119+
overflow-y:auto;
120+
}
121+
.modal .page.active {
122+
display:block;
123+
}
124+
125+
#taxonomy > ul {
80126
list-style-type: none;
81127
padding:0;
82128
margin:0;
83129
}
84-
.modal > div > ul ul {
130+
#taxonomy > ul ul {
85131
list-style-type: none;
86132
padding:0;
87133
padding-left: 1.5em;
88134
}
89-
.modal > div li {
135+
#taxonomy li {
90136
margin-top: 0.5em;
91137
margin-bottom: 0.5em;
92138
}
93-
.modal > div input[type="checkbox"] {
139+
#taxonomy input[type="checkbox"] {
94140
margin-right: 0.5em;
95141
}
96-
.modal > div input.jscolor {
142+
#taxonomy input.jscolor {
97143
margin-left: 0.5em;
98144
width:4em;
99145
text-align:center;
@@ -105,7 +151,7 @@ header > button {
105151
cursor: pointer;
106152
box-shadow: 0 0 8px rgba(0,0,0,0.2);
107153
}
108-
.modal > div input.jscolor[disabled="true"] {
154+
#taxonomy input.jscolor[disabled="true"] {
109155
border-color:#ccc;
110156
box-shadow: none;
111157
pointer-events:none;
@@ -146,12 +192,10 @@ header > button {
146192

147193
/* svg styles for main vis */
148194
#main {
149-
margin-top:40px;
195+
margin-top:100px;
196+
margin-bottom:20px;
150197
position:relative;
151198
}
152-
#main svg {
153-
background-color: hsl(40,10%,90%);
154-
}
155199
#main text {
156200
font-family: BrownPro, Brown, futura, helvetica, arial, sans-serif;
157201
text-anchor: middle;

index.html

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,29 @@
1717
<option>passage1</option>
1818
<option>passage2</option>
1919
</select>
20-
<button id="syntax-toggle">Hide syntax</button>
21-
<button id="taxonomy-toggle">Taxonomy ▾</button>
20+
<button id="taxonomy-toggle">Taxonomy</button>
21+
<button id="options-toggle">Options</button>
2222
</header>
2323

2424
<div id="main">
2525
<div id="tooltip">
2626
</div>
2727
</div>
28-
<div class="modal" id="taxonomy">
28+
<div class="modal" id="modal">
2929
<div>
30+
<header>
31+
<span class="tab active" data-id="taxonomy">Taxonomy</span>
32+
<span class="tab" data-id="tree">Syntax Tree</span>
33+
<span class="tab" data-id="graph">Graph</span>
34+
<span class="tab" data-id="options">Options</span>
35+
</header>
36+
<div class="page active" id="taxonomy"></div>
37+
<div class="page" id="tree"></div>
38+
<div class="page" id="graph"></div>
39+
<div class="page" id="options">
40+
<p><input type="checkbox" checked> Syntax tree visible</p>
41+
<p><input type="checkbox"> Hide links when moving words</p>
42+
</div>
3043
</div>
3144
</div>
3245

js/components/link.js

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,26 @@ class Link {
7777
this.svgTexts.push(text);
7878
}
7979

80+
// apply click events to text
81+
this.svgTexts.forEach(text => {
82+
text.node.oncontextmenu = (e) => {
83+
e.preventDefault();
84+
svg.fire('link-label-right-click', { object: this, type: 'text', event: e });
85+
};
86+
});
87+
8088
this.line = this.svg.path()
8189
.addClass('polyline');
8290

91+
// apply drag events to line
8392
let draggedHandle = null;
8493
let x = 0;
94+
95+
this.line.node.oncontextmenu = (e) => {
96+
e.preventDefault();
97+
svg.fire('link-right-click', { object: this, type: 'link', event: e });
98+
}
99+
85100
this.line.draggable()
86101
.on('dragstart', (e) => {
87102
let closestHandle = this.handles.reduce((acc, val) =>
@@ -117,6 +132,7 @@ class Link {
117132
else if (!this.top && anchor.syntaxTag instanceof WordTag) {
118133
halfWidth = anchor.syntaxTag.ww / 2;
119134
}
135+
halfWidth = Math.max(halfWidth, 13);
120136
draggedHandle.offset = draggedHandle.offset < 0
121137
? Math.max(-halfWidth + 3, draggedHandle.offset)
122138
: Math.min(halfWidth - 3, draggedHandle.offset);
@@ -155,10 +171,19 @@ class Link {
155171
.sort((a,b) => a.slot - b.slot)
156172
.filter(link => link.top == this.top);
157173

174+
let w = 10; // magic number => TODO: resize this to tag width?
175+
158176
if (l.length > 1) {
159-
l = l.filter(link => h.anchor.idx > link.endpoints[0].idx == h.anchor.idx > this.endpoints[0].idx);
160-
let w = 10; // magic number => TODO: resize this to tag width?
161-
h.offset = (l.indexOf(this) + 0.5) / l.length * (h.anchor.idx > this.endpoints[0].idx ? -w : w);
177+
if (h.anchor instanceof Link && h.anchor.trigger.idx === h.anchor.endpoints[0].idx) {
178+
h.offset = l.indexOf(this) / l.length * 2 * w;
179+
}
180+
else if (h.anchor instanceof Link && h.anchor.trigger.idx === h.anchor.endpoints[1].idx) {
181+
h.offset = l.indexOf(this) / l.length * 2 * -w;
182+
}
183+
else {
184+
l = l.filter(link => h.anchor.idx > link.endpoints[0].idx == h.anchor.idx > this.endpoints[0].idx);
185+
h.offset = (l.indexOf(this) + 0.5) / l.length * (h.anchor.idx > this.endpoints[0].idx ? -w : w);
186+
}
162187
}
163188
else {
164189
h.offset = 0;

js/main.js

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,68 @@ const Main = (function() {
7070
// }
7171
// });
7272
// }
73+
74+
function setActiveTab(pageId, modalId="modal") {
75+
let m = document.getElementById(modalId);
76+
m.classList.add('open');
77+
78+
m.querySelector('.tab.active').classList.remove('active');
79+
m.querySelector('.page.active').classList.remove('active');
80+
m.querySelector('header span[data-id="' + pageId + '"]').classList.add('active');
81+
document.getElementById(pageId).classList.add('active');
82+
}
83+
84+
let modalHeader = document.querySelector('#modal header');
85+
let modalDrag = null;
86+
let modalWindow = document.querySelector('#modal > div');
87+
modalHeader.onmousedown = function(e) {
88+
modalDrag = e;
89+
}
90+
document.addEventListener('mousemove', function(e) {
91+
if (modalDrag) {
92+
let dx = e.x - modalDrag.x;
93+
let dy = e.y - modalDrag.y;
94+
modalDrag = e;
95+
let transform = modalWindow.style.transform.match(/-?\d+/g) || [0,0];
96+
transform[0] = +transform[0] + dx || dx;
97+
transform[1] = +transform[1] + dy || dy;
98+
modalWindow.style.transform = `translate(${transform[0]}px, ${transform[1]}px)`;
99+
}
100+
});
101+
document.addEventListener('mouseup', function() {
102+
modalDrag = null;
103+
let transform = modalWindow.style.transform.match(/-?\d+/g);
104+
if (!transform) { return; }
105+
106+
let rect = modalWindow.getBoundingClientRect();
107+
if (rect.left > window.innerWidth - 50) {
108+
transform[0] -= (50 + rect.left - window.innerWidth);
109+
}
110+
else if (rect.right < 50) {
111+
transform[0] -= (rect.right - 50);
112+
}
113+
if (rect.top < 0) {
114+
transform[1] -= rect.top;
115+
}
116+
else if (rect.top > window.innerHeight - 50) {
117+
transform[1] -= (50 + rect.top - window.innerHeight);
118+
}
119+
modalWindow.style.transform = `translate(${transform[0]}px, ${transform[1]}px)`;
120+
});
121+
122+
document.querySelectorAll('.modal header .tab').forEach(tab => {
123+
tab.onclick = function() {
124+
setActiveTab(this.getAttribute('data-id'));
125+
}
126+
});
127+
128+
document.getElementById('options-toggle').onclick = function() {
129+
setActiveTab('options');
130+
}
73131
document.getElementById('taxonomy-toggle').onclick = function() {
74-
document.getElementById('taxonomy').classList.add('open');
132+
setActiveTab('taxonomy');
75133
}
76-
document.getElementById('taxonomy').onclick = function(e) {
134+
document.getElementById('modal').onclick = function(e) {
77135
e.target.classList.remove('open');
78136
}
79137
}
@@ -88,6 +146,8 @@ const Main = (function() {
88146
ymlToJson.convert('taxonomy.yml.txt', function(taxonomy) {
89147
[words, links, clusters] = buildWordsAndLinks();
90148

149+
//FIXME
150+
console.log(words.filter(x => x.val === 'Silencing').map(x => x.links));
91151
// turn taxonomy into a proper tree
92152
let tree = (function() {
93153

@@ -304,7 +364,7 @@ const Main = (function() {
304364
};
305365

306366
// populate taxonomy
307-
let div = document.querySelector('#taxonomy > div');
367+
let div = document.getElementById('taxonomy');
308368
div.innerHTML = '';
309369
let ul = document.createElement('ul');
310370
div.appendChild(ul);

js/managers/tooltip.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ const Tooltip = (function() {
1515
// listeners to open tooltip
1616
svg.on('tag-right-click', openTooltip);
1717
svg.on('word-right-click', openTooltip);
18+
svg.on('link-label-right-click', openTooltip);
19+
svg.on('link-right-click', openTooltip);
1820
}
1921
}
2022

@@ -35,6 +37,14 @@ const Tooltip = (function() {
3537
else if (activeObject instanceof WordTag || activeObject instanceof WordCluster) {
3638
html += '<p id="menu--remove-tag">Remove</p>';
3739
}
40+
else if (activeObject instanceof Link) {
41+
if (e.detail.type === 'text') {
42+
html += '<p id="menu--edit-link-label">Edit label</p>';
43+
}
44+
else {
45+
html += '<p id="menu--remove-link">Remove link</p>';
46+
}
47+
}
3848
if (html) {
3949
div.innerHTML = html;
4050
div.style.left = Math.min(e.detail.event.x, width) + 'px';
@@ -80,6 +90,11 @@ const Tooltip = (function() {
8090
case 'menu--edit-tag':
8191
_svg.fire('tag-edit', { object: activeObject.tag });
8292
break;
93+
case 'menu--edit-link-label':
94+
break;
95+
case 'menu--remove-link':
96+
activeObject.remove();
97+
break;
8398
default: ;
8499
}
85100
console.log(e.target.id, activeObject && activeObject.val);

0 commit comments

Comments
 (0)