Mercurial > hg > NetworkVis
comparison query_builder/querybuild.html @ 32:acc60a20582c
Temporary Changes for querybuilder. Selecting attribute and having results list filter not fully working yet. Need 'ALL' option in attributes.
| author | arussell |
|---|---|
| date | Sat, 19 Dec 2015 09:15:43 -0500 |
| parents | 5384b71df52a |
| children | 4bbb832c53ac |
comparison
equal
deleted
inserted
replaced
| 28:5384b71df52a | 32:acc60a20582c |
|---|---|
| 5 <title>Query Builder</title> | 5 <title>Query Builder</title> |
| 6 <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"> | 6 <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"> |
| 7 <link rel="stylesheet" href="select2-4.0.1/dist/css/select2.min.css"> | 7 <link rel="stylesheet" href="select2-4.0.1/dist/css/select2.min.css"> |
| 8 | 8 |
| 9 <script type="text/javascript" src="js/d3.min.js"></script> | 9 <script type="text/javascript" src="js/d3.min.js"></script> |
| 10 <script type="text/javascript" src="js/underscore-min.js"></script> | |
| 10 <script type="text/javascript" src="select2-4.0.1/vendor/jquery-2.1.0.js"></script> | 11 <script type="text/javascript" src="select2-4.0.1/vendor/jquery-2.1.0.js"></script> |
| 11 <script type="text/javascript" src="select2-4.0.1/dist/js/select2.full.min.js"></script> | 12 <script type="text/javascript" src="select2-4.0.1/dist/js/select2.full.min.js"></script> |
| 13 | |
| 12 | 14 |
| 13 | 15 |
| 14 </head> | 16 </head> |
| 15 <body style="background:none;"> | 17 <body style="background:none;"> |
| 16 <div role="navigation" class="navbar navbar-default navbar-static-top"> | 18 <div role="navigation" class="navbar navbar-default navbar-static-top"> |
| 47 <div class="s2-example"> | 49 <div class="s2-example"> |
| 48 <div id="filters"> | 50 <div id="filters"> |
| 49 <div class="row" id="startrow" style="margin-top: 15px"> | 51 <div class="row" id="startrow" style="margin-top: 15px"> |
| 50 <div class="col-sm-4 col-md-4" id="select-col1"> | 52 <div class="col-sm-4 col-md-4" id="select-col1"> |
| 51 <select class="selected-object form-control"> | 53 <select class="selected-object form-control"> |
| 52 <option selected>Selected object is: </option> | 54 <option selected>Object type : </option> |
| 53 </select> | 55 </select> |
| 54 </div> | 56 </div> |
| 55 <div class="col-sm-4 col-md-4" id="select-col2"> | 57 <div class="col-sm-4 col-md-4" id="select-col2"> |
| 56 <select class="select-object1 form-control"> | 58 <select class="select-object1 form-control"> |
| 57 <option selected>TEXT</option> | 59 <option selected>TEXT</option> |
| 58 <option>WITNESS</option> | 60 <option>WITNESS</option> |
| 59 <option>PERSON</option> | 61 <option>PERSON</option> |
| 62 <option>CODEX</option> | |
| 63 <option>PLACE</option> | |
| 64 <option>REPOSITORY</option> | |
| 65 <option>COLLECTION</option> | |
| 60 </select> | 66 </select> |
| 61 </div> | 67 </div> |
| 62 </div> | 68 </div> |
| 63 <div class="row" id="row1" style="margin-top: 15px"> | 69 <div class="row" id="row1" style="margin-top: 15px"> |
| 64 <div class="col-sm-4 col-md-4" id="1filter-col1"> | 70 <div class="col-sm-4 col-md-4" id="1filter-col1"> |
| 103 | 109 |
| 104 // Defining initial variables and helper functions | 110 // Defining initial variables and helper functions |
| 105 var sourceType = "TEXT"; | 111 var sourceType = "TEXT"; |
| 106 var targets = []; | 112 var targets = []; |
| 107 var targetTypes = []; | 113 var targetTypes = []; |
| 108 var listTolerance = 100; | 114 var targetObj = []; // The current objects on the display box |
| 109 var numFilters = 1; | 115 var numFilters = 1; |
| 110 var filters = [ | 116 var filters = [ |
| 111 { id: 0, text: 'has relation' }, | 117 { id: 0, text: 'has relation' }, |
| 112 { id: 1, text: 'attribute contains' } | 118 { id: 1, text: 'attribute' } |
| 113 ]; | 119 ]; |
| 114 $(".filter-box"+numFilters).select2({ | 120 $(".filter-box"+numFilters).select2({ |
| 115 // Initialize first filter box | 121 // Initialize first filter box |
| 116 data: filters, | 122 data: filters, |
| 117 minimumResultsForSearch: Infinity | 123 minimumResultsForSearch: Infinity |
| 118 }); | 124 }); |
| 125 var listTolerance = 100; | |
| 126 //$("") | |
| 127 | |
| 119 function filter_html(n) { | 128 function filter_html(n) { |
| 120 return '<div class="row" id="row'+n+'" style="margin-top: 15px">' + | 129 return '<div class="row" id="row'+n+'" style="margin-top: 15px">' + |
| 121 '<div class="col-sm-4 col-md-4" id="'+n+'filter-col1">' + | 130 '<div class="col-sm-4 col-md-4" id="'+n+'filter-col1">' + |
| 122 '<select class="filter-box'+n+' form-control">' + | 131 '<select class="filter-box'+n+' form-control">' + |
| 123 '<option value="" disabled selected>Choose filter...</option>' + | 132 '<option value="" disabled selected>Choose filter...</option>' + |
| 125 '</div>' + | 134 '</div>' + |
| 126 '</div>'; | 135 '</div>'; |
| 127 } | 136 } |
| 128 function constraint_html(classn) { | 137 function constraint_html(classn) { |
| 129 return '<div class="col-sm-4 col-md-4" id="'+classn+'filter-col2">' + | 138 return '<div class="col-sm-4 col-md-4" id="'+classn+'filter-col2">' + |
| 130 '<select class="constraint-box'+classn+' form-control" >' + | 139 '<select class="rel-constraint-box'+classn+' form-control" >' + |
| 131 '</select>' + | 140 '</select>' + |
| 132 '</div>'; | 141 '</div>'; |
| 133 } | 142 } |
| 143 function attr_constraint_html(classn) { | |
| 144 return '<div class="col-sm-4 col-md-4" id="'+classn+'filter-col2">' + | |
| 145 '<select class="attr-constraint-box'+classn+' form-control" >' + | |
| 146 '</select>' + | |
| 147 '</div>'; | |
| 148 } | |
| 134 function submit_html(classn) { | 149 function submit_html(classn) { |
| 135 return '<div class="col-sm-4 col-md-4" id="'+classn+'filter-col2">' + | 150 return '<div class="col-sm-4 col-md-4" id="'+classn+'filter-col3">' + |
| 136 '<div class="form-group'+classn+'">' + | 151 '<div class="form-group'+classn+'">' + |
| 137 '<textarea class="form-control" rows="1" id="attribute-text-search'+classn+'">' + | 152 '<form onsubmit="return false;"> ' + |
| 138 '</textarea>' + | 153 '<input type="text" name="attr-field" class="form-control" id="attr-input'+classn+'">' + |
| 154 '</input>' + | |
| 155 '</form>' + | |
| 139 '</div>' + | 156 '</div>' + |
| 140 '</div>'; | 157 '</div>'; |
| 141 } | 158 } |
| 142 function select_html(selection) { | 159 function select_html(selection, n) { |
| 143 return '<div class="row" id="startrow" style="margin-top: 15px">' + | 160 return '<div class="row" id="row'+n+'" style="margin-top: 15px">' + |
| 144 '<div class="col-sm-4 col-md-4" id="select-col1"> ' + | 161 '<div class="col-sm-4 col-md-4" id="select-col1"> ' + |
| 145 '<select class="selected-object form-control"> ' + | 162 '<select class="selected-object form-control"> ' + |
| 146 '<option selected>Selected object is: </option> ' + | 163 '<option selected>Selected object is: </option> ' + |
| 147 '</select> ' + | 164 '</select> ' + |
| 148 '</div> ' + | 165 '</div> ' + |
| 149 '<div class="col-sm-4 col-md-4" id="select-col2"> ' + | 166 '<div class="col-sm-4 col-md-4" id="select-col2"> ' + |
| 150 '<select class="select-object1 form-control"> ' + | 167 '<h4>' + selection + |
| 151 '<option selected>TEXT</option> ' + | 168 '</h4>' + |
| 152 '<option>WITNESS</option> ' + | |
| 153 '<option>PERSON</option> ' + | |
| 154 '</select> ' + | |
| 155 '</div> ' + | 169 '</div> ' + |
| 156 '</div>'; | 170 '</div>'; |
| 157 } | 171 } |
| 158 | 172 |
| 159 | 173 |
| 173 console.log("minus filter"); | 187 console.log("minus filter"); |
| 174 $("#row"+numFilters).remove(); | 188 $("#row"+numFilters).remove(); |
| 175 numFilters--; | 189 numFilters--; |
| 176 }); | 190 }); |
| 177 $("#results-container").dblclick(function() { | 191 $("#results-container").dblclick(function() { |
| 178 if ($("#results-container option:selected").length == 1) { | 192 var displayChoice = $("#results-container").find("option:selected").text(); |
| 179 var selection = $(this).text(); | 193 console.log(displayChoice + "........."); |
| 180 console.log("add filter"); | 194 var selection; |
| 181 numFilters++; | 195 |
| 182 $("#filters").append(select_html(selection, numFilters)); | 196 _.map(targetObj, function(obj){ |
| 183 // Generate inner relation list | 197 |
| 184 genRelations(sourceType, ".constraint-box"+classnum); | 198 if (_.values(_.values(targetObj))[1] === displayChoice) { |
| 185 | 199 selection = (_.values(_.values(obj))[0])[1]; |
| 186 } | 200 } |
| 201 else { | |
| 202 selection = (_.values(_.values(obj))[0])[0]; | |
| 203 } | |
| 204 }); | |
| 205 numFilters++; | |
| 206 $("#filters").append(select_html(selection, numFilters)); | |
| 207 // Generate inner relation list | |
| 208 //genRelations(sourceType, ".constraint-box"+numFilters); | |
| 209 sourceType = selection; | |
| 187 console.log("add filter"); | 210 console.log("add filter"); |
| 188 }); | 211 }); |
| 189 | 212 $(function() { |
| 190 | 213 $("input").submit(function(event, data) { |
| 191 | 214 console.log($('.form-control').find("option:selected").text()); |
| 192 | 215 console.log(event); |
| 193 // For use in the onchange events below | 216 console.log(data); |
| 194 function genRelations(sourceNodeType, constraintBox) { | 217 event.preventDefault(); |
| 195 var query = "match (source:"+sourceNodeType+")-[rel]-target return distinct rel.type"; | 218 |
| 196 ajax1(query, constraintBox); | 219 }); |
| 197 } | 220 }); |
| 198 function genResults(sourceNodeType, selected, constraintBox) { | 221 |
| 199 var query = "match (source:"+sourceNodeType+")-["+selected+"]-(target) return target.label, target.type"; | |
| 200 ajax1(query, constraintBox); | |
| 201 } | |
| 202 // Can be used to return a list of all available attributes | |
| 203 // TODO: Not implemented | |
| 204 function genAttributes(sourceNodeType, constraintBox) { | |
| 205 var query = "match (n:"+sourceNodeType+") with keys(n) as collection unwind collection as attributes return distinct attributes"; | |
| 206 ajax1(query, constraintBox); | |
| 207 } | |
| 208 | 222 |
| 209 // Change Events | 223 // Change Events |
| 210 $('body').on('change', function(event){ | 224 $('body').on('change', function(event){ |
| 211 var classname = (event.target.className).substr(0, (event.target.className).indexOf(" ")); | 225 var classname = (event.target.className).substr(0, (event.target.className).indexOf(" ")); |
| 212 var classnum = (event.target.className.match(/\d+\.\d+|\d+\b|\d+(?=\w)/g) || [] ) | 226 var classnum = (event.target.className.match(/\d+\.\d+|\d+\b|\d+(?=\w)/g) || [] ).map(function (v) {return +v;}).shift(); |
| 213 .map(function (v) {return +v;}).shift(); | 227 var allclass = '.'+classname; |
| 214 var selectedOption = $('.'+classname+' option:selected').text(); | 228 var selectedOption = $(allclass).find('option:selected').text(); |
| 229 console.log("SEL "+ selectedOption); | |
| 215 | 230 |
| 216 // Change is on the filter box | 231 // Change is on the filter box |
| 217 if (classname.indexOf("filter-box") > -1) { | 232 if (classname.indexOf("filter-box") > -1) { |
| 218 if (selectedOption === "has relation") { | 233 if (selectedOption === "has relation") { |
| 219 // Remove any other boxes in the row | 234 // Remove any other boxes in the row |
| 220 $("#"+classnum+"filter-col2").remove(); | 235 $("#"+classnum+"filter-col2").remove(); |
| 221 $("#row"+classnum).append(constraint_html(classnum)); | 236 $("#row"+classnum).append(constraint_html(classnum)); |
| 222 // Generate inner relation list | 237 // Generate inner relation list |
| 223 genRelations(sourceType, ".constraint-box"+classnum); | 238 genRelations(sourceType, ".rel-constraint-box"+classnum); |
| 224 } | 239 } |
| 225 if (selectedOption === "attribute contains") { | 240 if (selectedOption === "attribute") { |
| 226 $("#"+classnum+"filter-col2").remove(); | 241 $("#"+classnum+"filter-col2").remove(); |
| 242 $("#row"+classnum).append(attr_constraint_html(classnum)); | |
| 243 genAttributes(sourceType, ".attr-constraint-box"+classnum); | |
| 244 //$("#row"+classnum).append(submit_html(classnum)); | |
| 227 $("#row"+classnum).append(submit_html(classnum)); | 245 $("#row"+classnum).append(submit_html(classnum)); |
| 228 //genAttributes(sourceType, ".constraint-box"+classnum); | 246 |
| 229 } | 247 } |
| 248 | |
| 249 // NOT IMPLEMENTED | |
| 250 /* | |
| 230 if (selectedOption === "return") { | 251 if (selectedOption === "return") { |
| 231 $("#"+classnum+"filter-col2").remove(); | 252 $("#"+classnum+"filter-col2").remove(); |
| 232 $("#row"+classnum).append(constraint_html(classnum)); | 253 $("#row"+classnum).append(constraint_html(classnum)); |
| 233 genAttributes(targetTypes, ".constraint-box"+classnum); | 254 genAttributes(targetTypes, ".constraint-box"+classnum); |
| 234 } | 255 } |
| 256 */ | |
| 235 } | 257 } |
| 236 | 258 |
| 237 // Change is on the relationship constraint box | 259 // Change is on the relationship constraint box |
| 238 if (classname.indexOf("constraint-box") > -1) { | 260 if (classname.indexOf("rel-constraint-box") > -1) { |
| 239 //$().remove(); | 261 //$().remove(); |
| 240 genResults(sourceType, selectedOption, "results-container"); | 262 genResults(sourceType, selectedOption, "results-container"); |
| 241 } | 263 } |
| 242 | 264 |
| 243 // TODO: if the select object is changed update the sourceType var that we are looking at | 265 // Change is on the attr constraint box |
| 266 if (classname.indexOf("attr-constraint-box") > -1) { | |
| 267 //$().remove(); | |
| 268 console.log("CHANGE ON ATTR"); | |
| 269 console.log("changing currentqueryattr to" + selectedOption); | |
| 270 currentQueryAttr = selectedOption; | |
| 271 console.log("currentQueryAttr is" + currentQueryAttr); | |
| 272 //genResults(sourceType, selectedOption, "results-container"); | |
| 273 } | |
| 274 | |
| 244 // Change is on subject scope | 275 // Change is on subject scope |
| 245 if (classname.indexOf("select-object") > -1) { | 276 if (classname.indexOf("select-object") > -1) { |
| 277 sourceType = selectedOption; | |
| 278 console.log("CHANGE ON SCOPE"); | |
| 279 genResults(sourceType, "New Source", "results-container"); | |
| 246 | 280 |
| 247 //ajax1(query, "results-container") | 281 //ajax1(query, "results-container") |
| 248 } | 282 } |
| 249 }); | 283 }); |
| 250 | 284 $("#filters").submit(function (event) { |
| 285 var inputId = $("input:text[name=attr-field]")[0].id; | |
| 286 var inputValue = $("input:text[name=attr-field]").val(); | |
| 287 // Alter results list | |
| 288 console.log("QUERY TYPE IS ATTRIBUTE NOW"); | |
| 289 currentQueryType = "attribute"; | |
| 290 console.log("SUBMITTED"); | |
| 291 genResults(sourceType, inputValue, "results-container") | |
| 292 | |
| 293 | |
| 294 }); | |
| 295 // For use in the onchange events above | |
| 296 function genRelations(sourceNodeType, constraintBox) { | |
| 297 console.log("GENERATE ALL RELATIONS"); | |
| 298 var query = "match (source:"+sourceNodeType+")-[rel]-target return distinct rel.type"; | |
| 299 console.log("QUERY TYPE IS RELATION NOW"); | |
| 300 currentQueryType = "relation"; | |
| 301 ajax1(query, constraintBox); | |
| 302 } | |
| 303 function genAttributes(sourceNodeType, constraintBox) { | |
| 304 console.log("GENERATE ALL ATTRIBUTES"); | |
| 305 var query = "match (n:"+sourceNodeType+") with keys(n) as collection unwind collection as attributes return distinct attributes"; | |
| 306 ajax1(query, constraintBox); | |
| 307 } | |
| 308 function genResults(sourceNodeType, selected, constraintBox) { | |
| 309 // TODO: Return first the list of current values of the display box | |
| 310 | |
| 311 if (selected === "New Source") { | |
| 312 console.log("NEW SOURCE - UPDATE RESULTS"); | |
| 313 var query = "match (source:"+sourceNodeType+") return source._n_label, source.type"; | |
| 314 } | |
| 315 else if (currentQueryType === "attribute") { | |
| 316 console.log("ATTR CHANGE - UPDATE RESULTS"); | |
| 317 console.log("before update currentQueryAttr is " + currentQueryAttr); | |
| 318 var qAttr = currentQueryAttr; | |
| 319 var query = "match (source:"+sourceNodeType+") where "+get_result_labels()+" AND source."+qAttr+"=~\"(?i).*"+selected+".*\" return distinct source._n_label, source.type limit 5"; | |
| 320 console.log(query); | |
| 321 } | |
| 322 else if (currentQueryType === "relation") { | |
| 323 var query = "match (source:" + sourceNodeType + ")-[rel:" + selected + "]->(target) return distinct target._n_label, target.type"; | |
| 324 console.log("REL CHANGE - UPDATE RESULTS"); | |
| 325 } | |
| 326 else { | |
| 327 console.log("GENRESULTS IMPROPERLY CALLED"); | |
| 328 return; | |
| 329 } | |
| 330 ajax1(query, constraintBox); | |
| 331 } | |
| 332 var currentQueryType; | |
| 333 var currentQueryAttr; | |
| 334 var resultLabelString = ""; | |
| 335 function get_result_labels() { | |
| 336 return resultLabelString; | |
| 337 } | |
| 338 function set_result_labels(currentResults) { | |
| 339 resultLabelString = "("; | |
| 340 for (var i = 0; i < currentResults.length; i++) { | |
| 341 if (i > 0) resultLabelString += " OR "; | |
| 342 resultLabelString += 'source._n_label=\"'+currentResults[i].text.substr(1)+'\"'; | |
| 343 } | |
| 344 resultLabelString += ")" | |
| 345 } | |
| 346 // to use contains | |
| 347 // TODO: start n = node(*) where n.Name =~ '.*SUBSTRING.*' return n.Name, n; | |
| 251 | 348 |
| 252 | 349 |
| 253 | 350 |
| 254 // Ajax request function | 351 // Ajax request function |
| 255 function ajax1(q, resBox) { | 352 function ajax1(q, resBox) { |
| 256 console.log(q); | |
| 257 $.ajaxSetup({ | 353 $.ajaxSetup({ |
| 258 headers: { | 354 headers: { |
| 259 "Authorization": 'Basic ' + window.btoa("neo4j"+":"+"neo5j") | 355 "Authorization": 'Basic ' + window.btoa("neo4j"+":"+"neo5j") |
| 260 } | 356 } |
| 261 }); | 357 }); |
| 299 dataGen(a1.data, resBox); | 395 dataGen(a1.data, resBox); |
| 300 } | 396 } |
| 301 // On success, generate new data | 397 // On success, generate new data |
| 302 // TODO: might want to just always return nodes and then deal with the queryData different for each type of return | 398 // TODO: might want to just always return nodes and then deal with the queryData different for each type of return |
| 303 function dataGen(dataArr, resBox) { | 399 function dataGen(dataArr, resBox) { |
| 304 console.log(dataArr); | |
| 305 var d = dataArr; | 400 var d = dataArr; |
| 306 targets = []; | 401 targets = []; |
| 307 | 402 |
| 308 // Consider implementing localStorage to avoid reloading every time | 403 // Consider implementing localStorage to avoid reloading every time |
| 309 var queryData = []; | 404 var queryData = []; |
| 316 queryData.sort(function(a,b){ | 411 queryData.sort(function(a,b){ |
| 317 var c = a.text.replace(/<|>/g, ''); | 412 var c = a.text.replace(/<|>/g, ''); |
| 318 var d = b.text.replace(/<|>/g, ''); | 413 var d = b.text.replace(/<|>/g, ''); |
| 319 return c.localeCompare(d); | 414 return c.localeCompare(d); |
| 320 }); | 415 }); |
| 321 console.log(queryData[0].text); | |
| 322 | 416 |
| 323 // Change the displayed results | 417 // Change the displayed results |
| 324 if (resBox === "results-container") { | 418 if (resBox === "results-container") { |
| 325 process_display_results(queryData); | 419 process_display_results(queryData); |
| 326 } | 420 } |
| 421 // Or fill any select boxes | |
| 327 else { | 422 else { |
| 328 $(resBox).select2({ | 423 $(resBox).select2({ |
| 329 data: queryData | 424 data: queryData |
| 330 }); | 425 }); |
| 331 } | 426 } |
| 332 } | 427 } |
| 333 function process_display_results(queryData) { | 428 function process_display_results(queryData) { |
| 334 var weights = []; | 429 var weights = []; |
| 335 var resultLength = queryData.length; | 430 var resultLength = queryData.length; |
| 336 targetTypes = []; | 431 targetTypes = []; |
| 337 | 432 targetObj = queryData; |
| 433 set_result_labels(queryData); | |
| 338 $('#results-container') | 434 $('#results-container') |
| 339 .find('option') | 435 .find('option') |
| 340 .remove() | 436 .remove() |
| 341 .end() | 437 .end() |
| 342 ; | 438 ; |
| 439 for (var i = 0; i < targets.length; i++) { | |
| 440 if (targetTypes.indexOf(targets[i]) == -1) { | |
| 441 targetTypes.push(targets[i]); | |
| 442 weights.push(1); | |
| 443 } | |
| 444 else { | |
| 445 weights[targetTypes.indexOf(targets[i])] += 1; | |
| 446 } | |
| 447 } | |
| 343 if (resultLength < listTolerance) { | 448 if (resultLength < listTolerance) { |
| 344 for (var i = 0; i < resultLength; i++) { | 449 for (var i = 0; i < resultLength; i++) { |
| 345 // TODO: put this jQuery call into its own function to be called if the else statement occurs | 450 // TODO: put this jQuery call into its own function to be called if the else statement occurs |
| 346 // TODO: but the user actually does want to see the entire huge list. | 451 // TODO: but the user actually does want to see the entire huge list. |
| 452 // This next bit removes duplicate labels if we want to use that for things like cities | |
| 453 // would this throw issues with other things?? | |
| 454 //$('#results-container option:contains('+queryData[i].text+')').each(function(){ | |
| 455 // $(this).remove(); | |
| 456 //}); | |
| 347 $('#results-container') | 457 $('#results-container') |
| 348 .append($("<option></option>") | 458 .append($("<option></option>") |
| 349 .attr("value", i) | 459 .attr("value", i) |
| 350 .text(queryData[i].text)); | 460 .text(queryData[i].text)); |
| 351 } | 461 } |
| 352 } | 462 } |
| 353 else { | 463 else { |
| 354 for (var i = 0; i < targets.length; i++) { | |
| 355 if (targetTypes.indexOf(targets[i]) == -1) { | |
| 356 targetTypes.push(targets[i]); | |
| 357 weights.push(1); | |
| 358 } | |
| 359 else { | |
| 360 weights[targetTypes.indexOf(targets[i])] += 1; | |
| 361 } | |
| 362 } | |
| 363 for (var i = 0; i < targetTypes.length; i++) { | 464 for (var i = 0; i < targetTypes.length; i++) { |
| 364 $('#results-container') | 465 $('#results-container') |
| 365 .append($("<option></option>") | 466 .append($("<option></option>") |
| 366 .text(targetTypes[i] + " [ " + weights[i] + " ]")); | 467 .text(targetTypes[i] + " [ " + weights[i] + " ]")); |
| 367 } | 468 } |
