diff --git a/static/js/proxyMapper.js b/static/js/proxyMapper.js new file mode 100644 index 0000000..6198258 --- /dev/null +++ b/static/js/proxyMapper.js @@ -0,0 +1,171 @@ +(function(factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + define(['jquery'], factory); + } else if (window.jQuery && !window.jQuery.fn.ProxyMapper) { + factory(window.jQuery); + } + } + (function($) { + 'use strict'; + + var ProxyMapper = function(mapping, data, options) { + this.mapping = mapping; + this.data = data; + this._default_options = { + fillValue: 0 + }; + this.options = $.extend({}, this._default_options, options); + //this.result = { + // dates: [], + //}; + this.result = {}; + + //for (var k in this.mapping) { + // this.result[k] = []; + //} + this.result.dates = []; + + this.mappingDate = {}; + this.perform_mapping(); + return this.result; + }; + + ProxyMapper.prototype = { + constructor: ProxyMapper, + + perform_mapping: function(data) { + console.log(this.mapping); + if (this.mapping.dates.length > 0) { + this.c_dates(this.data, this.mapping.dates); // probe and fetch all dates + } + if (this.mapping.labels.length > 0) { + this.c_labels(this.data, this.mapping.labels); // probe and fetch all labels + } + if (this.mapping.labels.length > 0 && this.mapping.values.length > 0) { + this.c_values(this.data, this.mapping.labels); // fetch values and overwrite default values + } + }, + + c_dates: function(intermediate, instructions) { + var that = this; + var matchingFun = function (intermediate, instructions, additionalData) { + let index = instructions; + let val = intermediate[index]; + that.mappingDate[val] = that.result['dates'].length; + that.result['dates'].push(val); + }; + this.iter(intermediate, instructions, matchingFun, {}); + }, + + c_labels: function(intermediate, instructions, valuesLength) { + var that = this; + var matchingFun = function (intermediate, instructions, additionalData) { + let index = instructions; + let label = intermediate[index]; + let val = []; + for (var i=0; i 0 ) { + this.instructions = {}; + var that = this; + this.options.toBeMapped.forEach(function(item, index) { + that.instructions[item] = []; + that.itemColors.set(item, that.options.itemColors[index]); + }); + + // draw mapping table + this.draw_mapping_table(); + this.set_current_mapping_item(); + } + + if (this.options.interaction) { + //var result = new $.proxyMapper(this.instructions, this.treeData, {}); + this.treeDivResult = $('
'); + this.container.append(this.treeDivResult); + this.update_result_tree(); + } + + this.update(this.root); + } + + TreeFromJson.prototype = { + constructor: TreeFromJson, + + update: function(source) { + var that = this; + + // Compute the new tree layout. + var nodes = this.tree.nodes(this.root).reverse(), + links = this.tree.links(nodes); + + // Normalize for fixed-depth. + nodes.forEach(function(d) { d.y = d.depth * 100; }); + + // Update the nodes… + var node = this.svg.selectAll("g.node") + .data(nodes, function(d) { return d.id || (d.id = ++that.i); }); + + // Enter any new nodes at the parent's previous + var nodeEnter = node.enter().append("g") + .attr("class", "node") + .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; }); + if (this.options.interaction) { + nodeEnter.filter(function(d) { + return d.additionalNode === undefined || !d.additionalNode; + }) + .on("click", function(d, i) { that.click(d, i, this); }); + } else { + nodeEnter.attr("class", "node nodeNoInteraction"); + } + + nodeEnter.filter(function(d) { + return d.additionalNode === undefined || !d.additionalNode; + }) + .append("circle") + .attr("r", 1e-6) + .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }); + + nodeEnter.append("text") + .attr("x", function(d) { return d.children || d._children ? -13 : 13; }) + .attr("dy", ".35em") + .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; }) + .text(function(d) { return d.name; }) + .style("fill-opacity", 1e-6); + + + // Transition nodes to their new position. + var nodeUpdate = node.transition() + .duration(this.options.duration) + .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; }); + + nodeUpdate.select("circle") + .attr("r", 10) + .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; }); + + nodeUpdate.select("text") + .style("fill-opacity", 1); + + // Transition exiting nodes to the parent's new position. + var nodeExit = node.exit().transition() + .duration(this.options.duration) + .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; }) + .remove(); + + nodeExit.select("circle") + .attr("r", 1e-6); + + nodeExit.select("text") + .style("fill-opacity", 1e-6); + + // Update the links... + var link = this.svg.selectAll("path.link") + .data(links, function(d) { return d.target.id; }); + + // Enter any new links at the parent's previous position. + var linkEnter = link.enter().insert("g", "g"); + linkEnter.append("path") + .attr("class", "link") + .attr("d", function(d) { + var o = {x: source.x0, y: source.y0}; + return that.diagonal({source: o, target: o}); + }); + + + linkEnter.append('rect') + .attr("class", "rectText") + .attr("transform", function(d) { + return "translate(" + + d.source.y + "," + + d.source.x + ")"; + }) + .style("fill-opacity", 1e-6); + linkEnter.append('text') + .attr("class", "linkText") + .attr("font-family", "Arial, Helvetica, sans-serif") + .attr("fill", "Black") + .attr("transform", function(d) { + return "translate(" + + d.source.y + "," + + d.source.x + ")"; + }) + .attr("dy", ".35em") + .attr("text-anchor", "middle") + .text(function(d) { + return d.target.linkname; + }) + .style("fill-opacity", 1e-6); + + // update rectangle size based on text + linkEnter.selectAll("rect") + .attr("width", function(d) { return d.target.linkname !== undefined ? that.letterWidth*d.target.linkname.length : 0; }) + .attr("height", 22) + + + // Transition links to their new position. + var linkUpdate = link; + linkUpdate.select('path').transition() + .duration(this.options.duration) + .attr("d", this.diagonal); + + linkUpdate.select('rect').transition() + .duration(this.options.duration) + .style("fill-opacity", 1) + .attr("d", this.diagonal) + .attr("transform", function(d){ + let xoffset = d.target.linkname !== undefined ? that.letterWidth*d.target.linkname.length/2 : 0; + let yoffset = 10; + return "translate(" + + ((d.source.y + d.target.y)/2-xoffset) + "," + + ((d.source.x + d.target.x)/2-yoffset) + ")"; + } + ); + linkUpdate.select('text').transition() + .duration(this.options.duration) + .style("fill-opacity", 1) + .attr("d", this.diagonal) + .attr("transform", function(d){ + return "translate(" + + ((d.source.y + d.target.y)/2) + "," + + ((d.source.x + d.target.x)/2) + ")"; + } + ); + + // Transition exiting nodes to the parent's new position. + link.exit().select('path').transition() + .duration(this.options.duration) + .attr("d", function(d) { + var o = {x: source.x, y: source.y}; + return that.diagonal({source: o, target: o}); + }) + .remove(); + + // Stash the old positions for transition. + nodes.forEach(function(d) { + d.x0 = d.x; + d.y0 = d.y; + }); + }, + + find_child_index: function(child) { + var c_id = child.id; + var par = child.parent; + if (!par) { + return; + } + var children = par.children; + for (var i=0; i'); + var thead = $('') + var tbody = $('') + var row1 = $(''); + var row2 = $(''); + this.options.toBeMapped.forEach(function(item, index) { + var itemColor = that.options.itemColors[index]; + var cellH = $(''+item+''); + var cellB = $(''); + cellH.click(function() { that.set_current_mapping_item(item); }); + cellB.click(function() { that.set_current_mapping_item(item); }); + that.set_color(cellH, itemColor); + that.set_color(cellB, itemColor); + row1.append(cellH); + row2.append(cellB); + }); + thead.append(row1); + tbody.append(row2); + this.mappingDomTable.append(thead); + this.mappingDomTable.append(tbody); + this.fillValueDomInput = $(''); + var configDiv = $('
') + .append($('')) + .append(this.fillValueDomInput); + var div = $('
'); + div.append(this.mappingDomTable); + div.append(configDiv); + this.container.prepend(div); + + this.fillValueDomInput.on('input', function() { + that.update_result_tree(); + }); + }, + + set_color: function(item, color) { + item.css('background-color', color); + if (this.should_invert_text_color(color)) { + item.css('color', 'white'); + } else { + item.css('color', 'black'); + } + }, + + should_invert_text_color: function(color) { + var colorS = color.replace('#', ''); + var r = parseInt('0x'+colorS.substring(0,2)); + var g = parseInt('0x'+colorS.substring(2,4)); + var b = parseInt('0x'+colorS.substring(4,6)); + var avg = ((2 * r) + b + (3 * g))/6; + if (avg < 128) { + return true; + } else { + return false; + } + }, + + // if name is empty, select first item not having instructions + set_current_mapping_item: function(name) { + if (name === undefined) { + for (var entry of this.options.toBeMapped) { + if (this.instructions[entry].length == 0) { + name = entry; + break; + } + } + if (name === undefined) { // all items have a mapping, do nothing + return; + } + } + this.mappingDomTable.find('td').addClass('grey'); + this.mappingDomTable.find('td').removeClass('picking'); + var cell = this.mappingDomTable.find('#'+name+'Cell'); + var itemColor = this.itemColors.get(name); + cell.removeClass('grey'); + this.currentPickingCell = cell; + this.currentPicking = name; + }, + + add_instruction: function(instructions) { + this.instructions[this.currentPicking] = instructions; + this.currentPickingCell.text(instructions.toString()); + this.set_current_mapping_item(); + this.update_result_tree(); + }, + + // destroy and redraw + update_result_tree: function() { + var options = { + interaction: false + }; + + var adjusted_instructions = $.extend(true, {}, this.instructions); + var res=[]; + var l = adjusted_instructions.labels; + var v = adjusted_instructions.values; + for (var i=0; i maxWidth) { + var addNode = {}; + addNode.name = '...'; + addNode.parent = null; + addNode.additionalNode = true; + child['children'].push(addNode); + } + + } else if (this.isObject(root)) { + child.children = []; + + var i = 0; + for (var k in root) { + if (i > maxWidth) { + break; + } + var node = root[k]; + child.children.push(this.create_tree(node, k, depth-1, maxDepth, maxWidth)); + i++; + } + if (root.length > maxWidth) { + var addNode = {}; + addNode.name = '...'; + addNode.parent = null; + addNode.additionalNode = true; + child.children.push(addNode); + } + + } else { + child.name = root; + } + return child; + } + + } + + $.treeFromJson = TreeFromJson; + $.fn.treeFromJson = function(data, option) { + var pickerArgs = arguments; + var tfj; + + this.each(function() { + var $this = $(this), + inst = $this.data('treeFromJson'), + options = ((typeof option === 'object') ? option : {}); + if ((!inst) && (typeof option !== 'string')) { + tfj = new TreeFromJson($this, data, options); + $this.data('treeFromJson', tfj); + } else { + if (typeof option === 'string') { + inst[option].apply(inst, Array.prototype.slice.call(pickerArgs, 1)); + } + } + }); + return tfj; + } + $.fn.treeFromJson.constructor = TreeFromJson; + }) +); diff --git a/templates/test.html b/templates/test.html new file mode 100644 index 0000000..d6ad5d5 --- /dev/null +++ b/templates/test.html @@ -0,0 +1,357 @@ + + + + + + + + + + + Test + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +