Skip to content

Instantly share code, notes, and snippets.

@jonathaneunice
Created December 29, 2016 21:51
Show Gist options
  • Save jonathaneunice/f75a4f2644c0101b0f9159b468c7fbce to your computer and use it in GitHub Desktop.
Save jonathaneunice/f75a4f2644c0101b0f9159b468c7fbce to your computer and use it in GitHub Desktop.
/**
* CSS imperative declarations.
* E.g. cssi('div#one.two.three')
* yields { element: 'div',
* id: 'one',
* class: 'two three',
* }
* Classes are not split out into an array
* because that replicates information (anti DRY)
* and not especially compatible with D3 .attrs
*/
function cssi (s) {
s = s.trim();
var eltM = s.match(/^\w+/);
var idM = s.match(/#(\w+)/);
var classM = s.match(/\.(\w+)/g);
var attrM = s.match(/\[[^\]]*\]/g);
res = {};
if (eltM && eltM.length) res.element = eltM[0];
if (idM && idM.length) res.id = idM[1];
if (classM && classM.length)
res.class = classM.map(s => s.slice(1)).join(' ');
if (attrM && attrM.length) {
attrM.forEach(a => {
var insides = a.slice(1,-1); // take off [ and ]
insides.split(';').forEach(assign => {
assign = assign.trim();
var [__, left, right] = assign.match(/(.*?)\s*[=:]\s*(.*)/);
var rightFC = right.charAt(0);
if ((rightFC === '"') || (rightFC === "'")) {
right = right.slice(1, -1); // take off quotes
}
res[left] = right;
});
});
}
return res;
}
// does not ahndle typical .attr(name, value) case
// but does handle function => map, string => map
// and plain map
function attrx(map) {
var selection = this;
var tos = typeof map;
console.log('tos', tos)
if (tos === 'function')
return selection.each(function() {
var x = map.apply(this, arguments), s = select(this);
for (var name in x) s.attr(name, x[name]);
});
if (tos === 'string')
map = cssi(map);
for (var name in map) selection.attr(name, map[name]);
return selection;
}
function attrx(map) {
var selection = this;
var mapType = typeof map;
if (mapType === 'function')
return selection.each(function() {
var x = map.apply(this, arguments), s = select(this);
for (var name in x) s.attr(name, x[name]);
});
if (mapType === 'string')
map = cssi(map);
for (var name in map) selection.attr(name, map[name]);
return selection;
}
// simpler take on styles than attributes
// no functions supported yet; string or map asumed
function stylex(map) {
var selection = this;
var mapType = typeof map;
if (mapType === 'string')
map = cssi(map);
for (var name in map) selection.style(name, map[name]);
return selection;
}
function appendx(selector) {
var self = this;
var toAdd = cssi(selector);
self = self.append(toAdd.element);
for (var key in toAdd) {
if (key === 'element') continue;
self.attr(key, toAdd[key]);
}
return self;
}
// FIXME: need either more rigorous parser or to disallow colon on attrx and appendx
// link into D3 selection functions
d3.selection.prototype.appendx = appendx;
d3.selection.prototype.attrx = attrx;
d3.selection.prototype.stylex = stylex;
// for v3 need to extend the enter selection too
if (d3.version.charAt(0) === '3') {
d3.selection.enter.prototype.appendx = appendx;
d3.selection.enter.prototype.attrx = attrx;
d3.selection.enter.prototype.stylex = stylex;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment