Permalink
Browse files

Improve UX/UI.

  • Loading branch information...
1 parent bbeef0e commit 7a1e907edc6854f5e2f7aacf09fe170fb88bf546 @hdemers hdemers committed Jun 13, 2013
@@ -42,6 +42,7 @@ body {
#define {
margin-top: 40px;
margin-left: 40px;
+ width: 300px;
}
@@ -64,6 +65,10 @@ body {
font: 12px sans-serif;
}
+.js-more-node {
+ cursor: pointer;
+}
+
.link {
fill: none;
stroke: @link;
@@ -82,11 +87,11 @@ circle.js-parent {
}
.rootsynset {
- font-size: 24px;
+ font-size: 20px;
}
.synset {
- font-size: 18px;
+ font-size: 15px;
margin: 10px 0px 20px 20px;
}
@@ -101,3 +106,12 @@ circle.js-parent {
#spinner {
margin-bottom: 10px;
}
+
+.nav {
+ margin-bottom: 20px;
+}
+
+.nav > li > a {
+ padding: 5px 10px;
+ color: #333;
+}
@@ -1,5 +1,4 @@
@import "bootstrap.min.css";
-@import "bootstrap-responsive.min.css";
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif, default;
@@ -11,9 +10,3 @@ body {
-moz-border-radius: 0px;
border-radius: 0px;
}
-
-
-a {
- color: #5b4d3c;
-}
-

Large diffs are not rendered by default.

Oops, something went wrong.

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -9,7 +9,8 @@ define([
"d3",
"viewmodel",
"tree",
- "infomsg"
+ "infomsg",
+ "bootstrap"
],
function ($, _, ko, d3, viewmodel, tree, infomsg) {
var exports = {}, define, addGraph;
@@ -36,7 +37,7 @@ function ($, _, ko, d3, viewmodel, tree, infomsg) {
}
infomsg.clear();
- $("#spinner").show();
+ $("#spinner").removeClass("hidden");
return $.ajax({
url: "define/" + word,
@@ -48,12 +49,19 @@ function ($, _, ko, d3, viewmodel, tree, infomsg) {
" a definition for this word. <br>Try again.");
}
else {
+ // Because Bootstrap selects element with jQuery and selectors must
+ // escape dots, we need to remove those dots from the ids.
+ data.definitions.forEach(function (def) {
+ def.id = def.rootsynset.replace(/\./g, "");
+ });
+
// Add nodes to the DOM through Knockout
ko.utils.arrayPushAll(viewmodel.definitions, data.definitions);
- // Go through the added nodes and build graphs.
+ // Go through the added nodes and build graphs.
$(".js-definition").each(function (index, element) {
addGraph(element, data.definitions[index]);
});
+ $('.nav a:first').tab('show');
}
}).fail(function (jqXHR, textStatus, errorThrown) {
console.log("Failed", jqXHR, textStatus, errorThrown);
@@ -63,7 +71,7 @@ function ($, _, ko, d3, viewmodel, tree, infomsg) {
"this issue. (" + data.message + ")";
infomsg.error(textStatus, message, 0);
}).always(function () {
- $("#spinner").hide();
+ $("#spinner").addClass("hidden");
});
};
@@ -3,7 +3,7 @@
*/
require({
paths: {
- "jquery": "other/jquery-1.9.1.min",
+ "jquery": "other/jquery-2.1.0.min",
"knockout": "other/knockout-2.2.1",
"underscore": "other/underscore-min",
"domReady": "other/domReady",

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -11,7 +11,8 @@ define([
],
function ($, _, viewmodel, d3, ko) {
var exports = {},
- closeAll, toggle, makeTree;
+ closeAll, toggle, makeTree, reduce, expand, expandReduce,
+ moreNodeName = "... more ...";
exports.build = function (options) {
var that = {},
@@ -20,25 +21,25 @@ function ($, _, viewmodel, d3, ko) {
},
root, tree, diagonal, vis, index,
showAll, update,
- opts = _.defaults(options, defaults);
+ opts = _.defaults(options, defaults),
+ sizeX = 15, sizeY = 190;
that.draw = function (rootNode) {
var width, height,
- m = [20, 20, 20, 120],
- nodeWidth = 180, nodeHeight = 15;
+ m = [20, 20, 20, 120];
index = 0;
root = rootNode;
- tree = d3.layout.tree().size(null).elementsize([nodeHeight, nodeWidth]);
+ tree = d3.layout.tree().size(null).elementsize([sizeX, sizeY]);
var nodes = tree.nodes(root);
- var max_x = d3.max(nodes, function (d) {return d.x; });
- var max_y = d3.max(nodes, function (d) {return d.depth * nodeWidth; });
-
- height = max_x + 20;
- width = max_y + 100;
+ var maxX = d3.max(nodes, function (d) {return d.x; });
+ var maxY = d3.max(nodes, function (d) {return d.y; });
+ height = maxX + sizeX;
+ width = maxY + sizeY;
+
diagonal = d3.svg.diagonal()
.projection(function (d) { return [d.y, d.x]; });
@@ -51,63 +52,83 @@ function ($, _, viewmodel, d3, ko) {
root.x0 = height / 2;
root.y0 = 0;
+ //reduce(root);
update(root);
- // Initialize the display to show a few nodes.
- //root.children.forEach(closeAll);
- //toggle(root);
- //showAll(root);
};
update = function (source) {
var duration = d3.event && d3.event.altKey ? 5000 : 500;
- // Compute the new tree layout.
+ // Compute the new tree layout.
var nodes = tree.nodes(root).reverse();
- // Normalize for fixed-depth.
- nodes.forEach(function (d) { d.y = d.depth * 180; });
-
- // Update the nodes…
+ // Update the nodes…
var node = vis.selectAll("g.js-node")
.data(nodes, function (d) { return d.id || (d.id = ++index); });
- // Enter any new nodes at the parent's previous position.
+ // Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("svg:g")
.attr("class", function (d) {
return "js-node " + (d.path ? "js-path": '');
})
.attr("transform", function (d) {
return "translate(" + source.y0 + "," + source.x0 + ")";
})
- .on("click", function (d) { toggle(d); update(d); });
+ .on("click", function (d) {
+ if (d3.event.ctrlKey) {
+ expandReduce(d, true);
+ update(d);
+ }
+ else {
+ toggle(d);
+ update(d);
+ }
+ });
nodeEnter.append("svg:circle")
.attr("r", 1e-6)
- .attr("class", function (d) { return d._children ? "js-parent" : ''; });
+ .attr("class", function (d) {return d._children ? "js-parent" : ''; });
nodeEnter.append("svg:text")
- .attr("x", function (d) { return d.children || d._children ? -10 : 10; })
+ .attr("x", function (d) {
+ return d.children || d._children ? -10 : 10;
+ })
.attr("dy", ".35em")
- .attr("text-anchor", function (d) { return d.children || d._children ? "end" : "start"; })
- .text(function (d) { return d.id; })
- .style("fill-opacity", 1e-6);
+ .attr("text-anchor", function (d) {
+ return d.children || d._children ? "end" : "start";
+ })
+ .text(function (d) { return d.name || d.id; })
+ .style("fill-opacity", 1e-6)
+ .attr("class", function (d) {
+ return d.name === moreNodeName ? "js-more-node" : '';
+ })
+ .on("click", function (d) {
+ if (d.name === moreNodeName && d.parent) {
+ expand(d.parent);
+ update(d);
+ }
+ });
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
- .attr("transform", function (d) { return "translate(" + d.y + "," + d.x + ")"; });
+ .attr("transform", function (d) {
+ return "translate(" + d.y + "," + d.x + ")";
+ });
nodeUpdate.select("circle")
.attr("r", 4.5)
- .attr("class", function (d) { return d._children ? "js-parent" : ''; });
+ .attr("class", function (d) {return d._children ? "js-parent" : ''; });
nodeUpdate.select("text")
.style("fill-opacity", 1);
// Transition existing nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
- .attr("transform", function (d) { return "translate(" + source.y + "," + source.x + ")"; })
+ .attr("transform", function (d) {
+ return "translate(" + source.y + "," + source.x + ")";
+ })
.remove();
nodeExit.select("circle")
@@ -116,11 +137,11 @@ function ($, _, viewmodel, d3, ko) {
nodeExit.select("text")
.style("fill-opacity", 1e-6);
- // Update the links…
+ // Update the links…
var link = vis.selectAll("path.link")
.data(tree.links(nodes), function (d) { return d.target.id; });
- // Enter any new links at the parent's previous position.
+ // Enter any new links at the parent's previous position.
link.enter().insert("svg:path", "g")
.attr("class", function (d) {
return "link " + (d.target.path ? "js-path" : "");
@@ -133,12 +154,12 @@ function ($, _, viewmodel, d3, ko) {
.duration(duration)
.attr("d", diagonal);
- // Transition links to their new position.
+ // Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", diagonal);
- // Transition exiting nodes to the parent's new position.
+ // Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function (d) {
@@ -147,7 +168,7 @@ function ($, _, viewmodel, d3, ko) {
})
.remove();
- // Stash the old positions for transition.
+ // Stash the old positions for transition.
nodes.forEach(function (d) {
d.x0 = d.x;
d.y0 = d.y;
@@ -184,6 +205,54 @@ function ($, _, viewmodel, d3, ko) {
}
};
+ // Reduce the number of children for the given node. Recurse.
+ reduce = function (node) {
+ var has_children = function (n) {return n.children ? true : false; },
+ n = 5, nMissing;
+
+ if (node.children) {
+ if (node.children.length > 10) {
+ node._with_children = _.filter(node.children, has_children);
+ node._without_children = _.reject(node.children, has_children);
+
+ nMissing = n - node._with_children.length;
+ node.children = _.clone(node._with_children)
+ .concat(
+ _.first(node._without_children, nMissing));
+
+ node.children.push({
+ name: moreNodeName
+ });
+ }
+ node.children.forEach(reduce);
+ }
+ };
+
+ expand = function (node, recurse) {
+ if (node.children) {
+ if (node._with_children && node._without_children) {
+ node.children = node._with_children.concat(node._without_children);
+ node._with_children = null;
+ node._without_children = null;
+ }
+ if (recurse) {
+ _.each(node.children, function (child) {expand(child, true); });
+ }
+ }
+ };
+
+ _.mixin({
+ toggle: function (fn1, fn2) {
+ var fn = fn1;
+ return function () {
+ var result = fn.apply(this, arguments);
+ fn = fn === fn1 ? fn2 : fn1;
+ return result;
+ };
+ }
+ });
+
+ expandReduce = _.toggle(expand, reduce);
return exports;
});
@@ -10,16 +10,24 @@
{% block content %}
<div class="container-fluid">
- <div id="define" class="row-fluid">
- <form data-bind="submit: define">
- <input placeholder="English dictionary work"
+ <div id="define" class="row-fluid form-group">
+ <form class="form-inline" data-bind="submit: define">
+ <input placeholder="English dictionary work" class="form-control"
type="text" data-bind="value: word"></input>
- <img id="spinner" class="hide" src=/static/img/spinner.gif></img>
- </form>
+ <img id="spinner" class="hidden" src=/static/img/spinner.gif></img>
+ </form>
</div>
- <div id="container" class="row-fluid" data-bind="foreach: definitions">
- <div class="js-definition row-fluid">
+<ul class="nav nav-tabs" data-bind="foreach: definitions">
+ <li><a data-bind="text: rootsynset, attr:{href: '#' + id}"
+ data-toggle="tab"></a></li>
+</ul>
+
+<div id="container" class="row-fluid tab-content"
+ data-bind="foreach: definitions">
+
+ <div class="js-definition row-fluid tab-pane"
+ data-bind="attr: {id: id}">
<span class="rootsynset" data-bind="text: rootsynset"></span>
<div class="row-fluid" data-bind="foreach: synsets">

0 comments on commit 7a1e907

Please sign in to comment.