<commit_before>/* ========================================================================
 * ZUI: treemap.js
 * http://zui.sexy
 * ========================================================================
 * Copyright (c) 2014-2016 cnezsoft.com; Licensed MIT
 * ======================================================================== */


// Tree map data format
// {
//      text: main text,
//      html: main text as html format
//      style: node style,
//      textColor: text color,
//      color: background color
//      border: border style,
//      cableWidth: 2,
//      cableColor: '#808080'
//      cableStyle: 'solid'
// }


(function($, window, document, Math, undefined) {
    'use strict';

    var NAME = 'zui.treemap',
        DEFAULTS = {
            data: [],
            // direction: 'bottom', // or 'top', 'left', 'right'
            cableWidth: 1,
            cableColor: '#808080',
            cableStyle: 'solid',
            rowSpace: 30,
            nodeSpace: 20,
            listenNodeResize: true,
            nodeTemplate: '<div class="treemap-node"><a class="treemap-node-wrapper"></a></div>',
            foldable: true,
            clickNodeToFold: true,
            // sort: false, // Boolean or function
            // tooltip: null,
            // nodeStyle: null,
        };
        // var  DEFAULT_NODE = {
            // id: uuid(),           // uuid
            // text: '',             // main text,
            // html: '',             // main text as html format
            // style: null,          // node element style
            // textColor: '',        // text color
            // color: '',            // background color
            // border: '',           // border style,
            // tooltip: ''           // node caption
            // attrs: null           // attrs
            // title: ''             // node title
            // tooltip: ''           // node tooltip
        // };

    var getDataFromUlList = function($list) {
        return $list.children('li,.treemap-data-item').map(function() {
            var $item = $(this),
                item = $item.data(),
                $text = $item.children('.text'),
                $html = $item.children('.content'),
                $children = $item.children('ul,.treemap-data-list');
            if($text.length) item.text = $text.text();
            if($html.length) item.html = $html.html();
            if($children.length) {
                item.children = getDataFromUlList($children);
            }
            if(!item.text && !item.html) {
                var $content = $item.children(':not(ul,.treemap-data-list)');
                var $itemClone = $item.clone();
                $itemClone.find('ul,.treemap-data-list').remove();
                if(!$content.length) {
                    item.text = $itemClone.text();
                } else {
                    item.html = $itemClone.html();
                }
            }
            if(!item.id) item.id = $.zui.uuid();
            return item;
        }).get();
    };

    var Treemap = function(element, options) {
        var $element = $(element);
        if($.isArray(options)) {
            options = {data: options};
        }
        options = $.extend({}, DEFAULTS, $element.data(), options);
        
        var data = options.data || [];
        if(!data.length) {
            var $dataList = $element.children('.treemap-data');
            if($dataList.length) {
                data = getDataFromUlList($dataList.hide());
            }
        }

        var $nodes = $element.children('.treemap-nodes');
        if(!$nodes.length) {
            $nodes = $('<div class="treemap-nodes" unselectable="on"/>').appendTo($element);
        }

        var that     = this;
        that.$       = $element;
        that.$nodes  = $nodes;
        that.data    = $.isArray(data) ? data : [data];
        that.options = options;
        that.offsetX = 0;
        that.offsetY = 0;
        that.scale   = options.scale || 1;

        // Bind events
        
        that.render();

        $nodes.on('resize', '.treemap-node-wrapper', function() {
            that.delayDrawLines();
        });
        if(options.foldable) {
            $nodes.on('click', options.clickNodeToFold ? '.treemap-node-wrapper' : '.treemap-node-fold-icon', function() {
                var $node = $(this).closest('.treemap-node').addClass('tree-node-collapsing');
                $node.toggleClass('collapsed').find('[data-toggle="tooltip"]').tooltip('hide');
                that.drawLines();
                setTimeout(function() {
                    $node.removeClass('tree-node-collapsing');
                }, 200);
            });
        }

        $nodes.on('click', '.treemap-node-wrapper', function() {
            var $node = $(this).closest('.treemap-node');
            that.callEvent('onNodeClick', $node.data('node'));
        });
    };

    Treemap.prototype.render = function(data) {
        var that       = this;
        that.data = data || that.data;

        if(that.data) {
            that.createNodes();
            that.drawLines();
        }

        that.callEvent('afterRender');
    };

    Treemap.prototype.createNodes = function(nodes, parent, callback) {
        var that       = this,
            options    = that.options,
            rowSpace   = options.rowSpace,
            $nodes     = that.$nodes;
        if(!parent) {
            $nodes.find('.treemap-node-wrapper').off('resize.' + NAME);
            $nodes.empty();
        }
        if(options.sort) {
            nodes.sort($.isFunction(options.sort) ? options.sort : function(nodeX, nodeY) {
                return (nodeX.order || 0) - (nodeY.order);
            });
        }
        var lastNode = null;
        nodes = nodes || that.data;
        $.each(nodes || that.data, function(idx, node) {
            if(typeof node === 'string') {
                node = {html: node};
                nodes[idx] = node;
            }

            // Create node element
            var $node = $.isFunction(options.nodeTemplate) ? options.nodeTemplate(node, that) : $(options.nodeTemplate);

            // Create node wrapper element
            var $wrapper = $node.find('.treemap-node-wrapper');
            if(!$wrapper.length) {
                $wrapper = $('<div class="treemap-node-wrapper"/>').appendTo($node);
            }

            var children = node.children;
            var hasChild = children && children.length;
            node.isOnlyOneChild = hasChild === 1;

            // Set node data attributes
            node.idx    = idx;
            var row = parent ? (parent.row + 1) : 0;
            $node.toggleClass('treemap-node-has-child', !!hasChild)
                 .toggleClass('treemap-node-has-parent', !!parent)
                 .toggleClass('treemap-node-one-child', hasChild === 1)
                 .toggleClass('collapsed', !!node.collapsed && node.collapsed !== 'false')
                 .toggleClass('treemap-node-root', !row)
                 .attr('data-id', node.id).data('node', node);
            node.row = row;

            // Set node element attributes and sytle
            var style = $.extend({}, options.nodeStyle, node.style);
            if(node.textColor) style.color = node.textColor;
            if(node.color) style.backgroundColor = node.color;
            if(node.border) style.border = node.border;
            var attrs = $.extend({}, node.attrs, {
                title: node.caption
            });
            if(node.tooltip) {
                attrs['data-toggle'] = 'tooltip';<commit_msg> * add new attribute 'className' to set node class names.<commit_after>/* ========================================================================
 * ZUI: treemap.js
 * http://zui.sexy
 * ========================================================================
 * Copyright (c) 2014-2016 cnezsoft.com; Licensed MIT
 * ======================================================================== */


// Tree map data format
// {
//      text: main text,
//      html: main text as html format
//      style: node style,
//      textColor: text color,
//      color: background color
//      border: border style,
//      cableWidth: 2,
//      cableColor: '#808080'
//      cableStyle: 'solid'
// }


(function($, window, document, Math, undefined) {
    'use strict';

    var NAME = 'zui.treemap',
        DEFAULTS = {
            data: [],
            // direction: 'bottom', // or 'top', 'left', 'right'
            cableWidth: 1,
            cableColor: '#808080',
            cableStyle: 'solid',
            rowSpace: 30,
            nodeSpace: 20,
            listenNodeResize: true,
            nodeTemplate: '<div class="treemap-node"><a class="treemap-node-wrapper"></a></div>',
            foldable: true,
            clickNodeToFold: true,
            // sort: false, // Boolean or function
            // tooltip: null,
            // nodeStyle: null,
        };
        // var  DEFAULT_NODE = {
            // id: uuid(),           // uuid
            // text: '',             // main text,
            // html: '',             // main text as html format
            // style: null,          // node element style
            // textColor: '',        // text color
            // color: '',            // background color
            // border: '',           // border style,
            // tooltip: ''           // node caption
            // attrs: null           // attrs
            // title: ''             // node title
            // tooltip: ''           // node tooltip
        // };

    var getDataFromUlList = function($list) {
        return $list.children('li,.treemap-data-item').map(function() {
            var $item = $(this),
                item = $item.data(),
                $text = $item.children('.text'),
                $html = $item.children('.content'),
                $children = $item.children('ul,.treemap-data-list');
            if($text.length) item.text = $text.text();
            if($html.length) item.html = $html.html();
            if($children.length) {
                item.children = getDataFromUlList($children);
            }
            if(!item.text && !item.html) {
                var $content = $item.children(':not(ul,.treemap-data-list)');
                var $itemClone = $item.clone();
                $itemClone.find('ul,.treemap-data-list').remove();
                if(!$content.length) {
                    item.text = $itemClone.text();
                } else {
                    item.html = $itemClone.html();
                }
            }
            if(!item.id) item.id = $.zui.uuid();
            return item;
        }).get();
    };

    var Treemap = function(element, options) {
        var $element = $(element);
        if($.isArray(options)) {
            options = {data: options};
        }
        options = $.extend({}, DEFAULTS, $element.data(), options);
        
        var data = options.data || [];
        if(!data.length) {
            var $dataList = $element.children('.treemap-data');
            if($dataList.length) {
                data = getDataFromUlList($dataList.hide());
            }
        }

        var $nodes = $element.children('.treemap-nodes');
        if(!$nodes.length) {
            $nodes = $('<div class="treemap-nodes" unselectable="on"/>').appendTo($element);
        }

        var that     = this;
        that.$       = $element;
        that.$nodes  = $nodes;
        that.data    = $.isArray(data) ? data : [data];
        that.options = options;
        that.offsetX = 0;
        that.offsetY = 0;
        that.scale   = options.scale || 1;

        // Bind events
        
        that.render();

        $nodes.on('resize', '.treemap-node-wrapper', function() {
            that.delayDrawLines();
        });
        if(options.foldable) {
            $nodes.on('click', options.clickNodeToFold ? '.treemap-node-wrapper' : '.treemap-node-fold-icon', function() {
                var $node = $(this).closest('.treemap-node').addClass('tree-node-collapsing');
                $node.toggleClass('collapsed').find('[data-toggle="tooltip"]').tooltip('hide');
                that.drawLines();
                setTimeout(function() {
                    $node.removeClass('tree-node-collapsing');
                }, 200);
            });
        }

        $nodes.on('click', '.treemap-node-wrapper', function() {
            var $node = $(this).closest('.treemap-node');
            that.callEvent('onNodeClick', $node.data('node'));
        });
    };

    Treemap.prototype.render = function(data) {
        var that       = this;
        that.data = data || that.data;

        if(that.data) {
            that.createNodes();
            that.drawLines();
        }

        that.callEvent('afterRender');
    };

    Treemap.prototype.createNodes = function(nodes, parent, callback) {
        var that       = this,
            options    = that.options,
            rowSpace   = options.rowSpace,
            $nodes     = that.$nodes;
        if(!parent) {
            $nodes.find('.treemap-node-wrapper').off('resize.' + NAME);
            $nodes.empty();
        }
        if(options.sort) {
            nodes.sort($.isFunction(options.sort) ? options.sort : function(nodeX, nodeY) {
                return (nodeX.order || 0) - (nodeY.order);
            });
        }
        var lastNode = null;
        nodes = nodes || that.data;
        $.each(nodes || that.data, function(idx, node) {
            if(typeof node === 'string') {
                node = {html: node};
                nodes[idx] = node;
            }

            // Create node element
            var $node = $.isFunction(options.nodeTemplate) ? options.nodeTemplate(node, that) : $(options.nodeTemplate);

            // Create node wrapper element
            var $wrapper = $node.find('.treemap-node-wrapper');
            if(!$wrapper.length) {
                $wrapper = $('<div class="treemap-node-wrapper"/>').appendTo($node);
            }

            var children = node.children;
            var hasChild = children && children.length;
            node.isOnlyOneChild = hasChild === 1;

            // Set node data attributes
            node.idx    = idx;
            var row = parent ? (parent.row + 1) : 0;
            $node.toggleClass('treemap-node-has-child', !!hasChild)
                 .toggleClass('treemap-node-has-parent', !!parent)
                 .toggleClass('treemap-node-one-child', hasChild === 1)
                 .toggleClass('collapsed', !!node.collapsed && node.collapsed !== 'false')
                 .toggleClass('treemap-node-root', !row)
                 .attr('data-id', node.id).data('node', node);
            if(node.className) {
                $node.addClass(node.className);
            }
            node.row = row;

            // Set node element attributes and sytle
            var style = $.extend({}, options.nodeStyle, node.style);
            if(node.textColor) style.color = node.textColor;
            if(node.color) style.backgroundColor = node.color;
            if(node.border) style.border = node.border;
            var attrs = $.extend({}, node.attrs, {
                title: node.caption
            });
            if(node.tooltip) {
                attrs['data-toggle'] = 'tooltip';
{'fraction_non_alphanumeric': 0.1789870619595605, 'fraction_numerical': 0.004811130615694688, 'mean_word_length': 1.5428996528351793, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5171181', 'n_tokens_mistral': 4280, 'n_tokens_neox': 4122, 'n_words': 814}