Skip to content

Instantly share code, notes, and snippets.

@bollwyvl
Last active December 17, 2015 10:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bollwyvl/5599335 to your computer and use it in GitHub Desktop.
Save bollwyvl/5599335 to your computer and use it in GitHub Desktop.
Cards

Cards

Shows use of:

  • contenteditable
  • various events

Limitations, ways forward

  • only works in chrome right now
    • cross-browser dblclick event?
  • no pan
    • need to use d3.behavior.zoom?
;(function(d3){
var ENTER = 13;
var Z = 1;
var ZOOM = 1;
var card_collection = window.card_collection = [];
function Card(){
var my = {
x: 0,
y: 0,
text: null,
id: +(new Date()) + Math.random()
};
function wrap(attr){
return function(val){
if(val === void 0){ return my[attr]; }
my[attr] = val;
return api;
};
}
var api = {
x: wrap("x"),
y: wrap("y"),
text: wrap("text"),
id: wrap("id")
};
return api;
}
Card.create = function(){
var card = Card().x(d3.event.x).y(d3.event.y);
card._editable = 1;
card_collection.push(card);
render();
var div = d3.selectAll(".card").filter(function(d){
return d === card;
}).node();
Card.click.call(div, card);
};
Card.click = function(d, i){
d._editable = true;
render();
d3.select(this).select(".text").node().focus();
d3.event.stopPropagation();
};
Card.keyup = function(d, i){
if(d3.event.shiftKey && d3.event.keyCode === ENTER){
Card.save(d, i);
}
};
Card.save = function(d, i){
if(d._editable){ return; }
console.log("saved!");
this.blur();
var text = d3.select(this);
d.text(this.innerHTML);
d._editable = false;
render();
};
Card.zoom = function(){
var regex = {
scale: /scale\(([\d\.]*)\)/,
mtx: /matrix\(([\d\.]*), /,
};
var old_zoom = (
root.style("transform") ||
root.style("-webkit-transform") ||
"");
d3.entries(regex).map(function(regex, key){
var match = old_zoom.match(regex.value);
if(match !== null){
old_zoom = +match[1];
}
});
if(!old_zoom === null){
old_zoom = 1;
}
ZOOM = Math.max(0.01, old_zoom + d3.event.wheelDelta / 1000);
root.call(xb_scale(ZOOM));
};
Card.drag = d3.behavior.drag()
.origin(function(){
var that = d3.select(this);
return {
x: parseInt(that.style("left")),
y: parseInt(that.style("top"))
}
})
.on("drag", function(d, i){
if(editable(d)){return;}
d.x(d3.event.x)
.y(d3.event.y);
d3.select(this)
.style("left", d3.event.x + "px")
.style("top", d3.event.y + "px")
.style("z-index", Z++);
});
function attr(att){
return function(d){
return d[att];
};
}
attr.px = function(att){
var func = attr(att);
return function(d, i){
return func(d, i) + "px";
};
};
function xb_scale(amount){
var val = "scale(" + amount + ")";
return function(selection){
selection
.transition()
.style("transform", val)
.style("-webkit-transform", val)
};
}
// initialize the frame
var root = d3.select("body")
.on("mousewheel", Card.zoom)
.selectAll("#root")
.data([1]);
root.enter().append("div")
.attr("id", "root")
.on("dblclick", Card.create)
.call(xb_scale(ZOOM));
function editable(d, i){
return d._editable;
}
function render(){
var card = root.selectAll(".card")
.data(card_collection),
card_init = card.enter()
.append("div")
.attr("class", "card")
.call(Card.drag)
.style("left", function(d){ return d.x()+"px"; })
.style("top", function(d){ return d.y()+"px"; })
.on("dblclick", Card.click);
card_init.append("div")
.classed("text", 1)
.on("keydown", Card.keyup)
.on("blur", function(d, i){
d._editable = false;
Card.save.call(this, d,i);
});
card.select(".text")
.attr("contenteditable", editable)
.each(function(d, i){
this.innerHTML = d.text();
});
card
.style("left", attr.px("x"))
.style("top", attr.px("y"));
}
render();
}).call(this, d3);
<html>
<head>
<title>Card Moving/Editing Proof of Concept</title>
<style>
html, body{
margin: 0;
padding: 0;
overflow: hidden;
background-color: lightblue;
font-family: 'Gill Sans MT', 'Gill Sans';
}
#root{
width: 100%;
height: 100%;
}
.card{
height: 150px;
width: 150px;
position: absolute;
background-color: lightyellow;
overflow-y: auto;
text-align: center;
border-radius: 2px;
padding: 5px;
box-shadow: -1px 2px 5px 2px rgba(0, 0, 0, .25);
}
.card .text{
height: 100%;
width: 100%;
}
#doc{
position: fixed;
right: 10px;
bottom: 10px;
text-align: right;
opacity: .25;
}
</style>
</head>
<body>
<div id="doc">
<p>Double-click the background to make a card</p>
<p>Double-click a card to edit it</p>
<p>Zoom with mouse wheel</p>
</div>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="cards.js" charset="utf-8"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment