// Generated by CoffeeScript 1.8.0 var createTangleControls, initChart; createTangleControls = function(id, options) { return new Tangle(document.getElementById("tangle-controls" + id), { initialize: function() { initialize(this); return _.extend(this, options); }, update: function() { return update(this, "#chart" + id, "#content" + id); } }); }; initChart = function(opts) { var automateMutate, cellHeight, cellWidth, chart, color, colorIndex, colorPalette, colorState, content, createSVG, custom, defsamp, generateAndSortColors, getFill, getHeight, getOpacity, getYOffset, headsState, height, isRendering, iteration, lastPalette, margin, max, maxCount, min, mutate, mutateIndex, ngramMax, offState, openState, optKeys, option_defaults, options, processData, rand, randomize, randomizeMutate, reset, sample0, sample1, sample2, sample3, seed, stackOffset, tokenizer, width, _ref; if (opts == null) { opts = {}; } sample0 = "I have a dream"; sample1 = "How much wood would a woodchuck chuck If a woodchuck could chuck wood? He would chuck, he would, as much as he could, And chuck as much as a woodchuck would If a woodchuck could chuck wood."; sample2 = "Any one and any one, one and one and two, and one and one and one, and one and many, and one and some, and one and any one, and any one and any one, any one and any one is one and one is one and one is some one and some one is some one, any one and one and one and one, any one is that one and that one is that one and any one and one, and one and one, any one is the one and the one who is the one is that one. The one who is the one who is that one, any one and any one is one, one is one, one is that one, and any one, any one is one and one is one, and one and one, and one and one and one and one."; sample3 = "On the first day of Christmas, my true love sent to me A partridge in a pear tree. On the second day of Christmas, my true love sent to me Two turtle doves, And a partridge in a pear tree. On the third day of Christmas, my true love sent to me Three French hens, Two turtle doves, And a partridge in a pear tree. On the fourth day of Christmas, my true love sent to me Four calling birds, Three French hens, Two turtle doves, And a partridge in a pear tree. On the fifth day of Christmas, my true love sent to me Five golden rings, Four calling birds, Three French hens, Two turtle doves, And a partridge in a pear tree. On the sixth day of Christmas, my true love sent to me Six geese a-laying, Five golden rings, Four calling birds, Three French hens, Two turtle doves, And a partridge in a pear tree. On the seventh day of Christmas, my true love sent to me Seven swans a-swimming, Six geese a-laying, Five golden rings, Four calling birds, Three French hens, Two turtle doves, And a partridge in a pear tree. On the eighth day of Christmas, my true love sent to me Eight maids a-milking, Seven swans a-swimming, Six geese a-laying, Five golden rings, Four calling birds, Three French hens, Two turtle doves, And a partridge in a pear tree. On the ninth day of Christmas, my true love sent to me Nine ladies dancing, Eight maids a-milking, Seven swans a-swimming, Six geese a-laying, Five golden rings, Four calling birds, Three French hens, Two turtle doves, And a partridge in a pear tree. On the tenth day of Christmas, my true love sent to me Ten lords a-leaping, Nine ladies dancing, Eight maids a-milking, Seven swans a-swimming, Six geese a-laying, Five golden rings, Four calling birds, Three French hens, Two turtle doves, And a partridge in a pear tree. On the eleventh day of Christmas, my true love sent to me Eleven pipers piping, Ten lords a-leaping, Nine ladies dancing, Eight maids a-milking, Seven swans a-swimming, Six geese a-laying, Five golden rings, Four calling birds, Three French hens, Two turtle doves, And a partridge in a pear tree. On the twelfth day of Christmas, my true love sent to me Twelve drummers drumming, Eleven pipers piping, Ten lords a-leaping, Nine ladies dancing, Eight maids a-milking, Seven swans a-swimming, Six geese a-laying, Five golden rings, Four calling birds, Three French hens, Two turtle doves, And a partridge in a pear tree! "; defsamp = sample1; option_defaults = { height: 0, width: 0, offset: false, tails: false, white: true, separateByType: false, onlyDuplicates: true, heightByCount: false, border: 0, opacityFactor: 1, opacityFloor: .2, opacityMax: .8, ngramMin: 2, ngramMax: 100, heightScale: 10, yScale: 10, sortAlgo: 3, opacityAlgo: 2, fillAlgo: 1, sampleDiv: "#content", sample: defsamp, palette: "Pimp", mutate: false }; options = _.extend({}, option_defaults, opts); custom = false; stackOffset = 0; offState = {}; headsState = {}; colorState = {}; openState = {}; lastPalette = false; colorPalette = false; isRendering = false; iteration = 1; maxCount = 0; height = width = colorIndex = cellHeight = cellWidth = max = min = 0; margin = { top: 50, right: 20, bottom: 150, left: 20 }; reset = function(resetColor) { if (resetColor == null) { resetColor = false; } stackOffset = colorIndex = 0; openState = {}; if (resetColor) { return colorState = {}; } }; window.setOptions = function(opts) { var _ref; reset((opts.paletteType !== options.paletteType) || (opts.palette !== options.palette)); if (opts.mutate !== options.mutate) { isRendering = options.mutate; } options = _.extend({}, option_defaults, opts); options.sample || (options.sample = defsamp); options.fillAlgo = options.paletteType === "d3" ? 2 : 1; if (options.separateByType) { options.sortAlgo = 2; } if (!custom) { if ((_ref = d3.select(options.sampleDiv)[0][0]) != null) { _ref.value = options.sample; } } window.setopts || (window.setopts = {}); window.setopts[opts.id] = _.extend({}, options); window.chartrender(false, false, lastPalette !== opts.palette); return lastPalette = opts.palette; }; if ((_ref = d3.select(options.sampleDiv)[0][0]) != null) { _ref.value = defsamp; } content = function() { var _ref1; return ((_ref1 = d3.select(options.sampleDiv)[0][0]) != null ? _ref1.value : void 0) || options.sample; }; window.chartrender = function(doRandomize, resetSVG, resetPalette) { if (doRandomize == null) { doRandomize = false; } if (resetSVG == null) { resetSVG = false; } if (resetPalette == null) { resetPalette = false; } if (doRandomize || !colorPalette || resetPalette) { colorPalette = generateAndSortColors(64); } if (!options.sampleDiv) { options = _.extend({}, window.setopts[options.id]); } options.sampleDiv || (options.sampleDiv = "#content"); return d3.select("svg").call(chart, processData(content(), doRandomize), resetSVG); }; d3.select(window).on("keyup", function() { custom = true; if (_([32, 46, 8, 13]).contains(d3.event.keyCode)) { _.defer(function() { return window.chartrender(); }); } if (_([27]).contains(d3.event.keyCode)) { return _.defer(function() { if ((isRendering = !isRendering)) { return window.chartrender(true); } }); } }); generateAndSortColors = function(numberOfColors) { var colors, pal; pal = { "Pimp": { hclrange: [[0, 360], [0.9, 10], [0.4, 10]], algo: 'kmeans' }, "Pastel": { hclrange: [[0, 360], [0, 0.9], [1, 10]], algo: 'kmeans' }, "Radical": { hclrange: [[0, 360], [0, 10], [0, 10]], algo: 'forcevector' }, "Ocean": { hclrange: [[220, 260], [0.3, 10], [0.5, 10]], algo: 'forcevector' } }[options.palette]; colors = paletteGenerator.generate(numberOfColors, (function(color) { var hcl, _ref1, _ref2, _ref3; hcl = color.hcl(); return ((pal.hclrange[0][0] <= (_ref1 = hcl[0]) && _ref1 <= pal.hclrange[0][1])) && ((pal.hclrange[1][0] <= (_ref2 = hcl[1]) && _ref2 <= pal.hclrange[1][1])) && ((pal.hclrange[2][0] <= (_ref3 = hcl[2]) && _ref3 <= pal.hclrange[2][1])); }), pal.algo === 'forcevector', 50); return paletteGenerator.diffSort(colors); }; tokenizer = new Tokenizer(); seed = function() { return Math.seedrandom(content()); }; mutateIndex = 0; ngramMax = 100; optKeys = _.without(_(options).keys(), "ngramMin", "ngramMax", "width", "height", "margin"); mutate = function() { return randomize((optKeys.sort(function() { return .5 - Math.random(); })).slice(0, 4)); }; randomizeMutate = function() { reset(true); if (!++mutateIndex % 3) { return randomize(); } else { return mutate(); } }; automateMutate = function(cycle) { return setInterval((function() { if (isRendering) { return window.chartrender(true); } }), cycle || 2000); }; rand = function(items) { return items[Math.floor(Math.random() * items.length)]; }; randomize = function(keys) { var key, _i, _len, _ref1; colorPalette = generateAndSortColors(64); _ref1 = keys || optKeys; for (_i = 0, _len = _ref1.length; _i < _len; _i++) { key = _ref1[_i]; options[key] = (function() { switch (key) { case "separateByType": return rand([true, false, false]); case "heightByCount": return rand([true, false, false]); case "offset": return rand([true, false]); case "tails": return rand([true, false]); case "border": return rand([0, 0, 1, 1, 5]); case "white": return rand([true, false]); case "opacityFactor": return rand([0, 1, .5]); case "opacityFloor": return rand([.2, .4]); case "opacityMax": return rand([.4, .4, .6, .8, .95]); case "sortAlgo": return rand([1, 2, 3, 3, 3]); case "opacityAlgo": return rand([.2, .5, 1, 2, 3, 4]); case "fillAlgo": return rand([0, 1, 1, 1, 1, 2, 2, 3]); case "palette": return rand(["Ocean", "Pimp", "Radical", "Pastel"]); } })(); } if ((!options['white']) && (options['border'] === 5)) { options['border'] = 1; } if (!options['fillAlgo']) { options['fillAlgo'] = rand([0, 0, 0, 1, 2, 3]); } if (options['separateByType']) { options['tails'] = false; } return console.log(JSON.stringify(options)); }; d3.select(window).on("resize", _.throttle((function() { width = 0; window.chartrender(false, true); return window.chartrender(false, true); }), 100)); createSVG = function() { var bodyW, id, svg, _ref1; bodyW = +d3.select("body").style('width').replace('px', ''); if ((0 < (_ref1 = options.width) && _ref1 < 1)) { width = bodyW * options.width; height = options.height || bodyW / 4; } else { width = options.width || bodyW; height = options.height || bodyW / 4; } if (!(id = options.id)) { return null; } d3.select("" + id + " svg").remove(); return svg = d3.select(id).append("svg").attr("width", width + 20).attr("height", height + margin.bottom).append("g").attr("transform", function(d) { return "translate(0,0)"; }); }; chart = function(svg, data, resetSVG) { var bars, div, getYScale, l, line, maxStart, minStart, mousemove, mouseout, scale, text, x; div = d3.select("body").append("div").attr("class", "tooltip"); maxStart = _(data).max(function(d) { return d.start; }); minStart = _(data).min(function(d) { return d.start; }); if (!(svg = createSVG())) { return; } scale = options.separateByType ? options.offset ? 1 : .5 : options.offset ? options.tails ? .5 : .25 : options.tails ? 1 : 1; mousemove = function(d) { return div.text((d.key.split('\/')).slice(1).join(' ')).style("left", "" + (d3.event.pageX + 40) + "px").style("top", "" + (d3.event.pageY + 20) + "px").style("color", (getFill(d)).toString()).style("border-color", (getFill(d)).toString()).style("opacity", .8); }; mouseout = function() { return div.style("opacity", 0); }; l = maxStart ? maxStart.start + maxStart.length : 0; x = d3.scale.linear().domain([0, cellWidth * (l || tokenizer.results.length)]).range([0, width]); svg.select(".line").remove(); if (tokenizer.results.length < 200) { line = svg.selectAll(".line").data(tokenizer.results); line.enter().append("line").attr("class", "line").attr("x1", 0).attr("y1", 30).attr("x2", 0).attr("y2", height + margin.top + margin.bottom).style("stroke", function() { if (!(maxStart != null ? maxStart.start : void 0)) { return "#99f"; } else { return "#ccc"; } }).style("stroke-width", function() { if (!(maxStart != null ? maxStart.start : void 0)) { return 2; } else { return 1; } }).style("stroke-opacity", function() { if (!(maxStart != null ? maxStart.start : void 0)) { return 1; } else { return .25; } }).attr("transform", function(d, i) { return "translate(" + (x(i * cellWidth) + 1) + ",0)"; }); } if (maxStart) { getYScale = function(d) { var count, method, y, y2, y3; count = _(data).reduce((function(memo, obj) { return memo + (obj.length - 1); }), 0); y = d3.scale.linear().domain([-max.length / scale, max.length / scale]).range([0, height]); y2 = d3.scale.linear().domain([0, -count * 2]).range([0, height]); y3 = d3.scale.linear().domain([0, -count]).range([0, height]); method = options.separateByType ? (options.offset ? y2 : y3) : y; return method(options.yScale / 10 * (getYOffset(d))); }; bars = svg.selectAll(".bar").data(data); bars.exit().remove(); bars.enter().append("rect"); bars.attr("class", "bar").attr("x", function(d) { return x(d.start * cellWidth) + 1; }).attr("y", function(d) { return getYScale(d); }).attr("width", function(d) { return x(d.length * cellWidth); }).attr("height", function(d) { return options.heightScale / 10 * (getHeight(d)); }).attr("transform", function(d) { return "translate(0," + margin.top + ")"; }).style("stroke", function(d) { if (options.white) { return '#fff'; } else { return '#000'; } }).style("stroke-width", function(d) { return options.border; }).style("fill", function(d) { return getFill(d); }).attr("opacity", function(d) { return getOpacity(d); }).on("mousemove", mousemove).on("mouseout", mouseout); } svg.select(".label").remove(); if (tokenizer.results.length < 200) { text = svg.selectAll(".label").data(tokenizer.results); return text.enter().append("text").attr("class", "label").text(function(d) { return d; }).attr("font-size", function(d, i) { if (!(maxStart != null ? maxStart.start : void 0)) { return 20; } else { return Math.max(20 - tokenizer.results.length / 2, 10); } }).attr("fill", function(d, i) { if (!(maxStart != null ? maxStart.start : void 0)) { return "#99f"; } else { return "#ccc"; } }).attr("transform", function(d, i) { return "translate(" + (3 + x(i * cellWidth) + 1) + ",30)rotate(-22.5)"; }); } }; processData = function(rawData, doRandomize) { var data, newdata, values; if (doRandomize == null) { doRandomize = false; } newdata = []; headsState = {}; offState = {}; colorIndex = 0; min = options.ngramMin || 2; max = options.ngramMax || 100; if (doRandomize) { randomizeMutate(); } tokenizer.clear(); tokenizer.allgrams(min, max, rawData); values = options.onlyDuplicates ? tokenizer.getDuplicates() : tokenizer.getAllTokens(); newdata.push(_(values).map(function(d) { return _(d.location).map(function(item) { return { key: d.key, length: d.length, count: d.location.length, start: item }; }); })); data = (function() { switch (options.sortAlgo) { case 1: return _(_.flatten(newdata)).sortBy(function(d) { return d.start; }); case 2: return _(_.flatten(newdata)).sortBy(function(d) { return d.length; }); case 3: return (_(_.flatten(newdata)).sortBy(function(d) { return d.length; })).reverse(); } })(); maxCount = _(data).max(function(d) { return d.count; }); if (max = _(data).max(function(d) { return d.length; })) { cellWidth = Math.floor(width / (data.length || tokenizer.results.length)); cellHeight = options.offset ? height / max.length : height / max.length / 4; } else { cellWidth = cellHeight = 1; } return data; }; getHeight = function(d) { var mult, value, _ref1; _ref1 = options.heightByCount ? [d.count / maxCount.count + 1, 3] : [d.length, 1], value = _ref1[0], mult = _ref1[1]; if (options.separateByType) { mult = .1; } return mult * cellHeight * (options.tails ? !options.offset ? (value - 1) * 2 : (value - 1) / 2 : !options.offset ? 2 : 1); }; getOpacity = function(d) { switch (options.opacityAlgo) { case 2: return .2 + d3.min([.1, (max.length - (_.min([max.length, d.length + 2]))) / (max.length * 4)]); case 3: return d3.max([options.opacityFloor, options.opacityMax - options.opacityFactor * d.length / 10]); case 4: return .2 + (1 - Math.abs(options.ngramMax - options.ngramMin) / 10) / 2; default: return options.opacityAlgo; } }; color = d3.scale.ordinal().domain(_(options.sample).map(function(d) { return d.key; })).range(["#FF0080", "#00FF80", "#8000FF"]); getFill = function(d) { var _name, _name1, _name2, _name3; switch (options.fillAlgo) { case 1: return colorState[_name = d.key] || (colorState[_name] = colorPalette[(++colorIndex) % 64]); case 2: return colorState[_name1 = d.key] || (colorState[_name1] = color(d.key)); case 3: return colorState[_name2 = d.key] || (colorState[_name2] = d.length % 2 === 0 ? '#2BFF00' : '#FF00DB'); default: return colorState[_name3 = d.key] || (colorState[_name3] = colorPalette[mutateIndex % colorPalette.length]); } }; getYOffset = function(d) { var extra, key, mult, offset, side; offset = d.start % 2 === 1; key = d.key; extra = 0; if (options.separateByType) { if (options.offset) { stackOffset -= 2 * (d.length - 1); return stackOffset; } else { if (openState[d.key]) { return openState[d.key]; } else { stackOffset -= 2 * (d.length - 1); return openState[d.key] = stackOffset; } } } if (headsState[key] === void 0) { headsState[key] = offset; } side = headsState[key] ? 1 : -1; if (options.offset) { if (options.heightByCount) { mult = options.yScale / 10; if (side === 1) { return (d.length - 2) * mult; } else { return (d.length - 1) * -mult; } } if (options.tails && options.yScale === options.heightScale) { if (side === 1) { return 0; } else { return (d.length - 1) * -2; } } else { if (side === 1) { return d.length * 2 - 4; } else { return (d.length - 1) * -2; } } } else { return d.length * (options.tails ? -1 : 1); } }; window.automateMutate = automateMutate; automateMutate(2000); return window.chartrender(false, true); };