Skip to content

Commit 4b1a9e5

Browse files
committed
switch to colorpicker dependency
1 parent c23857e commit 4b1a9e5

File tree

6 files changed

+175
-95
lines changed

6 files changed

+175
-95
lines changed

css/style.css

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,9 @@ label[for="file-input"] {
180180
#taxonomy input[type="checkbox"] {
181181
margin-right: 0.5em;
182182
}
183-
#taxonomy input.jscolor {
183+
#taxonomy input.colorpicker {
184184
margin-left: 0.5em;
185-
width:4em;
185+
width:5em;
186186
text-align:center;
187187
display:inline-block;
188188
outline:none;
@@ -191,13 +191,19 @@ label[for="file-input"] {
191191
border-radius: 3px;
192192
cursor: pointer;
193193
box-shadow: 0 0 8px rgba(0,0,0,0.2);
194+
text-transform:uppercase;
195+
-moz-osx-font-smoothing:initial;
196+
-webkit-font-smoothing:initial;
194197
}
195-
#taxonomy input.jscolor[disabled="true"] {
198+
#taxonomy input.colorpicker[disabled="true"] {
196199
border-color:#ccc;
197200
box-shadow: none;
198201
pointer-events:none;
199202
opacity:0.5;
200203
}
204+
.cp-app {
205+
z-index:1001;
206+
}
201207

202208
body > #tree-svg {
203209
border-top: 1px solid #ccc;

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171

7272
<script src="libs/svg.js"></script>
7373
<script src="libs/svg.draggable.js"></script>
74-
<script src="libs/jscolor.min.js"></script>
74+
<script src="libs/jsColorPicker.min.js"></script>
7575
<script src="libs/d3.min.js"></script>
7676

7777
<script src="js/xhr.js"></script>

js/main.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -352,9 +352,10 @@ const Main = (function() {
352352
setSyntaxVisibility();
353353
draw();
354354

355-
tm.buildTree(taxonomy);
356-
tm.buildTagTypes(words);
357-
tm.populateTaxonomy();
355+
tm.draw(taxonomy, words);
356+
// tm.buildTree(taxonomy);
357+
// tm.buildTagTypes(words);
358+
// tm.populateTaxonomy();
358359
});
359360
})
360361
.catch(err => {

js/managers/taxonomy.js

Lines changed: 156 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const Taxonomy = (function() {
1414
'#a6761d',
1515
'#7f7f7f'
1616
];
17+
let div = {};
1718
let tagTypes = {};
1819

1920
function updateColor(word, color) {
@@ -25,14 +26,29 @@ const Taxonomy = (function() {
2526
}
2627
};
2728

28-
let div = {};
29+
function updateTagColor(tag, color) {
30+
tagTypes[tag].forEach(word => updateColor(word, color));
31+
};
2932

3033
class Taxonomy {
3134
constructor(id) {
3235
this.tree = {};
3336
div = document.getElementById('taxonomy');
3437
}
3538

39+
draw(taxonomy, words) {
40+
if (taxonomy) {
41+
this.buildTree(taxonomy);
42+
43+
if (words) {
44+
this.buildTagTypes(words);
45+
}
46+
47+
this.populateTaxonomy();
48+
this.attachHandlers();
49+
}
50+
}
51+
3652
buildTagTypes(words) {
3753
tagTypes = {};
3854
words.forEach(word => {
@@ -95,113 +111,175 @@ const Taxonomy = (function() {
95111
};
96112
}
97113

114+
// populate modal window with list of taxonomic classes
98115
populateTaxonomy() {
99-
let keys = Object.keys(tagTypes);
100-
101-
// populate taxonomy
102116
div.innerHTML = '<span id="toggle-taxonomy">Filter unused labels</span>';
103117

118+
// build list of inputs in DOM
104119
let ul = document.createElement('ul');
105120
div.appendChild(ul);
106121

107-
function createLi(el, ul) {
122+
let nli = 1; // number of list items
123+
function createLi(node, parent) {
108124
let li = document.createElement('li');
109-
el.el = li;
110125

111126
// create checkbox
112127
let cbox = document.createElement('input');
113128
cbox.setAttribute('type', 'checkbox');
114-
li.appendChild(cbox);
129+
cbox.id = 'cb-' + nli;
115130

116-
// text span
117-
li.appendChild(document.createTextNode(el.val));
131+
// create label for checkbox
132+
let label = document.createElement('label');
133+
label.setAttribute('for', cbox.id);
134+
label.textContent = node.val;
135+
node.cbox = cbox;
118136

119137
// create color picker input
120138
let picker = document.createElement('input');
121-
picker.className = 'jscolor';
139+
picker.className = 'colorpicker';
140+
picker.value = '#000000';
141+
picker.setAttribute('disabled', true);
142+
picker.node = node;
143+
node.picker = picker;
122144

123-
// set initial value
124-
let i = keys.indexOf(el.val);
125-
if (i > -1) {
126-
cbox.checked = true;
127-
picker.value = colors[i] || '#000000';
128-
129-
// propagate color to colorless ancestors
130-
let parent = el.parent;
131-
while (parent && parent.el && !parent.el.querySelector('input.jscolor').value) {
132-
parent.el.querySelector('input.jscolor').value = picker.value;
133-
parent = parent.parent;
134-
}
135-
}
136-
picker.setAttribute('disabled', !cbox.checked);
145+
li.appendChild(cbox);
146+
li.appendChild(label);
137147
li.appendChild(picker);
148+
parent.appendChild(li);
149+
++nli;
138150

139-
// recursively update picker colors
140-
function updateChildColors() {
141-
let color = this.value;
142-
console.log('color', color);
143-
function recurse(el) {
144-
if (tagTypes[el.val]) {
145-
tagTypes[el.val].forEach(word => updateColor(word, color));
146-
}
147-
if (el.children) {
148-
el.children.forEach(recurse);
149-
}
150-
}
151-
recurse(el);
151+
if (node.children) {
152+
let childUl = document.createElement('ul');
153+
li.appendChild(childUl);
154+
155+
node.children.forEach(child => {
156+
createLi(child, childUl);
157+
})
152158
}
159+
}
153160

154-
// attach listeners
155-
cbox.onclick = function() {
156-
// TODO: update children colors on click
157-
if (this.checked) {
158-
// enable current picker and disable children inputs
159-
picker.removeAttribute('disabled');
160-
li.querySelectorAll('input').forEach(input => {
161-
if (input.parentNode !== li) {
162-
input.setAttribute('disabled', true);
163-
}
164-
});
165-
updateChildColors.bind(picker);
166-
}
167-
else {
168-
// enable children inputs
169-
picker.setAttribute('disabled', true);
170-
let checkboxes = li.querySelectorAll('input[type="checkbox"]');
171-
let pickers = li.querySelectorAll('input.jscolor');
172-
checkboxes.forEach((cbox, i) => {
173-
cbox.removeAttribute('disabled');
174-
pickers[i].setAttribute('disabled', !cbox.checked);
175-
});
176-
updateChildColors();
161+
this.tree.hierarchy.forEach(node => {
162+
createLi(node, ul);
163+
});
164+
}
165+
166+
// bind events to data
167+
attachHandlers() {
168+
// initialize colorpicker
169+
let self = this;
170+
jsColorPicker('input.colorpicker', {
171+
customBG: '#000',
172+
init: function(elm, colors) {
173+
elm.style.backgroundColor = elm.value || '#000';
174+
elm.style.color = colors.rgbaMixCustom.luminance > 0.22 ? '#222' : '#ddd';
175+
},
176+
renderCallback: function(colors, mode) {
177+
/* ---- code taken from jsColor.js ---- */
178+
var options = this,
179+
input = options.input,
180+
patch = options.patch,
181+
RGB = colors.RND.rgb,
182+
HSL = colors.RND.hsl,
183+
AHEX = options.isIE8 ? (colors.alpha < 0.16 ? '0' : '') +
184+
(Math.round(colors.alpha * 100)).toString(16).toUpperCase() + colors.HEX : '',
185+
RGBInnerText = RGB.r + ', ' + RGB.g + ', ' + RGB.b,
186+
RGBAText = 'rgba(' + RGBInnerText + ', ' + colors.alpha + ')',
187+
isAlpha = colors.alpha !== 1 && !options.isIE8,
188+
colorMode = input.getAttribute('data-colorMode');
189+
190+
patch.style.cssText =
191+
'color:' + (colors.rgbaMixCustom.luminance > 0.22 ? '#222' : '#ddd') + ';' + // Black...???
192+
'background-color:' + RGBAText + ';' +
193+
'filter:' + (options.isIE8 ? 'progid:DXImageTransform.Microsoft.gradient(' + // IE<9
194+
'startColorstr=#' + AHEX + ',' + 'endColorstr=#' + AHEX + ')' : '');
195+
196+
input.value = (colorMode === 'HEX' && !isAlpha ? '#' + (options.isIE8 ? AHEX : colors.HEX) :
197+
colorMode === 'rgb' || (colorMode === 'HEX' && isAlpha) ?
198+
(!isAlpha ? 'rgb(' + RGBInnerText + ')' : RGBAText) :
199+
('hsl' + (isAlpha ? 'a(' : '(') + HSL.h + ', ' + HSL.s + '%, ' + HSL.l + '%' +
200+
(isAlpha ? ', ' + colors.alpha : '') + ')')
201+
);
202+
203+
if (options.displayCallback) {
204+
options.displayCallback(colors, mode, options);
177205
}
206+
207+
/* -- manually invoke callback -- */
208+
self.setColor(this.input.node);
178209
}
179-
picker.onchange = updateChildColors;
210+
});
180211

181-
if (el.children) {
182-
let childUl = document.createElement('ul');
183-
li.appendChild(childUl);
184-
el.children.forEach(child => createLi(child, childUl));
212+
const keys = Object.keys(tagTypes);
213+
this.tree.flat.forEach(node => {
214+
// disable/enable color picking on a node
215+
node.cbox.onclick = () => this.onCheckboxClick(node);
216+
217+
// check if tag type exists in document
218+
if (tagTypes[node.val]) {
219+
this.setColor(node, colors[keys.indexOf(node.val)]);
220+
node.cbox.click();
221+
}
222+
});
223+
224+
// update colors of existing data
225+
Object.keys(tagTypes).forEach((tag, i) => updateTagColor(tag, colors[i]));
226+
}
227+
228+
/* handle event when checkbox state changes */
229+
onCheckboxClick(node) {
230+
if (node.cbox.checked) {
231+
// activate node
232+
// propagate color to all descendants
233+
node.picker.removeAttribute('disabled');
234+
this.setColor(node);
235+
} else {
236+
// deactivate node
237+
// undo color propagation to all descendants
238+
node.picker.setAttribute('disabled', true);
239+
if (node.parent) {
240+
this.setColor(node, node.parent.picker.value);
241+
} else {
242+
this.setColor(node, '#000000');
185243
}
186-
ul.appendChild(li);
187244
}
188-
this.tree.hierarchy.forEach(el => createLi(el, ul));
189-
jscolor.installByClassName('jscolor');
245+
}
246+
247+
/* change the color of a node */
248+
setColor(node, color) {
249+
let picker = node.picker;
190250

191-
document.getElementById('toggle-taxonomy').onclick = function() {
192-
if (ul.className === 'filtered') {
193-
ul.className = '';
194-
this.innerHTML = 'Show all labels';
251+
// manually set color
252+
if (color) {
253+
const c = new Colors({ color: color });
254+
const labelColor = c.colors.RGBLuminance > 0.22 ? '#222' : '#ddd';
255+
picker.value = color;
256+
picker.style.cssText = `color:${labelColor}; background-color:${color};`;
257+
}
258+
259+
if (tagTypes[node.val]) {
260+
updateTagColor(node.val, picker.value);
261+
}
262+
263+
// set color of input and descendant inputs
264+
function inheritColor(child) {
265+
if (!child.cbox.checked) {
266+
// set color and style
267+
child.picker.value = picker.value;
268+
child.picker.style.cssText = picker.style.cssText || child.picker.style.cssText;
269+
if (tagTypes[child.val]) {
270+
updateTagColor(child.val, picker.value);
195271
}
196-
else {
197-
ul.className = 'filtered';
198-
this.innerHTML = 'Filter unused labels';
272+
273+
// recursively propagate value to all children
274+
if (child.children) {
275+
child.children.forEach(inheritColor);
199276
}
277+
}
200278
}
201279

202-
keys.forEach((tag, i) => {
203-
tagTypes[tag].forEach(word => updateColor(word, colors[i]));
204-
});
280+
if (node.children) {
281+
node.children.forEach(inheritColor);
282+
}
205283
}
206284

207285
remove(object) {

libs/jsColorPicker.min.js

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libs/jscolor.min.js

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)