<!DOCTYPE html>
<html>

<head>
    <meta charset='utf-8'>
    <meta http-equiv="X-UA-Compatible" content="chrome=1">
    <meta name="description" content="Online Ishikava / Fishbone diagram">
    <link rel="stylesheet" type="text/css" media="screen" href="stylesheet.css">
    <title>Online Ishikava / Fishbone diagram</title>
    <style>
        html, body{ margin: 0; padding: 0; overflow: hidden;background: none}

        *{ font-family: monospace; }

        .note {color:gray;font-size: 0.8em;}

        .label-0{ font-size: 2em; }
        .label-1{ font-size: 1.5em; fill: #111; }
        .label-2{ font-size: 1em; fill: #444; }
        .label-3{ font-size: .9em; fill: #888; }
        .label-4{ font-size: .8em; fill: #aaa; }
        .label-5{ font-size: .8em; fill: #aaa; }
        .label-6{ font-size: .8em; fill: #aaa; }

        .link-0{ stroke: #000; stroke-width: 2px}
        .link-1{ stroke: #333; stroke-width: 1px}
        .link-2,
        .link-3,
        .link-4,
        .link-5,
        .link-6{ stroke: #666; stroke-width: .5px; }

        .link-positive { stroke: blue; }
        .link-negative { stroke: red; }

        .positive { fill: green; stroke: green; }
        .negative { fill: red; stroke: red; }
    </style>
    <script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.4.1/d3.min.js" charset="utf-8"></script>
    <script src="./d3.fishbone.js" charset="utf-8"></script>
    <script src="./underscore-min.js" charset="utf-8"></script>
    <script src="./underscore.string.min.js" charset="utf-8"></script>
</head>

<body>

<!-- HEADER -->
<div id="header_wrap" class="outer">
    <header class="inner">
        <h2 id="project_tagline">Online Ishikava / Fishbone diagram</h2>
    </header>
</div>

<div style="padding: 2px;width: 24%;float:left;min-height: 1000px;">
    <p class="note">- Type brainstorm protocol below</p>
    <p class="note">- Redraw happens on Enter or use <button id="refresh">Refresh</button></p>
    <p class="note">- Use double-click on node to drill down</p>
    <p class="note">- Click to <a href="#">get back to root</a></p>
<textarea id="structure" style="width:100%; min-height: 600px;">
A Problem
- People
-- Fatigue
--- Why?
---- Why?
     ! Comment node with exclamation / @author / + for pros
     ! Comment node with exclamation / @author / - for cons

- Interactions
-- Precedent
--- Why?

- Processes
-- A lot of meetings
--- Why?

- Materials
-- Slow server
--- Why?

- Environment
-- Market is down
--- Why?

- Requirements
-- Too large stories
--- Why?
</textarea>
</div>

<div id="target" style="border: dotted 1px #000; min-height: 1000px; width: 75%;float:right"></div>

<script>

    var drawInContext = function() {

        var srcData = getData();

        var k = ((window.location.hash || '').substr(1) || srcData[0].k);

        var rec = srcData.filter(function (row) {
            return row.k === k;
        });

        if (rec.length === 0) {
            return [];
        }

        var path = rec[0].path + '/' + rec[0].k;

        var subX = srcData.filter(function (row) {
            return row.path.indexOf(path) === 0;
        });

        srcData = rec.concat(subX);

        drawFishbone(srcData);
    };

    $('#structure').on('keypress', function (e) {
        if (e.keyCode === 13) {
            parseSrc();
            drawInContext();
        }
    });

    $('#refresh').on('click', function (e) {
        parseSrc();
        drawInContext();
    });

    var size = (function () {
        var g = window.document.documentElement;
        return {
            width: $('#target').width(),
            height: g.clientHeight - 65
        };
    });

    var times = function (num) {
        var r = [];
        for (var i = 0; i < num; i++) r.push(i);
        return r;
    };

    var svg;
    var fishbone;
    var srcData = [];
    var feedback = [];

    function parseTokenRow(str, i) {
        var c = -1;
        while (str.charAt(++c) === '-');
        var token = str.substr(c).trim();
        var parts = token.split('/');
        return {
            level: c,
            key: (parts[0] + i),
            name: (parts[0]),
            rate: ((parts[1] === '+') ? (+1) : (-1))};
    }

    function parseCommentRow(str) {
        return str
                .trim()
                .substr(1) // remove !
                .split('/')
                .map(function (p) {
                    return p.trim();
                })
                .reduce(function (memo, p) {
                    var c = p.charAt(0);
                    if (c === '+') {
                        memo.rate = (+1);
                    } else if (c === '-') {
                        memo.rate = (-1);
                    } else if (c === '@') {
                        memo.author = p.substr(1);
                    } else {
                        memo.comment = p;
                    }
                    return memo;
                }, {});
    }

    function parseSrc() {

        var v = $('#structure').val();
        var t = v.split('\n');

        var path = [];
        feedback = [];
        srcData = [];
        t
                .filter(function (rowStr) {
                    return !!rowStr.trim();
                })
                .forEach(function (rowStr, i) {
                    var s = rowStr.trim();
                    if (s.charAt(0) === '!') {
                        // comment
                        var c = parseCommentRow(s);
                        feedback.push({
                            k: path[path.length - 1],
                            rate: (c.rate || -1),
                            comment: c.comment,
                            author: c.author
                        });
                    } else {
                        // structure
                        var o = parseTokenRow(s, i);
                        var lvl = o.level;
                        var key = o.key;
                        var name = o.name;
                        var rate = o.rate;
                        path[lvl] = key;
                        path = path.slice(0, (lvl + 1));
                        srcData.push({
                            "k": key,
                            "name": name,
                            "path": ['.'].concat(path.slice(0, lvl)).join('/'),
                            "rate": rate
                        });
                    }
                });
    }

    parseSrc();

    var forceLayout = function () {
        var s = size();
        var force = fishbone.force();
        force.size([s.width, s.height]);
        force.start();
        times(250).forEach(force.tick.bind(force));
        force.stop();

        force.start();
    };

    var onDblClickBranch = function (row) {
        window.location.hash = ('#' + row.k);
    };

    var getData = function () {
        return JSON.parse(JSON.stringify(srcData));
    };

    var drawFishbone = function (data) {

        // create the configurable selection modifier
        fishbone = d3.fishbone(
                size(),
                function () {
                    return data;
                },
                function () {
                    return feedback;
                },
                onDblClickBranch,
                function () {});

        var target = d3.select('#target');
        target.select('svg').remove();
        svg = target
                .append('svg')
                .attr(size())
                .call(fishbone.defaultArrow)
                .call(fishbone);

        forceLayout();
    };

    $(window).on('hashchange', drawInContext);
    drawInContext();

    // handle resizing the window
    d3
        .select(window)
        .on("resize", function () {
            forceLayout();
            svg.attr(size());
        });
</script>
<script>
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
                (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
            m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

    ga('create', 'UA-67431368-1', 'auto');
    ga('send', 'pageview');

</script>
</body>
</html>