From 61d01176b70f8f1f44eaa64e8359cd652a350e59 Mon Sep 17 00:00:00 2001 From: Sami Mokaddem Date: Mon, 27 Aug 2018 06:35:10 +0000 Subject: [PATCH] Added function capability to be applied on value + better input parsing and output generation --- static/js/proxyMapper.js | 136 +++++++++++++++++++++------ static/js/treeFromJson.js | 191 +++++++++++++++++++++++++++++++------- 2 files changed, 266 insertions(+), 61 deletions(-) diff --git a/static/js/proxyMapper.js b/static/js/proxyMapper.js index e070f6e..57881de 100644 --- a/static/js/proxyMapper.js +++ b/static/js/proxyMapper.js @@ -12,14 +12,18 @@ var ProxyMapper = function(mapping, data, options) { this.mapping = mapping; this.data = data; - console.log(options); this._default_options = { fillValue: 0, functions: { - dates: function (value) {return value;}, - labels: function (value) {return value;}, - values: function (value) {return value;} - } + dates: function (value, datum) {return value;}, + labels: function (value, datum) {return value;}, + values: function (value, datum) {return value;} + }, + prefillData: { + dates: [], + labels: [] + }, + datum: false // the tree data to walk in parallel }; this.options = $.extend({}, this._default_options, options); this.result = {}; @@ -36,19 +40,33 @@ perform_mapping: function(data) { if (this.mapping.dates.length > 0) { + for (var x of this.options.prefillData.dates) { this.result['dates'].push(x); } this.c_dates(this.data, this.mapping.dates); // probe and fetch all dates } + + let fillArray = []; + for (var i=0; i 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) { + + //if (this.mapping.labels.length > 0 && this.mapping.values.length > 0) { + if (Object.keys(this.result).length > 1 && this.mapping.values.length > 0) { this.c_values(this.data, this.mapping.values); // fetch values and overwrite default values for (var k in this.result) { this.result[k] = this.result[k].filter(function(n){ return n != undefined }); } } }, - + c_dates: function(intermediate, instructions) { var that = this; var matchingFun = function (intermediate, instructions, additionalData) { @@ -56,27 +74,32 @@ let val = intermediate[index]; if (that.mappingI2[val] === undefined) { that.mappingI2[val] = that.result['dates'].length; - let nval = that.options.functions.dates(val); + let nval = that.options.functions.dates(val, additionalData.datum); that.result['dates'].push(nval); } }; - this.iter(intermediate, instructions, matchingFun, {}); + this.iter(intermediate, instructions, matchingFun, { datum: this.options.datum }); }, c_labels: function(intermediate, instructions, valuesLength) { var that = this; var matchingFun = function (intermediate, instructions, additionalData) { + let reg = /\{(\w+)\}/; + let res = reg.exec(instructions); + if (res !== null) { + instructions = res[1]; + } let index = instructions; - if (index == 'l') { // labels are the key themself + if (index == 'l') { // labels are the keys themself for (let label in intermediate) { let val = []; for (var i=0; i 0) { + curI = this.fetch_value(intermediate[i], sub_instructions); + } else { + curI = i; + } + additionalData[i_type] = curI; + } + additionalData.datum = this.update_datum(additionalData.datum, i); + return this.iter(intermediate[i], instructions.slice(1), matchingFun, additionalData); + } + // fallback to standard loop + } if (!(Array.isArray(intermediate) || this.isObject(intermediate))) { @@ -155,7 +214,8 @@ } if (Array.isArray(intermediate)) { - for (var node of intermediate) { + for (var k=0; k 0 ) { this.instructions = {}; + this.prefillData = {}; var that = this; this.options.toBeMapped.forEach(function(item, index) { that.instructions[item] = []; + that.prefillData[item] = []; that.itemColors.set(item, that.options.itemColors[index]); }); @@ -142,7 +144,7 @@ var nodeEnterNotArray = nodeEnter.filter(function(d) { var not_add = d.additionalNode === undefined || !d.additionalNode; - var not_arr = d.children === undefined || d.children[0].linkname === undefined; + var not_arr = d.children === undefined || d.children[0].linkname === undefined || d.children[0].linkname !== ''; return not_add && not_arr; }); nodeEnterNotArray @@ -152,8 +154,8 @@ var nodeEnterArray = nodeEnter.filter(function(d) { var not_add = d.additionalNode === undefined || !d.additionalNode; - var is_arr = d.children !== undefined && d.children[0].linkname !== undefined; - return not_add && is_arr; + var not_arr = d.children === undefined || d.children[0].linkname === undefined || d.children[0].linkname !== ''; + return not_add && !not_arr; }); nodeEnterArray .append("rect") @@ -319,8 +321,8 @@ var children = par.children; for (var i=0; i simulate label click - let source = clicked.data()[0]; - let target = child; - if (target.linkname !== undefined && target.linkname !== '') { - var resL = this.svg.selectAll("path.link").filter(function(d) { - return d.source.id == source.id && d.target.id == target.id; + // First child is not a node, should highlight all labels instead + + var itemColor = this.itemColors.get(this.currentPicking); + var resRect = this.svg.selectAll(".rectText") + .filter(function(d) { + if (d.depth == 0) { + return false; + } + var c1 = d.source.depth == o_depth; + return c1; + }); + var resText = this.svg.selectAll(".linkText") + .filter(function(d) { + if (d.depth == 0) { + return false; + } + var c1 = d.source.depth == o_depth; + return c1; + }); + resRect.data().forEach(function(elem) { + if (elem.picked !== undefined && elem.picked != '') { + console.log('Possible collision with '+elem.picked); + } + elem.picked = that.currentPicking; + }); + + + resRect.style('fill', itemColor) + resText.style('fill', that.should_invert_text_color(itemColor) ? 'white' : 'black'); + + + resCircle = that.svg.selectAll(".node circle") + .filter(function(d) { + return d.parent.depth == clicked.data()[0].depth; + //return d.parent !== null && d.parent.id == clicked.data()[0].id; + }); + var nodesData = []; + if(resCircle !== undefined) { + resCircle.data().forEach(function(elem) { + if (elem.picked !== undefined && elem.picked != '') { + // alert || repick conflicting ???? + console.log('Possible collision with '+elem.picked); + //alert('Possible collision with '+elem.picked); + } + elem.picked = that.currentPicking; + nodesData.push(elem); }); - that.clickLabel(resL.data()[0]); } + + // find all paths + var paths = []; + nodesData.forEach(function(d, i) { + paths[i] = that.find_full_path(d, []); + }); + var instructions = this.compute_mapping_instructions(paths); + this.add_instruction(instructions); return; + + //let source = clicked.data()[0]; + //let target = child; + //if (target.linkname !== undefined && target.linkname !== '') { + // var resL = this.svg.selectAll("path.link").filter(function(d) { + // return d.source.id == source.id && d.target.id == target.id; + // }); + // that.clickLabel(resL.data()[0]); + //} + //return; } else { // children are leaves resCircle = that.svg.selectAll(".node circle") .filter(function(d) { @@ -434,6 +503,7 @@ var that = this; var o_depth = d.source.depth; var dest_depth = d.target.depth; + var c_label = d.target.linkname; var c_id = d.source.id; var c_index; // no index as the index is the label itself var itemColor = this.itemColors.get(this.currentPicking); @@ -447,7 +517,8 @@ return false; } var c1 = d.source.depth == o_depth; - return c1; + var c2 = d.target.linkname === c_label; + return c1 && c2; }); var resText = this.svg.selectAll(".linkText") .filter(function(d) { @@ -455,7 +526,8 @@ return false; } var c1 = d.source.depth == o_depth; - return c1; + var c2 = d.target.linkname === c_label; + return c1 && c2; }); @@ -473,15 +545,28 @@ // find all paths var paths = []; - var nodes = that.svg.selectAll(".node circle").filter( - function(d) { return d.depth == dest_depth;} + var nodesCircle = that.svg.selectAll(".node circle").filter( + function(d) { + return d.depth == dest_depth && d.linkname == c_label; + //return d.depth == dest_depth; + } ); - - nodes.data().forEach(function(d, i) { + nodesCircle.data().forEach(function(d, i) { paths[i] = that.find_full_path(d, []); }); - var instructions = this.compute_mapping_instructions(paths); - this.add_instruction(instructions); + var nodesRect = that.svg.selectAll(".node rect").filter( + function(d) { + return d.depth == dest_depth && d.linkname == c_label; + //return d.depth == dest_depth; + } + ); + nodesRect.data().forEach(function(d, i) { + paths[i] = that.find_full_path(d, []); + }); + + //var instructions = this.compute_mapping_instructions(paths); + //this.add_instruction(instructions); + this.add_prefill_data([c_label]); }, @@ -510,7 +595,7 @@ elem.picked = ''; }); - this.add_instruction(''); + this.add_instruction([]); }, @@ -524,7 +609,7 @@ if (prevVal === null) { prevVal = arr[i]; } else { - if (prevVal != arr[i]) { // value different, nood to loop over them + if (prevVal != arr[i]) { // value different, need to loop over them instruction = 'l' break; } @@ -617,7 +702,7 @@ set_current_mapping_item: function(name) { if (name === undefined) { for (var entry of this.options.toBeMapped) { - if (this.instructions[entry].length == 0) { + if (this.instructions[entry].length == 0 && this.prefillData[entry].length == 0) { name = entry; break; } @@ -645,6 +730,13 @@ this.update_result_tree(); }, + add_prefill_data: function(data) { + this.prefillData[this.currentPicking] = data; + this.currentPickingCell.text(data.toString()); + this.set_current_mapping_item(); + this.update_result_tree(); + }, + // destroy and redraw update_result_tree: function() { var options = { @@ -661,13 +753,15 @@ $('.mappingTable textarea').each(function() { var dom = $(this); var f_body = dom.val(); - functions[dom[0].id] = new Function('value', 'd', f_body); + functions[dom[0].id] = new Function('value', 'datum', f_body); }); // perform mapping var pm_options = { fillValue: this.fillValueDomInput.val(), - functions: functions + functions: functions, + datum: this.root, + prefillData: this.prefillData }; var adjustedInstructions = this.adjust_instruction(); var result = new $.proxyMapper(adjustedInstructions, this.data, pm_options); @@ -687,13 +781,21 @@ // label & value if (l.length != 0 && v.length != 0) { var smaller_array = v.length < l.length ? v : l; + var has_matched = false; for (var i=0; i maxWidth) { var addNode = {}; var remaining = root.length - maxWidth; - addNode.name = ''+remaining+'...'; + //addNode.name = ''+remaining+'...'; + addNode.name = '['+remaining+' more]'; addNode.parent = null; addNode.additionalNode = true; child['children'].push(addNode); @@ -805,7 +925,8 @@ if (Object.keys(root).length > maxWidth) { var addNode = {}; var remaining = root.length - maxWidth; - addNode.name = ''+remaining+' ...'; + //addNode.name = ''+remaining+' ...'; + addNode.name = '['+remaining+' more]'; addNode.parent = null; addNode.additionalNode = true; child.children.push(addNode);