From 3169d94d9b05410aa9b5380477bf10827c6afcde Mon Sep 17 00:00:00 2001 From: zsloan Date: Tue, 4 Aug 2015 21:42:47 +0000 Subject: Fixed additive effect for lodchart Made some more changes/improvements to various tables throughout the site --- .../wqflask/interval_mapping/interval_mapping.py | 46 +- .../wqflask/marker_regression/marker_regression.py | 40 +- wqflask/wqflask/static/new/javascript/lod_chart.js | 17 +- wqflask/wqflask/static/new/javascript/panelutil.js | 13 + .../new/javascript/show_trait_mapping_tools.coffee | 22 +- .../new/javascript/show_trait_mapping_tools.js | 482 +++--- .../DataTables/extensions/dataTables.colResize.js | 1669 +++++++++----------- wqflask/wqflask/templates/collections/list.html | 16 +- wqflask/wqflask/templates/collections/view.html | 15 +- wqflask/wqflask/templates/correlation_page.html | 16 +- wqflask/wqflask/templates/index_page.html | 15 +- wqflask/wqflask/templates/marker_regression.html | 60 +- wqflask/wqflask/templates/search_result_page.html | 21 +- wqflask/wqflask/templates/show_trait.html | 9 +- .../wqflask/templates/show_trait_edit_data.html | 10 +- .../templates/show_trait_mapping_tools.html | 4 +- 16 files changed, 1176 insertions(+), 1279 deletions(-) (limited to 'wqflask') diff --git a/wqflask/wqflask/interval_mapping/interval_mapping.py b/wqflask/wqflask/interval_mapping/interval_mapping.py index 672a9401..79cb1481 100755 --- a/wqflask/wqflask/interval_mapping/interval_mapping.py +++ b/wqflask/wqflask/interval_mapping/interval_mapping.py @@ -53,6 +53,9 @@ class IntervalMapping(object): self.set_options(start_vars) + self.score_type = "LRS" + self.cutoff = 3 + self.json_data = {} self.json_data['lodnames'] = ['lod.hk'] self.gen_reaper_results(tempdata) @@ -65,22 +68,17 @@ class IntervalMapping(object): chromosome_mb_lengths[key] = self.species.chromosomes.chromosomes[key].mb_length - #print("self.qtl_results:", self.qtl_results) - print("JSON DATA:", self.json_data) - #os.chdir(webqtlConfig.TMPDIR) json_filename = webqtlUtil.genRandStr(prefix="intmap_") json.dumps(self.json_data, webqtlConfig.TMPDIR + json_filename) self.js_data = dict( - result_score_type = "LRS", + result_score_type = self.score_type, manhattan_plot = self.manhattan_plot, - additive = self.additive, chromosomes = chromosome_mb_lengths, qtl_results = self.qtl_results, json_data = self.json_data - #lrs_lod = self.lrs_lod, ) def set_options(self, start_vars): @@ -158,7 +156,6 @@ class IntervalMapping(object): self.json_data['chr'] = [] self.json_data['pos'] = [] self.json_data['lod.hk'] = [] - self.json_data['additive'] = [] self.json_data['markernames'] = [] for qtl in reaper_results: reaper_locus = qtl.locus @@ -166,6 +163,7 @@ class IntervalMapping(object): self.json_data['lod.hk'].append(qtl.lrs) self.json_data['markernames'].append(reaper_locus.name) if self.additive: + self.json_data['additive'] = [] self.json_data['additive'].append(qtl.additive) locus = {"name":reaper_locus.name, "chr":reaper_locus.chr, "cM":reaper_locus.cM, "Mb":reaper_locus.Mb} qtl = {"lrs": qtl.lrs, "locus": locus, "additive": qtl.additive} @@ -206,8 +204,9 @@ class IntervalMapping(object): self.json_data['chr'] = [] self.json_data['pos'] = [] self.json_data['lod.hk'] = [] - self.json_data['additive'] = [] self.json_data['markernames'] = [] + if self.additive: + self.json_data['additive'] = [] #Need to convert the QTL objects that qtl reaper returns into a json serializable dictionary self.qtl_results = [] @@ -223,37 +222,6 @@ class IntervalMapping(object): qtl = {"lrs_value": qtl.lrs, "chr":reaper_locus.chr, "Mb":reaper_locus.Mb, "cM":reaper_locus.cM, "name":reaper_locus.name, "additive":qtl.additive} self.qtl_results.append(qtl) - - - def gen_qtl_results_2(self, tempdata): - """Generates qtl results for plotting interval map""" - - self.dataset.group.get_markers() - self.dataset.read_genotype_file() - - pheno_vector = np.array([val == "x" and np.nan or float(val) for val in self.vals]) - - #if self.dataset.group.species == "human": - # p_values, t_stats = self.gen_human_results(pheno_vector, tempdata) - #else: - genotype_data = [marker['genotypes'] for marker in self.dataset.group.markers.markers] - - no_val_samples = self.identify_empty_samples() - trimmed_genotype_data = self.trim_genotypes(genotype_data, no_val_samples) - - genotype_matrix = np.array(trimmed_genotype_data).T - - t_stats, p_values = lmm.run( - pheno_vector, - genotype_matrix, - restricted_max_likelihood=True, - refit=False, - temp_data=tempdata - ) - - self.dataset.group.markers.add_pvalues(p_values) - - self.qtl_results = self.dataset.group.markers.markers def identify_empty_samples(self): diff --git a/wqflask/wqflask/marker_regression/marker_regression.py b/wqflask/wqflask/marker_regression/marker_regression.py index c003f5e8..850dfc7f 100755 --- a/wqflask/wqflask/marker_regression/marker_regression.py +++ b/wqflask/wqflask/marker_regression/marker_regression.py @@ -79,9 +79,9 @@ class MarkerRegression(object): included_markers, p_values = gemma_mapping.run_gemma(self.dataset, self.samples, self.vals) self.dataset.group.get_specified_markers(markers = included_markers) self.dataset.group.markers.add_pvalues(p_values) - qtl_results = self.dataset.group.markers.markers + results = self.dataset.group.markers.markers elif self.mapping_method == "rqtl_plink": - qtl_results = self.run_rqtl_plink() + results = self.run_rqtl_plink() elif self.mapping_method == "rqtl_geno": if start_vars['num_perm'] == "": self.num_perm = 0 @@ -95,32 +95,32 @@ class MarkerRegression(object): if start_vars['pair_scan'] == "true": self.pair_scan = True - qtl_results = self.run_rqtl_geno() - print("qtl_results:", qtl_results) + results = self.run_rqtl_geno() + print("qtl_results:", results) elif self.mapping_method == "plink": - qtl_results = self.run_plink() - #print("qtl_results:", pf(qtl_results)) + results = self.run_plink() + #print("qtl_results:", pf(results)) elif self.mapping_method == "pylmm": print("RUNNING PYLMM") self.num_perm = start_vars['num_perm'] if self.num_perm != "": if int(self.num_perm) > 0: self.run_permutations(str(temp_uuid)) - qtl_results = self.gen_data(str(temp_uuid)) + results = self.gen_data(str(temp_uuid)) else: print("RUNNING NOTHING") if self.pair_scan == True: - self.filtered_markers = [] + self.qtl_results = [] highest_chr = 1 #This is needed in order to convert the highest chr to X/Y - for marker in qtl_results: + for marker in results: if marker['chr1'] > 0 or marker['chr1'] == "X" or marker['chr1'] == "X/Y": if marker['chr1'] > highest_chr or marker['chr1'] == "X" or marker['chr1'] == "X/Y": highest_chr = marker['chr1'] if 'lod_score' in marker: - self.filtered_markers.append(marker) + self.qtl_results.append(marker) - for qtl in enumerate(self.filtered_markers): + for qtl in enumerate(self.qtl_results): self.json_data['chr1'].append(str(qtl['chr1'])) self.json_data['chr2'].append(str(qtl['chr2'])) self.json_data['Mb'].append(qtl['Mb']) @@ -132,19 +132,20 @@ class MarkerRegression(object): data_set = self.dataset.name, maf = self.maf, manhattan_plot = self.manhattan_plot, - qtl_results = self.filtered_markers, + qtl_results = self.qtl_results, ) else: - self.lod_cutoff = 2 - self.filtered_markers = [] + self.score_type = "LRS" + self.cutoff = 2 + self.qtl_results = [] highest_chr = 1 #This is needed in order to convert the highest chr to X/Y - for marker in qtl_results: + for marker in results: if marker['chr'] > 0 or marker['chr'] == "X" or marker['chr'] == "X/Y": if marker['chr'] > highest_chr or marker['chr'] == "X" or marker['chr'] == "X/Y": highest_chr = marker['chr'] if 'lod_score' in marker: - self.filtered_markers.append(marker) + self.qtl_results.append(marker) self.json_data['chr'] = [] self.json_data['pos'] = [] @@ -155,8 +156,7 @@ class MarkerRegression(object): self.json_data['significant'] = self.significant #Need to convert the QTL objects that qtl reaper returns into a json serializable dictionary - self.qtl_results = [] - for index, qtl in enumerate(self.filtered_markers): + for index, qtl in enumerate(self.qtl_results): if index<40: print("lod score is:", qtl['lod_score']) if qtl['chr'] == highest_chr and highest_chr != "X" and highest_chr != "X/Y": @@ -179,14 +179,14 @@ class MarkerRegression(object): self.js_data = dict( - result_score_type = "LOD", + result_score_type = self.score_type, json_data = self.json_data, this_trait = self.this_trait.name, data_set = self.dataset.name, maf = self.maf, manhattan_plot = self.manhattan_plot, chromosomes = chromosome_mb_lengths, - qtl_results = self.filtered_markers, + qtl_results = self.qtl_results, ) diff --git a/wqflask/wqflask/static/new/javascript/lod_chart.js b/wqflask/wqflask/static/new/javascript/lod_chart.js index 631d8632..35b37070 100644 --- a/wqflask/wqflask/static/new/javascript/lod_chart.js +++ b/wqflask/wqflask/static/new/javascript/lod_chart.js @@ -20,7 +20,6 @@ lodchart = function() { }; titlepos = 20; manhattanPlot = false; - additive = false; ylim = null; additive_ylim = null; nyticks = 5; @@ -70,7 +69,8 @@ lodchart = function() { return results; })(); ylim = ylim != null ? ylim : [0, d3.max(data[lodvarname])]; - if (additive) { + + if ('additive' in data) { data['additive'] = (function() { var j, len, ref, results; ref = data['additive']; @@ -91,7 +91,7 @@ lodchart = function() { g.append("rect").attr("x", margin.left).attr("y", margin.top).attr("height", height).attr("width", width).attr("fill", darkrect).attr("stroke", "none"); yscale.domain(ylim).range([height + margin.top, margin.top + margin.inner]); yticks = yticks != null ? yticks : yscale.ticks(nyticks); - if (additive) { + if ('additive' in data) { additive_yscale.domain(additive_ylim).range([height + margin.top, margin.top + margin.inner + height / 2]); additive_yticks = additive_yticks != null ? additive_yticks : additive_yscale.ticks(nyticks); } @@ -147,7 +147,7 @@ lodchart = function() { return formatAxis(yticks)(d); }); yaxis.append("text").attr("class", "title").attr("y", margin.top + height / 2).attr("x", margin.left - axispos.ytitle).text(ylab).attr("transform", rotate_ylab ? "rotate(270," + (margin.left - axispos.ytitle) + "," + (margin.top + height / 2) + ")" : "").attr("text-anchor", "middle").attr("fill", "slateblue"); - if (additive) { + if ('additive' in data) { rotate_additive_ylab = rotate_additive_ylab != null ? rotate_additive_ylab : additive_ylab.length > 1; additive_yaxis = g.append("g").attr("class", "y axis"); additive_yaxis.selectAll("empty").data(additive_yticks).enter().append("line").attr("y1", function(d) { @@ -186,12 +186,12 @@ lodchart = function() { return yscale(data.lodByChr[chr][i][lodcolumn]); }); }; - if (additive) { + if ('additive' in data) { additivecurve = function(chr, lodcolumn) { return d3.svg.line().x(function(d) { return xscale[chr](d); }).y(function(d, i) { - return additive_yscale(data.additiveByChr[chr][i][lodcolumn]); + return additive_yscale(data.additiveByChr[chr][i]); }); }; } @@ -203,7 +203,7 @@ lodchart = function() { curves.append("path").datum(data.posByChr[chr[0]]).attr("d", lodcurve(chr[0], lodvarnum)).attr("stroke", lodlinecolor).attr("fill", "none").attr("stroke-width", linewidth).style("pointer-events", "none"); } } - if (additive) { + if ('additive' in data) { ref1 = data.chrnames; for (k = 0, len1 = ref1.length; k < len1; k++) { chr = ref1[k]; @@ -430,9 +430,6 @@ lodchart = function() { chart.yscale = function() { return yscale; }; - chart.additive = function() { - return additive; - }; chart.additive_yscale = function() { return additive_yscale; }; diff --git a/wqflask/wqflask/static/new/javascript/panelutil.js b/wqflask/wqflask/static/new/javascript/panelutil.js index 7c14f4de..113512b4 100644 --- a/wqflask/wqflask/static/new/javascript/panelutil.js +++ b/wqflask/wqflask/static/new/javascript/panelutil.js @@ -47,12 +47,19 @@ reorgLodData = function(data, lodvarname) { } data.posByChr = {}; data.lodByChr = {}; + if ('additive' in data){ + data.additiveByChr = {}; + } _ref = data.chrnames; for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { chr = _ref[i]; data.posByChr[chr[0]] = []; data.lodByChr[chr[0]] = []; + if ('additive' in data){ + data.additiveByChr[chr[0]] = []; + } _ref1 = data.pos; + for (j = _j = 0, _len1 = _ref1.length; _j < _len1; j = ++_j) { pos = _ref1[j]; if (data.chr[j].toString() === chr[0]) { @@ -71,6 +78,12 @@ reorgLodData = function(data, lodvarname) { return _results; })(); data.lodByChr[chr[0]].push(lodval); + + if ('additive' in data){ + addval = data['additive'][j] + data.additiveByChr[chr[0]].push(addval); + } + } } } diff --git a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee index 16ca1886..d14fb98c 100755 --- a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee +++ b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.coffee @@ -112,6 +112,11 @@ open_mapping_results = (data) -> form.submit() ) +outlier_text = "One or more outliers exist in this data set. Please review values before mapping. \ + Including outliers when mapping may lead to misleading results. \ + We recommend winsorising the outliers \ + or simply deleting them." + showalert = (message,alerttype) -> $('#alert_placeholder').append('
×'+message+'
') @@ -126,6 +131,11 @@ $('input[name=display_all]').change(() => $('#suggestive').hide() ) +$("#pylmm_mapping_compute").on("mouseover", => + if ( $(".outlier").length and $(".outlier-alert").length < 1 ) + showalert(outlier_text, "alert-success outlier-alert") +) + $("#pylmm_compute").on("click", => $("#progress_bar_container").modal() url = "/marker_regression" @@ -140,8 +150,7 @@ $("#pylmm_compute").on("click", => # block_outliers() do_ajax_post(url, form_data) ) - - + $("#rqtl_geno_compute").on("click", => $("#progress_bar_container").modal() @@ -187,11 +196,12 @@ $("#gemma_compute").on("click", => do_ajax_post(url, form_data) ) +$("#interval_mapping_compute").on("mouseover", => + if ( $(".outlier").length and $(".outlier-alert").length < 1 ) + showalert(outlier_text, "alert-success outlier-alert") +) + $("#interval_mapping_compute").on("click", => - showalert("One or more outliers exist in this data set. Please review values before mapping. \ - Including outliers when mapping may lead to misleading results. \ - We recommend winsorising the outliers \ - or simply deleting them.", "alert-success") console.log("In interval mapping") $("#progress_bar_container").modal() url = "/interval_mapping" diff --git a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js index d6f4ba89..3be40a57 100755 --- a/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js +++ b/wqflask/wqflask/static/new/javascript/show_trait_mapping_tools.js @@ -1,249 +1,269 @@ -// Generated by CoffeeScript 1.9.2 -var block_outliers, composite_mapping_fields, do_ajax_post, get_progress, mapping_method_fields, open_mapping_results, showalert, submit_special, toggle_enable_disable, update_time_remaining; - -submit_special = function() { - var url; - console.log("In submit_special"); - console.log("this is:", this); - console.log("$(this) is:", $(this)); - url = $(this).data("url"); - console.log("url is:", url); - $("#trait_data_form").attr("action", url); - return $("#trait_data_form").submit(); -}; - -update_time_remaining = function(percent_complete) { - var minutes_remaining, now, period, total_seconds_remaining; - now = new Date(); - period = now.getTime() - root.start_time; - console.log("period is:", period); - if (period > 8000) { - total_seconds_remaining = (period / percent_complete * (100 - percent_complete)) / 1000; - minutes_remaining = Math.round(total_seconds_remaining / 60); - if (minutes_remaining < 3) { - return $('#time_remaining').text(Math.round(total_seconds_remaining) + " seconds remaining"); - } else { - return $('#time_remaining').text(minutes_remaining + " minutes remaining"); +// Generated by CoffeeScript 1.8.0 +(function() { + var block_outliers, composite_mapping_fields, do_ajax_post, get_progress, mapping_method_fields, open_mapping_results, outlier_text, showalert, submit_special, toggle_enable_disable, update_time_remaining; + + submit_special = function() { + var url; + console.log("In submit_special"); + console.log("this is:", this); + console.log("$(this) is:", $(this)); + url = $(this).data("url"); + console.log("url is:", url); + $("#trait_data_form").attr("action", url); + return $("#trait_data_form").submit(); + }; + + update_time_remaining = function(percent_complete) { + var minutes_remaining, now, period, total_seconds_remaining; + now = new Date(); + period = now.getTime() - root.start_time; + console.log("period is:", period); + if (period > 8000) { + total_seconds_remaining = (period / percent_complete * (100 - percent_complete)) / 1000; + minutes_remaining = Math.round(total_seconds_remaining / 60); + if (minutes_remaining < 3) { + return $('#time_remaining').text(Math.round(total_seconds_remaining) + " seconds remaining"); + } else { + return $('#time_remaining').text(minutes_remaining + " minutes remaining"); + } } - } -}; - -get_progress = function() { - var params, params_str, temp_uuid, url; - console.log("temp_uuid:", $("#temp_uuid").val()); - temp_uuid = $("#temp_uuid").val(); - params = { - key: temp_uuid }; - params_str = $.param(params); - url = "/get_temp_data?" + params_str; - console.log("url:", url); - $.ajax({ - type: "GET", - url: url, - success: (function(_this) { - return function(progress_data) { - var percent_complete; - percent_complete = progress_data['percent_complete']; - console.log("in get_progress data:", progress_data); - $('#marker_regression_progress').css("width", percent_complete + "%"); - if (root.start_time) { - if (!isNaN(percent_complete)) { - return update_time_remaining(percent_complete); - } - } else { - return root.start_time = new Date().getTime(); - } - }; - })(this) - }); - return false; -}; -block_outliers = function() { - return $('.outlier').each((function(_this) { - return function(_index, element) { - return $(element).find('.trait_value_input').val('x'); + get_progress = function() { + var params, params_str, temp_uuid, url; + console.log("temp_uuid:", $("#temp_uuid").val()); + temp_uuid = $("#temp_uuid").val(); + params = { + key: temp_uuid }; - })(this)); -}; - -do_ajax_post = function(url, form_data) { - $.ajax({ - type: "POST", - url: url, - data: form_data, - error: (function(_this) { - return function(xhr, ajaxOptions, thrownError) { - alert("Sorry, an error occurred"); - console.log(xhr); - clearInterval(_this.my_timer); - $('#progress_bar_container').modal('hide'); - $('#static_progress_bar_container').modal('hide'); - return $("body").html("We got an error."); - }; - })(this), - success: (function(_this) { - return function(data) { - clearInterval(_this.my_timer); - $('#progress_bar_container').modal('hide'); - $('#static_progress_bar_container').modal('hide'); - return open_mapping_results(data); - }; - })(this) - }); - console.log("settingInterval"); - this.my_timer = setInterval(get_progress, 1000); - return false; -}; - -open_mapping_results = function(data) { - return $.colorbox({ - html: data, - href: "#mapping_results_holder", - height: "90%", - width: "90%", - onComplete: (function(_this) { - return function() { - var filename, getSvgXml; - root.create_lod_chart(); - filename = "lod_chart_" + js_data.this_trait; - getSvgXml = function() { - var svg; - svg = $("#topchart").find("svg")[0]; - return (new XMLSerializer).serializeToString(svg); + params_str = $.param(params); + url = "/get_temp_data?" + params_str; + console.log("url:", url); + $.ajax({ + type: "GET", + url: url, + success: (function(_this) { + return function(progress_data) { + var percent_complete; + percent_complete = progress_data['percent_complete']; + console.log("in get_progress data:", progress_data); + $('#marker_regression_progress').css("width", percent_complete + "%"); + if (root.start_time) { + if (!isNaN(percent_complete)) { + return update_time_remaining(percent_complete); + } + } else { + return root.start_time = new Date().getTime(); + } }; - $("#exportform > #export").click(function() { - var form, svg_xml; - svg_xml = getSvgXml(); - form = $("#exportform"); - form.find("#data").val(svg_xml); - form.find("#filename").val(filename); - return form.submit(); - }); - return $("#exportpdfform > #export_pdf").click(function() { - var form, svg_xml; - svg_xml = getSvgXml(); - form = $("#exportpdfform"); - form.find("#data").val(svg_xml); - form.find("#filename").val(filename); - return form.submit(); - }); - }; - })(this) - }); -}; - -showalert = function(message, alerttype) { - return $('#alert_placeholder').append('
�' + message + '
'); -}; - -$('#suggestive').hide(); - -$('input[name=display_all]').change((function(_this) { - return function() { - console.log("check"); - if ($('input[name=display_all]:checked').val() === "False") { - return $('#suggestive').show(); - } else { - return $('#suggestive').hide(); - } + })(this) + }); + return false; }; -})(this)); - -$("#pylmm_compute").on("click", (function(_this) { - return function() { - var form_data, url; - $("#progress_bar_container").modal(); - url = "/marker_regression"; - $('input[name=method]').val("pylmm"); - $('input[name=num_perm]').val($('input[name=num_perm_pylmm]').val()); - $('input[name=manhattan_plot]').val($('input[name=manhattan_plot_pylmm]:checked').val()); - form_data = $('#trait_data_form').serialize(); - console.log("form_data is:", form_data); - return do_ajax_post(url, form_data); + + block_outliers = function() { + return $('.outlier').each((function(_this) { + return function(_index, element) { + return $(element).find('.trait_value_input').val('x'); + }; + })(this)); }; -})(this)); - -$("#rqtl_geno_compute").on("click", (function(_this) { - return function() { - var form_data, url; - $("#progress_bar_container").modal(); - url = "/marker_regression"; - $('input[name=method]').val("rqtl_geno"); - $('input[name=num_perm]').val($('input[name=num_perm_rqtl_geno]').val()); - $('input[name=manhattan_plot]').val($('input[name=manhattan_plot_rqtl]:checked').val()); - $('input[name=control_marker]').val($('input[name=control_rqtl_geno]').val()); - form_data = $('#trait_data_form').serialize(); - console.log("form_data is:", form_data); - return do_ajax_post(url, form_data); + + do_ajax_post = function(url, form_data) { + $.ajax({ + type: "POST", + url: url, + data: form_data, + error: (function(_this) { + return function(xhr, ajaxOptions, thrownError) { + alert("Sorry, an error occurred"); + console.log(xhr); + clearInterval(_this.my_timer); + $('#progress_bar_container').modal('hide'); + $('#static_progress_bar_container').modal('hide'); + return $("body").html("We got an error."); + }; + })(this), + success: (function(_this) { + return function(data) { + clearInterval(_this.my_timer); + $('#progress_bar_container').modal('hide'); + $('#static_progress_bar_container').modal('hide'); + return open_mapping_results(data); + }; + })(this) + }); + console.log("settingInterval"); + this.my_timer = setInterval(get_progress, 1000); + return false; }; -})(this)); - -$("#plink_compute").on("click", (function(_this) { - return function() { - var form_data, url; - $("#static_progress_bar_container").modal(); - url = "/marker_regression"; - $('input[name=method]').val("plink"); - $('input[name=maf]').val($('input[name=maf_plink]').val()); - form_data = $('#trait_data_form').serialize(); - console.log("form_data is:", form_data); - return do_ajax_post(url, form_data); + + open_mapping_results = function(data) { + return $.colorbox({ + html: data, + href: "#mapping_results_holder", + height: "90%", + width: "90%", + onComplete: (function(_this) { + return function() { + var filename, getSvgXml; + root.create_lod_chart(); + filename = "lod_chart_" + js_data.this_trait; + getSvgXml = function() { + var svg; + svg = $("#topchart").find("svg")[0]; + return (new XMLSerializer).serializeToString(svg); + }; + $("#exportform > #export").click(function() { + var form, svg_xml; + svg_xml = getSvgXml(); + form = $("#exportform"); + form.find("#data").val(svg_xml); + form.find("#filename").val(filename); + return form.submit(); + }); + return $("#exportpdfform > #export_pdf").click(function() { + var form, svg_xml; + svg_xml = getSvgXml(); + form = $("#exportpdfform"); + form.find("#data").val(svg_xml); + form.find("#filename").val(filename); + return form.submit(); + }); + }; + })(this) + }); }; -})(this)); - -$("#gemma_compute").on("click", (function(_this) { - return function() { - var form_data, url; - console.log("RUNNING GEMMA"); - $("#static_progress_bar_container").modal(); - url = "/marker_regression"; - $('input[name=method]').val("gemma"); - $('input[name=maf]').val($('input[name=maf_gemma]').val()); - form_data = $('#trait_data_form').serialize(); - console.log("form_data is:", form_data); - return do_ajax_post(url, form_data); + + outlier_text = "One or more outliers exist in this data set. Please review values before mapping. Including outliers when mapping may lead to misleading results. We recommend winsorising the outliers or simply deleting them."; + + showalert = function(message, alerttype) { + return $('#alert_placeholder').append('
�' + message + '
'); }; -})(this)); - -$("#interval_mapping_compute").on("click", (function(_this) { - return function() { - var form_data, url; - showalert("One or more outliers exist in this data set. Please review values before mapping. Including outliers when mapping may lead to misleading results. We recommend winsorising the outliers or simply deleting them.", "alert-success"); - console.log("In interval mapping"); - $("#progress_bar_container").modal(); - url = "/interval_mapping"; - $('input[name=method]').val("reaper"); - $('input[name=manhattan_plot]').val($('input[name=manhattan_plot_reaper]:checked').val()); - $('input[name=mapping_display_all]').val($('input[name=display_all_reaper]')); - $('input[name=suggestive]').val($('input[name=suggestive_reaper]')); - form_data = $('#trait_data_form').serialize(); - console.log("form_data is:", form_data); - return do_ajax_post(url, form_data); + + $('#suggestive').hide(); + + $('input[name=display_all]').change((function(_this) { + return function() { + console.log("check"); + if ($('input[name=display_all]:checked').val() === "False") { + return $('#suggestive').show(); + } else { + return $('#suggestive').hide(); + } + }; + })(this)); + + $("#pylmm_mapping_compute").on("mouseover", (function(_this) { + return function() { + if ($(".outlier").length && $(".outlier-alert").length < 1) { + return showalert(outlier_text, "alert-success outlier-alert"); + } + }; + })(this)); + + $("#pylmm_compute").on("click", (function(_this) { + return function() { + var form_data, url; + $("#progress_bar_container").modal(); + url = "/marker_regression"; + $('input[name=method]').val("pylmm"); + $('input[name=num_perm]').val($('input[name=num_perm_pylmm]').val()); + $('input[name=manhattan_plot]').val($('input[name=manhattan_plot_pylmm]:checked').val()); + form_data = $('#trait_data_form').serialize(); + console.log("form_data is:", form_data); + return do_ajax_post(url, form_data); + }; + })(this)); + + $("#rqtl_geno_compute").on("click", (function(_this) { + return function() { + var form_data, url; + $("#progress_bar_container").modal(); + url = "/marker_regression"; + $('input[name=method]').val("rqtl_geno"); + $('input[name=num_perm]').val($('input[name=num_perm_rqtl_geno]').val()); + $('input[name=manhattan_plot]').val($('input[name=manhattan_plot_rqtl]:checked').val()); + $('input[name=control_marker]').val($('input[name=control_rqtl_geno]').val()); + form_data = $('#trait_data_form').serialize(); + console.log("form_data is:", form_data); + return do_ajax_post(url, form_data); + }; + })(this)); + + $("#plink_compute").on("click", (function(_this) { + return function() { + var form_data, url; + $("#static_progress_bar_container").modal(); + url = "/marker_regression"; + $('input[name=method]').val("plink"); + $('input[name=maf]').val($('input[name=maf_plink]').val()); + form_data = $('#trait_data_form').serialize(); + console.log("form_data is:", form_data); + return do_ajax_post(url, form_data); + }; + })(this)); + + $("#gemma_compute").on("click", (function(_this) { + return function() { + var form_data, url; + console.log("RUNNING GEMMA"); + $("#static_progress_bar_container").modal(); + url = "/marker_regression"; + $('input[name=method]').val("gemma"); + $('input[name=maf]').val($('input[name=maf_gemma]').val()); + form_data = $('#trait_data_form').serialize(); + console.log("form_data is:", form_data); + return do_ajax_post(url, form_data); + }; + })(this)); + + $("#interval_mapping_compute").on("mouseover", (function(_this) { + return function() { + if ($(".outlier").length && $(".outlier-alert").length < 1) { + return showalert(outlier_text, "alert-success outlier-alert"); + } + }; + })(this)); + + $("#interval_mapping_compute").on("click", (function(_this) { + return function() { + var form_data, url; + console.log("In interval mapping"); + $("#progress_bar_container").modal(); + url = "/interval_mapping"; + $('input[name=method]').val("reaper"); + $('input[name=manhattan_plot]').val($('input[name=manhattan_plot_reaper]:checked').val()); + $('input[name=mapping_display_all]').val($('input[name=display_all_reaper]')); + $('input[name=suggestive]').val($('input[name=suggestive_reaper]')); + form_data = $('#trait_data_form').serialize(); + console.log("form_data is:", form_data); + return do_ajax_post(url, form_data); + }; + })(this)); + + composite_mapping_fields = function() { + return $(".composite_fields").toggle(); }; -})(this)); -composite_mapping_fields = function() { - return $(".composite_fields").toggle(); -}; + mapping_method_fields = function() { + return $(".mapping_method_fields").toggle(); + }; -mapping_method_fields = function() { - return $(".mapping_method_fields").toggle(); -}; + $("#use_composite_choice").change(composite_mapping_fields); -$("#use_composite_choice").change(composite_mapping_fields); + $("#mapping_method_choice").change(mapping_method_fields); -$("#mapping_method_choice").change(mapping_method_fields); + toggle_enable_disable = function(elem) { + return $(elem).prop("disabled", !$(elem).prop("disabled")); + }; -toggle_enable_disable = function(elem) { - return $(elem).prop("disabled", !$(elem).prop("disabled")); -}; + $("#choose_closet_control").change(function() { + return toggle_enable_disable("#control_locus"); + }); -$("#choose_closet_control").change(function() { - return toggle_enable_disable("#control_locus"); -}); + $("#display_all_lrs").change(function() { + return toggle_enable_disable("#suggestive_lrs"); + }); -$("#display_all_lrs").change(function() { - return toggle_enable_disable("#suggestive_lrs"); -}); +}).call(this); diff --git a/wqflask/wqflask/static/new/packages/DataTables/extensions/dataTables.colResize.js b/wqflask/wqflask/static/new/packages/DataTables/extensions/dataTables.colResize.js index 6ef9907a..2712750a 100644 --- a/wqflask/wqflask/static/new/packages/DataTables/extensions/dataTables.colResize.js +++ b/wqflask/wqflask/static/new/packages/DataTables/extensions/dataTables.colResize.js @@ -1,943 +1,846 @@ -var dt; -(function (dt) { - var ColResize = (function () { - function ColResize($, api, settings) { - this.$ = $; - this.tableSize = -1; - this.initialized = false; - this.dt = {}; - this.dom = { - fixedLayout: false, - fixedHeader: null, - winResizeTimer: null, - mouse: { - startX: -1, - startWidth: null - }, - table: { - prevWidth: null - }, - origState: true, - resize: false, - scrollHead: null, - scrollHeadTable: null, - scrollFoot: null, - scrollFootTable: null, - scrollFootInner: null, - scrollBody: null, - scrollBodyTable: null, - scrollX: false, - scrollY: false - }; - this.settings = this.$.extend(true, {}, dt.ColResize.defaultSettings, settings); - this.dt.settings = api.settings()[0]; - this.dt.api = api; - this.dt.settings.colResize = this; - this.registerCallbacks(); - } - ColResize.prototype.initialize = function () { - var _this = this; - this.$.each(this.dt.settings.aoColumns, function (i, col) { - return _this.setupColumn(col); - }); - - //Initialize fixedHeader if specified - if (this.settings.fixedHeader) - this.setupFixedHeader(); - - //Save scroll head and body if found - this.dom.scrollHead = this.$('div.' + this.dt.settings.oClasses.sScrollHead, this.dt.settings.nTableWrapper); - this.dom.scrollHeadInner = this.$('div.' + this.dt.settings.oClasses.sScrollHeadInner, this.dom.scrollHead); - this.dom.scrollHeadTable = this.$('div.' + this.dt.settings.oClasses.sScrollHeadInner + ' > table', this.dom.scrollHead); - - this.dom.scrollFoot = this.$('div.' + this.dt.settings.oClasses.sScrollFoot, this.dt.settings.nTableWrapper); - this.dom.scrollFootInner = this.$('div.' + this.dt.settings.oClasses.sScrollFootInner, this.dom.scrollFoot); - this.dom.scrollFootTable = this.$('div.' + this.dt.settings.oClasses.sScrollFootInner + ' > table', this.dom.scrollFoot); - - this.dom.scrollBody = this.$('div.' + this.dt.settings.oClasses.sScrollBody, this.dt.settings.nTableWrapper); - this.dom.scrollBodyTable = this.$('> table', this.dom.scrollBody); - this.dt.api.on('draw.dt', this.onDraw.bind(this)); - if (this.dom.scrollFootTable) { - this.dt.api.on('colPinFcDraw.dt', function (e, colPin, data) { - if (data.leftClone.header) - _this.$('tfoot', data.leftClone.header).remove(); - if (data.leftClone.footer) - _this.$('thead', data.leftClone.footer).remove(); - if (data.rightClone.header) - _this.$('tfoot', data.rightClone.header).remove(); - if (data.rightClone.footer) - _this.$('thead', data.rightClone.footer).remove(); - }); - } - - this.dom.scrollX = this.dt.settings.oInit.sScrollX === undefined ? false : true; - this.dom.scrollY = this.dt.settings.oInit.sScrollY === undefined ? false : true; - - //SaveTableWidth - this.dt.settings.sTableWidthOrig = this.$(this.dt.settings.nTable).width(); - this.updateTableSize(); - - this.dt.settings.oFeatures.bAutoWidthOrig = this.dt.settings.oFeatures.bAutoWidth; - this.dt.settings.oFeatures.bAutoWidth = false; - - if (this.dt.settings.oInit.bStateSave && this.dt.settings.oLoadedState) { - this.loadState(this.dt.settings.oLoadedState); +/*! ColResize 0.0.10 + */ + +/** + * @summary ColResize + * @description Provide the ability to resize columns in a DataTable + * @version 0.0.10 + * @file dataTables.colResize.js + * @author Silvacom Ltd. + * + * For details please refer to: http://www.datatables.net + * + * Special thank to everyone who has contributed to this plug in + * - dykstrad + * - tdillan (for 0.0.3 and 0.0.5 bug fixes) + * - kylealonius (for 0.0.8 bug fix) + * - the86freak (for 0.0.9 bug fix) + */ + +(function (window, document, undefined) { + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables plug-in API functions test + * + * This are required by ColResize in order to perform the tasks required, and also keep this + * code portable, to be used for other column resize projects with DataTables, if needed. + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + var factory = function ($, DataTable) { + "use strict"; + + /** + * Plug-in for DataTables which will resize the columns depending on the handle clicked + * @method $.fn.dataTableExt.oApi.fnColResize + * @param object oSettings DataTables settings object - automatically added by DataTables! + * @param int iCol Take the column to be resized + * @returns void + */ + $.fn.dataTableExt.oApi.fnColResize = function (oSettings, iCol) { + var v110 = $.fn.dataTable.Api ? true : false; + + /* + * Update DataTables' event handlers + */ + + /* Fire an event so other plug-ins can update */ + $(oSettings.oInstance).trigger('column-resize', [ oSettings, { + "iCol": iCol + } ]); + }; + + /** + * ColResize provides column resize control for DataTables + * @class ColResize + * @constructor + * @param {object} dt DataTables settings object + * @param {object} opts ColResize options + */ + var ColResize = function (dt, opts) { + var oDTSettings; + + if ($.fn.dataTable.Api) { + oDTSettings = new $.fn.dataTable.Api(dt).settings()[0]; + } + // 1.9 compatibility + else if (dt.fnSettings) { + // DataTables object, convert to the settings object + oDTSettings = dt.fnSettings(); + } + else if (typeof dt === 'string') { + // jQuery selector + if ($.fn.dataTable.fnIsDataTable($(dt)[0])) { + oDTSettings = $(dt).eq(0).dataTable().fnSettings(); + } } - - this.onDraw(); - this.dom.table.preWidth = parseFloat(this.dom.scrollBodyTable.css('width')); - - if (!this.dom.scrollX && this.dom.scrollY && this.settings.fixedLayout && this.dt.settings._reszEvt) { - //We have to manually resize columns on window resize - var eventName = 'resize.DT-' + this.dt.settings.sInstance; - this.$(window).off(eventName); - this.$(window).on(eventName, function () { - _this.proportionallyColumnSizing(); - //api._fnAdjustColumnSizing(this.dt.settings); - }); + else if (dt.nodeName && dt.nodeName.toLowerCase() === 'table') { + // Table node + if ($.fn.dataTable.fnIsDataTable(dt.nodeName)) { + oDTSettings = $(dt.nodeName).dataTable().fnSettings(); + } } - - if (this.dom.scrollX || this.dom.scrollY) { - this.dt.api.on('column-sizing.dt', this.fixFootAndHeadTables.bind(this)); - this.dt.api.on('column-visibility.dt', this.fixFootAndHeadTables.bind(this)); + else if (dt instanceof jQuery) { + // jQuery object + if ($.fn.dataTable.fnIsDataTable(dt[0])) { + oDTSettings = dt.eq(0).dataTable().fnSettings(); + } } + else { + // DataTables settings object + oDTSettings = dt; + } + + // Convert from camelCase to Hungarian, just as DataTables does + if ($.fn.dataTable.camelToHungarian) { + $.fn.dataTable.camelToHungarian(ColResize.defaults, opts || {}); + } + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Public class variables + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * @namespace Settings object which contains customizable information for ColResize instance + */ + this.s = { + /** + * DataTables settings object + * @property dt + * @type Object + * @default null + */ + "dt": null, + + /** + * Initialisation object used for this instance + * @property init + * @type object + * @default {} + */ + "init": $.extend(true, {}, ColResize.defaults, opts), + + /** + * @namespace Information used for the mouse drag + */ + "mouse": { + "startX": -1, + "startY": -1, + "targetIndex": -1, + "targetColumn": -1, + "neighbourIndex": -1, + "neighbourColumn": -1 + }, - this.initialized = true; - this.dt.settings.oApi._fnCallbackFire(this.dt.settings, 'colResizeInitCompleted', 'colResizeInitCompleted', [this]); - }; - - ColResize.prototype.setupColumn = function (col) { - var _this = this; - var $th = this.$(col.nTh); - if (col.resizable === false) - return; - - // listen to mousemove event for resize - $th.on('mousemove.ColResize', function (e) { - if (_this.dom.resize || col.resizable === false) - return; - - /* Store information about the mouse position */ - var $thTarget = e.target.nodeName.toUpperCase() == 'TH' ? _this.$(e.target) : _this.$(e.target).closest('TH'); - var offset = $thTarget.offset(); - var nLength = $thTarget.innerWidth(); - - /* are we on the col border (if so, resize col) */ - if (Math.abs(e.pageX - Math.round(offset.left + nLength)) <= 5) { - $thTarget.css({ 'cursor': 'col-resize' }); - } else - $thTarget.css({ 'cursor': 'pointer' }); - }); - - //Save the original width - col._ColResize_sWidthOrig = col.sWidthOrig; - col.initWidth = $th.width(); - col.minWidthOrig = col.minWidth; - - $th.on('dblclick.ColResize', function (e) { - _this.onDblClick(e, $th, col); - }); - - $th.off('mousedown.ColReorder'); - - // listen to mousedown event - $th.on('mousedown.ColResize', function (e) { - return _this.onMouseDown(e, col); - }); - }; - - ColResize.prototype.setupFixedHeader = function () { - var fhSettings = this.settings.fixedHeader === true ? undefined : this.settings.fixedHeader; - - //If left or right option was set to true disable resizing for the first or last column - if (this.$.isPlainObject(fhSettings)) { - var columns = this.dt.settings.aoColumns; - if (fhSettings.left === true) - columns[0].resizable = false; - if (fhSettings.right === true) - columns[columns.length - 1].resizable = false; - } + /** + * Status variable keeping track of mouse down status + * @property isMousedown + * @type boolean + * @default false + */ + "isMousedown": false + }; - this.dom.fixedHeader = new this.$.fn.dataTable.FixedHeader(this.dt.api, fhSettings); - var origUpdateClones = this.dom.fixedHeader._fnUpdateClones; - var that = this; - //FixeHeader doesn't have any callback after updating the clones so we have to wrap the orig function - this.dom.fixedHeader._fnUpdateClones = function () { - origUpdateClones.apply(this, arguments); - that.memorizeFixedHeaderNodes(); + /** + * @namespace Common and useful DOM elements for the class instance + */ + this.dom = { + /** + * Resizing element (the one the mouse is resizing) + * @property resize + * @type element + * @default null + */ + "resizeCol": null, + + /** + * Resizing element neighbour (the column next to the one the mouse is resizing) + * This is for fixed table resizing. + * @property resize + * @type element + * @default null + */ + "resizeColNeighbour": null, + + /** + * Array of events to be restored, used for overriding existing events from other plugins for a time. + * @property restoreEvents + * @type array + * @default [] + */ + "restoreEvents": [] }; - //As we missed the first call of _fnUpdateClones we have to call memorizeFixedHeaderNodes function manually - this.memorizeFixedHeaderNodes(); - }; - ColResize.prototype.memorizeFixedHeaderNodes = function () { - var _this = this; - var fhSettings = this.dom.fixedHeader.fnGetSettings(); - var fhCache = fhSettings.aoCache; - var i, col; - for (i = 0; i < fhCache.length; i++) { - var type = fhCache[i].sType; - var propName; - var selector; - switch (type) { - case 'fixedHeader': - propName = 'fhTh'; - selector = 'thead>tr>th'; - this.dt.settings.fhTHead = fhCache[i].nNode; - break; - case 'fixedFooter': - propName = 'fhTf'; - selector = 'thead>tr>th'; - - //prepend a cloned thead to the floating footer table so that resizing will work correctly - var tfoot = this.$(fhCache[i].nNode); - var thead = this.$(this.dt.settings.nTHead).clone().css({ height: 0, visibility: 'hidden' }); - this.$('tr', thead).css('height', 0); - this.$('tr>th', thead).css({ - 'height': 0, - 'padding-bottom': 0, - 'padding-top': 0, - 'border-bottom-width': 0, - 'border-top-width': 0, - 'line-height': 0 - }); - tfoot.prepend(thead); - this.$('tfoot>tr>th', tfoot).css('width', ''); - this.dt.settings.fhTFoot = fhCache[i].nNode; - break; - default: - continue; + /* Constructor logic */ + this.s.dt = oDTSettings.oInstance.fnSettings(); + this.s.dt._colResize = this; + this._fnConstruct(); + + /* Add destroy callback */ + oDTSettings.oApi._fnCallbackReg(oDTSettings, 'aoDestroyCallback', $.proxy(this._fnDestroy, this), 'ColResize'); + + return this; + }; + + + ColResize.prototype = { + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Public methods + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * Reset the column widths to the original widths that was detected on + * start up. + * @return {this} Returns `this` for chaining. + * + * @example + * // DataTables initialisation with ColResize + * var table = $('#example').dataTable( { + * "sDom": 'Zlfrtip' + * } ); + * + * // Add click event to a button to reset the ordering + * $('#resetOrdering').click( function (e) { + * e.preventDefault(); + * $.fn.dataTable.ColResize( table ).fnReset(); + * } ); + */ + "fnReset": function () { + var a = []; + for (var i = 0, iLen = this.s.dt.aoColumns.length; i < iLen; i++) { + this.s.dt.aoColumns[i].width = this.s.dt.aoColumns[i]._ColResize_iOrigWidth; } - this.$(selector, fhCache[i].nNode).each(function (j, th) { - col = _this.getVisibleColumn(j); - col[propName] = th; - }); - } - }; + this.s.dt.adjust().draw(); - //zero based index - ColResize.prototype.getVisibleColumn = function (idx) { - var columns = this.dt.settings.aoColumns; - var currVisColIdx = -1; - for (var i = 0; i < columns.length; i++) { - if (!columns[i].bVisible) - continue; - currVisColIdx++; - if (currVisColIdx == idx) - return columns[i]; - } - return null; - }; - - ColResize.prototype.updateTableSize = function () { - if (this.dom.scrollX && this.dom.scrollHeadTable.length) - this.tableSize = this.dom.scrollHeadTable.width(); - else - this.tableSize = -1; - }; + return this; + }, - ColResize.prototype.proportionallyColumnSizing = function () { - var _this = this; - var prevWidths = [], newWidths = [], prevWidth, newWidth, newTableWidth, prevTableWidth, moveLength, multiplier, cWidth, i, j, delay = 500, prevTotalColWidths = 0, currTotalColWidths, columnRestWidths = [], columns = this.dt.settings.aoColumns, bodyTableColumns = this.$('thead th', this.dom.scrollBodyTable), headTableColumns = this.$('thead th', this.dom.scrollHeadTable), footTableColumns = this.dom.scrollFootTable.length ? this.$('thead th', this.dom.scrollFootTable) : [], visColumns = []; - for (i = 0; i < columns.length; i++) { - if (!columns[i].bVisible) - continue; - visColumns.push(columns[i]); - columnRestWidths.push(0); //set default value - } + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Private methods (they are of course public in JS, but recommended as private) + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - for (i = 0; i < bodyTableColumns.length; i++) { - cWidth = parseFloat(bodyTableColumns[i].style.width); - prevTotalColWidths += cWidth; - prevWidths.push(cWidth); - } - - for (i = 0; i < bodyTableColumns.length; i++) { - bodyTableColumns[i].style.width = ''; - } + /** + * Constructor logic + * @method _fnConstruct + * @returns void + * @private + */ + "_fnConstruct": function () { + var that = this; + var iLen = that.s.dt.aoColumns.length; + var i; - //Get the new table width calculated by the browser - newTableWidth = parseFloat(this.dom.scrollBodyTable.css('width')); + that._fnSetupMouseListeners(); - //Get the old table width - prevTableWidth = this.dom.table.preWidth; - moveLength = newTableWidth - prevTableWidth; - if (moveLength == 0) { - for (i = 0; i < bodyTableColumns.length; i++) { - bodyTableColumns[i].style.width = prevWidths[i] + 'px'; + /* Add event handlers for the resize handles */ + for (i = 0; i < iLen; i++) { + /* Mark the original column width for later reference */ + this.s.dt.aoColumns[i]._ColResize_iOrigWidth = this.s.dt.aoColumns[i].width; } - return; - } - //var tot = 0; - currTotalColWidths = prevTotalColWidths; - for (i = 0; i < visColumns.length; i++) { - //For each column calculate the new width - prevWidth = prevWidths[i]; - multiplier = (+(prevWidth / prevTotalColWidths).toFixed(2)); - - //tot += multiplier; - newWidth = prevWidth + (moveLength * multiplier) + columnRestWidths[i]; - currTotalColWidths -= prevWidth; - - //Check whether the column can be resized to the new calculated value - //if not, set it to the min or max width depends on the moveLength value - if (!this.canResizeColumn(visColumns[i], newWidth)) { - cWidth = moveLength > 0 ? this.getColumnMaxWidth(visColumns[i]) : this.getColumnMinWidth(visColumns[i]); - var rest = newWidth - cWidth; - newWidth = cWidth; - - for (j = (i + 1); j < visColumns.length; j++) { - columnRestWidths[j] += rest * (+(visColumns[j] / currTotalColWidths).toFixed(2)); + this._fnSetColumnIndexes(); + + /* State saving */ + this.s.dt.oApi._fnCallbackReg( this.s.dt, 'aoStateSaveParams', function (oS, oData) { + that._fnStateSave.call(that, oData); + }, "ColResize_State" ); + + // State loading + this._fnStateLoad(); + }, + + /** + * @method _fnStateSave + * @param object oState DataTables state + * @private + */ + "_fnStateSave": function (oState) { + this.s.dt.aoColumns.forEach(function(col, index) { + oState.columns[index].width = col.sWidthOrig; + }); + }, + + /** + * If state has been loaded, apply the saved widths to the columns + * @method _fnStateLoad + * @private + */ + "_fnStateLoad": function() { + var that = this, + loadedState = this.s.dt.oLoadedState; + if (loadedState && loadedState.columns) { + var colStates = loadedState.columns, + currCols = this.s.dt.aoColumns; + // Only apply the saved widths if the number of columns is the same. + // Otherwise, we don't know if we're applying the width to the correct column. + if (colStates.length > 0 && colStates.length === currCols.length) { + colStates.forEach(function(state, index) { + var col = that.s.dt.aoColumns[index]; + if (state.width) { + col.sWidthOrig = col.sWidth = state.width; + } + }); } } - newWidths.push(newWidth); - } - - //Apply the calculated column widths to the headers cells - var tablesWidth = this.dom.scrollBodyTable.outerWidth() + 'px'; - for (i = 0; i < headTableColumns.length; i++) { - headTableColumns[i].style.width = newWidths[i] + 'px'; - } - this.dom.scrollHeadTable.css('width', tablesWidth); - this.dom.scrollHeadInner.css('width', tablesWidth); - - for (i = 0; i < bodyTableColumns.length; i++) { - bodyTableColumns[i].style.width = newWidths[i] + 'px'; - } - - if (this.dom.scrollFootTable.length) { - for (i = 0; i < footTableColumns.length; i++) { - footTableColumns[i].style.width = newWidths[i] + 'px'; + }, + + /** + * Remove events of type from obj add it to restoreEvents array to be restored at a later time + * @param until string flag when to restore the event + * @param obj Object to remove events from + * @param type type of event to remove + * @param namespace namespace of the event being removed + */ + "_fnDelayEvents": function (until, obj, type, namespace) { + var that = this; + //Get the events for the object + var events = $._data($(obj).get(0), 'events'); + $.each(events, function (i, o) { + //If the event type matches + if (i == type) { + //Loop through the possible many events with that type + $.each(o, function (k, v) { + //Somehow it is possible for the event to be undefined make sure it is defined first + if (v) { + if (namespace) { + //Add the event to the array of events to be restored later + that.dom.restoreEvents.push({"until": until, "obj": obj, "type": v.type, "namespace": v.namespace, "handler": v.handler}); + //If the namespace matches + if (v.namespace == namespace) { + //Turn off/unbind the event + $(obj).off(type + "." + namespace); + } + } else { + //Add the event to the array of events to be restored later + that.dom.restoreEvents.push({"until": until, "obj": obj, "type": v.type, "namespace": null, "handler": v.handler}); + //Turn off/unbind the event + $(obj).off(type); + } + } + }); + } + }); + }, + + /** + * Loop through restoreEvents array and restore the events on the elements provided + */ + "_fnRestoreEvents": function (until) { + var that = this; + //Loop through the events to be restored + var i; + for (i = that.dom.restoreEvents.length; i--;) { + if (that.dom.restoreEvents[i].until == undefined || that.dom.restoreEvents[i].until == null || that.dom.restoreEvents[i].until == until) { + if (that.dom.restoreEvents[i].namespace) { + //Turn on the event for the object provided + $(that.dom.restoreEvents[i].obj).off(that.dom.restoreEvents[i].type + "." + that.dom.restoreEvents[i].namespace).on(that.dom.restoreEvents[i].type + "." + that.dom.restoreEvents[i].namespace, that.dom.restoreEvents[i].handler); + that.dom.restoreEvents.splice(i, 1); + } else { + //Turn on the event for the object provided + $(that.dom.restoreEvents[i].obj).off(that.dom.restoreEvents[i].type).on(that.dom.restoreEvents[i].type, that.dom.restoreEvents[i].handler); + that.dom.restoreEvents.splice(i, 1); + } + } } - this.dom.scrollFootTable[0].style.width = tablesWidth; - this.dom.scrollFootInner[0].style.width = tablesWidth; - } + }, - //console.log('moveLength: ' + moveLength + ' multiplier: ' + tot); - //console.log(newWidths); - this.dom.table.preWidth = newTableWidth; - - //Call afterResizing function after the window stops resizing - if (this.dom.winResizeTimer) - clearTimeout(this.dom.winResizeTimer); - this.dom.winResizeTimer = setTimeout(function () { - _this.afterResizing(); - _this.dom.winResizeTimer = null; - }, delay); - }; + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Mouse drop and drag + */ - ColResize.prototype.getColumnIndex = function (col) { - //Get the current column position - var colIdx = -1; - for (var i = 0; i < this.dt.settings.aoColumns.length; i++) { - if (this.dt.settings.aoColumns[i] === col) { - colIdx = i; - break; + "_fnSetupMouseListeners":function() { + var that = this; + $(that.s.dt.nTableWrapper).off("mouseenter.ColResize").on("mouseenter.ColResize","th",function(e) { + e.preventDefault(); + that._fnMouseEnter.call(that, e, this); + }); + $(that.s.dt.nTableWrapper).off("mouseleave.ColResize").on("mouseleave.ColResize","th",function(e) { + e.preventDefault(); + that._fnMouseLeave.call(that, e, this); + }); + }, + + /** + * Add mouse listeners to the resize handle on TH element + * @method _fnMouseListener + * @param i Column index + * @param nTh TH resize handle element clicked on + * @returns void + * @private + */ + "_fnMouseListener": function (i, nTh) { + var that = this; + $(nTh).off('mouseenter.ColResize').on('mouseenter.ColResize', function (e) { + e.preventDefault(); + that._fnMouseEnter.call(that, e, nTh); + }); + $(nTh).off('mouseleave.ColResize').on('mouseleave.ColResize', function (e) { + e.preventDefault(); + that._fnMouseLeave.call(that, e, nTh); + }); + }, + + /** + * + * @param e Mouse event + * @param nTh TH element that the mouse is over + */ + "_fnMouseEnter": function (e, nTh) { + var that = this; + if(!that.s.isMousedown) { + //Once the mouse has entered the cell add mouse move event to see if the mouse is over resize handle + $(nTh).off('mousemove.ColResizeHandle').on('mousemove.ColResizeHandle', function (e) { + e.preventDefault(); + that._fnResizeHandleCheck.call(that, e, nTh); + }); } - } - return colIdx; - }; + }, + + /** + * Clear mouse events when the mouse has left the th + * @param e Mouse event + * @param nTh TH element that the mouse has just left + */ + "_fnMouseLeave": function (e, nTh) { + //Once the mouse has left the TH make suure to remove the mouse move listener + $(nTh).off('mousemove.ColResizeHandle'); + }, + + /** + * Mouse down on a TH element in the table header + * @method _fnMouseDown + * @param event e Mouse event + * @param element nTh TH element to be resized + * @returns void + * @private + */ + "_fnMouseDown": function (e, nTh) { + var that = this; + + that.s.isMousedown = true; - ColResize.prototype.getColumnEvent = function (th, type, ns) { - var event; - var thEvents = this.$._data(th, "events"); - this.$.each(thEvents[type] || [], function (idx, handler) { - if (handler.namespace === ns) - event = handler; - }); - return event; - }; - - ColResize.prototype.loadState = function (data) { - var _this = this; - var i, col; - - var onInit = function () { - if (_this.settings.fixedLayout) { - _this.setTablesLayout('fixed'); + /* Store information about the mouse position */ + var target = $(e.target).closest('th, td'); + var offset = target.offset(); + + /* Store information about the mouse position for resize calculations in mouse move function */ + this.s.mouse.startX = e.pageX; + this.s.mouse.startY = e.pageY; + + //Store the indexes of the columns the mouse is down on + var idx = that.dom.resizeCol[0].cellIndex; + + // the last column has no 'right-side' neighbour + // with fixed this can make the table smaller + if (that.dom.resizeColNeighbour[0] === undefined){ + var idxNeighbour = 0; } else { - _this.setTablesLayout('auto'); + var idxNeighbour = that.dom.resizeColNeighbour[0].cellIndex; } - if (!data.colResize) { - if (_this.dt.settings.oFeatures.bAutoWidthOrig) - _this.dt.settings.oFeatures.bAutoWidth = true; - else if (_this.dt.settings.sTableWidthOrig) - _this.$(_this.dt.settings.nTable).width(_this.dt.settings.sTableWidthOrig); - - for (i = 0; i < _this.dt.settings.aoColumns.length; i++) { - col = _this.dt.settings.aoColumns[i]; - if (col._ColResize_sWidthOrig) { - col.sWidthOrig = col._ColResize_sWidthOrig; - } - } - _this.dom.origState = true; - } else { - var columns = data.colResize.columns || []; - var wMap = {}; + + - if (_this.dt.settings.oFeatures.bAutoWidth) { - _this.dt.settings.oFeatures.bAutoWidth = false; - } + if (idx === undefined) { + return; + } - if (_this.dom.scrollX && data.colResize.tableSize > 0) { - _this.dom.scrollHeadTable.width(data.colResize.tableSize); - _this.dom.scrollHeadInner.width(data.colResize.tableSize); - _this.dom.scrollBodyTable.width(data.colResize.tableSize); - _this.dom.scrollFootTable.width(data.colResize.tableSize); + this.s.mouse.targetIndex = idx; + this.s.mouse.targetColumn = this.s.dt.aoColumns[ idx ]; + + this.s.mouse.neighbourIndex = idxNeighbour; + this.s.mouse.neighbourColumn = this.s.dt.aoColumns[ idxNeighbour ]; + + /* Add event handlers to the document */ + $(document) + .off('mousemove.ColResize').on('mousemove.ColResize', function (e) { + that._fnMouseMove.call(that, e); + }) + .off('mouseup.ColResize').on('mouseup.ColResize', function (e) { + that._fnMouseUp.call(that, e); + }); + }, + + /** + * Deal with a mouse move event while dragging to resize a column + * @method _fnMouseMove + * @param e Mouse event + * @returns void + * @private + */ + "_fnMouseMove": function (e) { + var that = this; + + var offset = $(that.s.mouse.targetColumn.nTh).offset(); + var relativeX = (e.pageX - offset.left); + var distFromLeft = relativeX; + var distFromRight = $(that.s.mouse.targetColumn.nTh).outerWidth() - relativeX - 1; + + //Change in mouse x position + var dx = e.pageX - that.s.mouse.startX; + //Get the minimum width of the column (default minimum 10px) + var minColumnWidth = Math.max(parseInt($(that.s.mouse.targetColumn.nTh).css('min-width')), 10); + //Store the previous width of the column + var prevWidth = $(that.s.mouse.targetColumn.nTh).width(); + //As long as the cursor is past the handle, resize the columns + if ((dx > 0 && distFromRight <= 0) || (dx < 0 && distFromRight >= 0)) { + if (!that.s.init.tableWidthFixed) { + //As long as the width is larger than the minimum + var newColWidth = Math.max(minColumnWidth, prevWidth + dx); + //Get the width difference (take into account the columns minimum width) + var widthDiff = newColWidth - prevWidth; + var colResizeIdx = parseInt(that.dom.resizeCol.attr("data-column-index")); + //Set datatable column widths + that.s.mouse.targetColumn.sWidthOrig = that.s.mouse.targetColumn.sWidth = that.s.mouse.targetColumn.width = newColWidth + "px"; + var domCols = $(that.s.dt.nTableWrapper).find("th[data-column-index='"+colResizeIdx+"']"); + //For each table expand the width by the same amount as the column + //This accounts for other datatable plugins like FixedColumns + domCols.parents("table").each(function() { + if(!$(this).parent().hasClass("DTFC_LeftBodyLiner")) { + var newWidth = $(this).width() + widthDiff; + $(this).width(newWidth); + } else { + var newWidth =$(that.s.dt.nTableWrapper).find(".DTFC_LeftHeadWrapper").children("table").width(); + $(this).parents(".DTFC_LeftWrapper").width(newWidth); + $(this).parent().width(newWidth+15); + $(this).width(newWidth); + } + }); + //Apply the new width to the columns after the table has been resized + domCols.width(that.s.mouse.targetColumn.width); + } else { + //A neighbour column must exist in order to resize a column in a table with a fixed width + if (that.s.mouse.neighbourColumn) { + //Get the minimum width of the neighbor column (default minimum 10px) + var minColumnNeighbourWidth = Math.max(parseInt($(that.s.mouse.neighbourColumn.nTh).css('min-width')), 10); + //Store the previous width of the neighbour column + var prevNeighbourWidth = $(that.s.mouse.neighbourColumn.nTh).width(); + //As long as the width is larger than the minimum + var newColWidth = Math.max(minColumnWidth, prevWidth + dx); + var newColNeighbourWidth = Math.max(minColumnNeighbourWidth, prevNeighbourWidth - dx); + //Get the width difference (take into account the columns minimum width) + var widthDiff = newColWidth - prevWidth; + var widthDiffNeighbour = newColNeighbourWidth - prevNeighbourWidth; + //Get the column index for the column being changed + var colResizeIdx = parseInt(that.dom.resizeCol.attr("data-column-index")); + var neighbourColResizeIdx = parseInt(that.dom.resizeColNeighbour.attr("data-column-index")); + //Set datatable column widths + that.s.mouse.neighbourColumn.sWidthOrig = that.s.mouse.neighbourColumn.sWidth = that.s.mouse.neighbourColumn.width = newColNeighbourWidth + "px"; + that.s.mouse.targetColumn.sWidthOrig = that.s.mouse.targetColumn.sWidth = that.s.mouse.targetColumn.width = newColWidth + "px"; + //Get list of columns based on column index in all affected tables tables. This accounts for other plugins like FixedColumns + var domNeighbourCols = $(that.s.dt.nTableWrapper).find("th[data-column-index='" + neighbourColResizeIdx + "']"); + var domCols = $(that.s.dt.nTableWrapper).find("th[data-column-index='" + colResizeIdx + "']"); + //If dx if positive (the width is getting larger) shrink the neighbour columns first + if(dx>0) { + domNeighbourCols.width(that.s.mouse.neighbourColumn.width); + domCols.width(that.s.mouse.targetColumn.width); + } else { + //Apply the new width to the columns then to the neighbour columns + domCols.width(that.s.mouse.targetColumn.width); + domNeighbourCols.width(that.s.mouse.neighbourColumn.width); + } + } } + } + that.s.mouse.startX = e.pageX; + }, + + /** + * Check to see if the mouse is over the resize handle area + * @param e + * @param nTh + */ + "_fnResizeHandleCheck": function (e, nTh) { + var that = this; + + var offset = $(nTh).offset(); + var relativeX = (e.pageX - offset.left); + var relativeY = (e.pageY - offset.top); + var distFromLeft = relativeX; + var distFromRight = $(nTh).outerWidth() - relativeX - 1; + + var handleBuffer = this.s.init.handleWidth / 2; + var leftHandleOn = distFromLeft < handleBuffer; + var rightHandleOn = distFromRight < handleBuffer; + + //If this is the first table cell + if ($(nTh).prev("th").length == 0) { + if(this.s.init.rtl) + rightHandleOn = false; + else + leftHandleOn = false; + } + //If this is the last cell and the table is fixed width don't let them expand the last cell directly + if ($(nTh).next("th").length == 0 && this.s.init.tableWidthFixed) { + if(this.s.init.rtl) + leftHandleOn = false; + else + rightHandleOn = false; + } - for (i = 0; i < columns.length; i++) { - wMap[i] = columns[i]; + var resizeAvailable = leftHandleOn||rightHandleOn; + + //If table is in right to left mode flip which TH is being resized + if (that.s.init.rtl) { + //Handle is to the left + if (leftHandleOn) { + that.dom.resizeCol = $(nTh); + that.dom.resizeColNeighbour = $(nTh).next(); + } else if (rightHandleOn) { + that.dom.resizeCol = $(nTh).prev(); + that.dom.resizeColNeighbour = $(nTh); } - for (i = 0; i < _this.dt.settings.aoColumns.length; i++) { - col = _this.dt.settings.aoColumns[i]; - var idx = col._ColReorder_iOrigCol != null ? col._ColReorder_iOrigCol : i; - col.sWidth = wMap[idx]; - col.sWidthOrig = wMap[idx]; - col.nTh.style.width = columns[i]; - - //Check for FixedHeader - if (col.fhTh) - col.fhTh.style.width = columns[i]; - if (col.fhTf) - col.fhTf.style.width = columns[i]; + } else { + //Handle is to the right + if (rightHandleOn) { + that.dom.resizeCol = $(nTh); + that.dom.resizeColNeighbour = $(nTh).next(); + } else if (leftHandleOn) { + that.dom.resizeCol = $(nTh).prev(); + that.dom.resizeColNeighbour = $(nTh); } - _this.dom.origState = false; } - _this.dt.api.columns.adjust(); - if (_this.dom.scrollX || _this.dom.scrollY) - _this.dt.api.draw(false); - }; - - if (this.initialized) { - onInit(); - return; - } - this.dt.settings.oApi._fnCallbackReg(this.dt.settings, 'colResizeInitCompleted', function () { - onInit(); - }, "ColResize_Init"); - }; - - ColResize.prototype.saveState = function (data) { - if (!this.dt.settings._bInitComplete) { - var oData = this.dt.settings.fnStateLoadCallback.call(this.dt.settings.oInstance, this.dt.settings); - if (oData && oData.colResize) - data.colResize = oData.colResize; - return; - } - this.updateTableSize(); - data.colResize = { - columns: [], - tableSize: this.tableSize - }; - - data.colResize.columns.length = this.dt.settings.aoColumns.length; - for (var i = 0; i < this.dt.settings.aoColumns.length; i++) { - var col = this.dt.settings.aoColumns[i]; - var idx = col._ColReorder_iOrigCol != null ? col._ColReorder_iOrigCol : i; - data.colResize.columns[idx] = col.sWidth; - } - }; - - ColResize.prototype.registerCallbacks = function () { - var _this = this; - /* State saving */ - this.dt.settings.oApi._fnCallbackReg(this.dt.settings, 'aoStateSaveParams', function (oS, oData) { - _this.saveState(oData); - }, "ColResize_StateSave"); - - /* State loading */ - this.dt.settings.oApi._fnCallbackReg(this.dt.settings, 'aoStateLoaded', function (oS, oData) { - _this.loadState(oData); - }, "ColResize_StateLoad"); - - if (this.$.fn.DataTable.models.oSettings.remoteStateInitCompleted !== undefined) { - //Integrate with remote state - this.dt.settings.oApi._fnCallbackReg(this.dt.settings, 'remoteStateLoadedParams', function (s, data) { - _this.loadState(data); - }, "ColResize_StateLoad"); - this.dt.settings.oApi._fnCallbackReg(this.dt.settings, 'remoteStateSaveParams', function (s, data) { - _this.saveState(data); - }, "ColResize_StateSave"); - } - }; - - ColResize.prototype.setTablesLayout = function (value) { - if (this.dom.scrollX || this.dom.scrollY) { - this.dom.scrollHeadTable.css('table-layout', value); - this.dom.scrollBodyTable.css('table-layout', value); - this.dom.scrollFootTable.css('table-layout', value); - } else { - this.$(this.dt.settings.nTable).css('table-layout', value); - } - this.dom.fixedLayout = value == 'fixed'; - }; - - //only when scrollX or scrollY are enabled - ColResize.prototype.fixFootAndHeadTables = function (e) { - var _this = this; - if (e != null && e.target !== this.dt.settings.nTable) - return; - - if (this.dom.scrollFootTable.length) { - this.$('thead', this.dom.scrollFootTable).remove(); - this.dom.scrollFootTable.prepend(this.$('thead', this.dom.scrollBodyTable).clone()); - } - this.$('tfoot', this.dom.scrollHeadTable).remove(); - this.dom.scrollHeadTable.append(this.$('tfoot', this.dom.scrollBodyTable).clone()); - var removeFooterWidth = function (table) { - _this.$('tfoot>tr>th', table).each(function (i, th) { - _this.$(th).css('width', ''); - }); - }; - - //Remove all tfoot headers widths - removeFooterWidth(this.dom.scrollFootTable); - removeFooterWidth(this.dom.scrollBodyTable); - removeFooterWidth(this.dom.scrollHeadTable); - }; - - ColResize.prototype.onDraw = function (e) { - if (e != null && e.target !== this.dt.settings.nTable) - return; - if (this.dom.scrollX || this.dom.scrollY) { - this.fixFootAndHeadTables(); - - //Fix the header table padding - if (this.dt.settings._bInitComplete) { - var borderWidth = this.dom.scrollHeadTable.outerWidth() - this.dom.scrollHeadTable.innerWidth(); - var paddingType = this.dt.settings.oBrowser.bScrollbarLeft ? 'padding-left' : 'padding-right'; - var paddingVal = parseFloat(this.dom.scrollHeadInner.css(paddingType)); - this.dom.scrollHeadInner.css(paddingType, (paddingVal + borderWidth) + 'px'); - } - } - - var autoWidthTypes = []; - if (this.settings.dblClick == 'autoMinFit' || !this.settings.fixedLayout) - autoWidthTypes.push('autoMinWidth'); - if (this.settings.dblClick == 'autoFit') - autoWidthTypes.push('autoWidth'); - - //Call this only once so that the table will be cloned only one time - if (autoWidthTypes.length) - this.updateColumnsAutoWidth(autoWidthTypes); - - if (!this.settings.fixedLayout) { - var columns = this.dt.settings.aoColumns; - var i; - for (i = 0; i < columns.length; i++) { - if (!columns[i].bVisible) - continue; - columns[i].minWidth = Math.max((columns[i].minWidthOrig || 0), columns[i].autoMinWidth); - - //We have to resize if the current column width if is less that the column minWidth - if (this.$(columns[i].nTh).width() < columns[i].minWidth) - this.resize(columns[i], columns[i].minWidth); + //If table width is fixed make sure both columns are resizable else just check the one. + if(this.s.init.tableWidthFixed) + resizeAvailable &= this.s.init.exclude.indexOf(parseInt($(that.dom.resizeCol).attr("data-column-index"))) == -1 && this.s.init.exclude.indexOf(parseInt($(that.dom.resizeColNeighbour).attr("data-column-index"))) == -1; + else + resizeAvailable &= this.s.init.exclude.indexOf(parseInt($(that.dom.resizeCol).attr("data-column-index"))) == -1; + + $(nTh).off('mousedown.ColResize'); + if (resizeAvailable) { + $(nTh).css("cursor", "ew-resize"); + + //Delay other mousedown events from the Reorder plugin + that._fnDelayEvents(null, nTh, "mousedown", "ColReorder"); + that._fnDelayEvents("click", nTh, "click", "DT"); + + $(nTh).off('mousedown.ColResize').on('mousedown.ColResize', function (e) { + e.preventDefault(); + that._fnMouseDown.call(that, e, nTh); + }) + .off('click.ColResize').on('click.ColResize', function (e) { + that._fnClick.call(that, e); + }); + } else { + $(nTh).css("cursor", "pointer"); + $(nTh).off('mousedown.ColResize click.ColResize'); + //Restore any events that were removed + that._fnRestoreEvents(); + //This is to restore column sorting on click functionality + if (!that.s.isMousedown) + //Restore click event if mouse is not down + this._fnRestoreEvents("click"); } - } else { - if (!this.dom.fixedLayout) { - this.setTablesLayout('fixed'); - this.afterResizing(); + }, + + "_fnClick": function (e) { + var that = this; + that.s.isMousedown = false; + e.stopImmediatePropagation(); + }, + + /** + * Finish off the mouse drag + * @method _fnMouseUp + * @param e Mouse event + * @returns void + * @private + */ + "_fnMouseUp": function (e) { + var that = this; + that.s.isMousedown = false; + + //Fix width of column to be the size the dom is limited to (for when user sets min-width on a column) + that.s.mouse.targetColumn.width = that.dom.resizeCol.width(); + + $(document).off('mousemove.ColResize mouseup.ColResize'); + this.s.dt.oInstance.fnAdjustColumnSizing(); + //Table width fix, prevents extra gaps between tables + var LeftWrapper = $(that.s.dt.nTableWrapper).find(".DTFC_LeftWrapper"); + var DTFC_LeftWidth = LeftWrapper.width(); + LeftWrapper.children(".DTFC_LeftHeadWrapper").children("table").width(DTFC_LeftWidth); + + if (that.s.init.resizeCallback) { + that.s.init.resizeCallback.call(that, that.s.mouse.targetColumn); } - } - }; - - ColResize.prototype.getTableAutoColWidths = function (table, types) { - var widths = {}, i, colIdx; - var $table = this.$(table); - for (i = 0; i < types.length; i++) { - widths[types[i]] = []; - } - if (!types.length || !$table.length) - return widths; - - var clnTable = $table.clone().removeAttr('id').css('table-layout', 'auto'); - - // Remove any assigned widths from the footer (from scrolling) - clnTable.find('thead th, tfoot th, tfoot td').css('width', ''); - var container = this.$('
').css({ - 'position': 'absolute', - 'width': '9999px', - 'height': '9999px' - }); - container.append(clnTable); - this.$(this.dt.settings.nTableWrapper).append(container); - - var headerCols = this.$('thead>tr>th', clnTable); - - for (i = 0; i < types.length; i++) { - var type = types[i]; - var fn = ''; - switch (type) { - case 'autoMinWidth': - clnTable.css('width', '1px'); - fn = 'width'; + }, + + /** + * Clean up ColResize memory references and event handlers + * @method _fnDestroy + * @returns void + * @private + */ + "_fnDestroy": function () { + var i, iLen; + + for (i = 0, iLen = this.s.dt.aoDrawCallback.length; i < iLen; i++) { + if (this.s.dt.aoDrawCallback[i].sName === 'ColResize_Pre') { + this.s.dt.aoDrawCallback.splice(i, 1); break; - case 'autoWidth': - clnTable.css('width', 'auto'); - fn = 'outerWidth'; - break; - default: - throw 'Invalid widthType ' + type; - } - for (colIdx = 0; colIdx < headerCols.length; colIdx++) { - widths[type].push(this.$(headerCols[colIdx])[fn]()); - } - } - - container.remove(); - return widths; - }; - - ColResize.prototype.updateColumnsAutoWidth = function (types) { - var columns = this.dt.settings.aoColumns; - var i, j, colLen, type, visColIdx = 0; - var widths = {}; - if (this.dom.scrollX || this.dom.scrollY) { - var headWidths = this.getTableAutoColWidths(this.dom.scrollHeadTable, types); - var bodyWidths = this.getTableAutoColWidths(this.dom.scrollBodyTable, types); - var footWidths = this.getTableAutoColWidths(this.dom.scrollFootTable, types); - - for (i = 0; i < types.length; i++) { - type = types[i]; - widths[type] = []; - footWidths[type].length = headWidths[type].length; - colLen = headWidths[type].length; - for (j = 0; j < colLen; j++) { - widths[type].push(Math.max(headWidths[type][j], bodyWidths[type][j], (footWidths[type][j] || 0))); } } - } else { - widths = this.getTableAutoColWidths(this.dt.settings.nTable, types); - } - - for (i = 0; i < columns.length; i++) { - if (!columns[i].bVisible) - continue; - for (j = 0; j < types.length; j++) { - type = types[j]; - columns[i][type] = widths[type][visColIdx]; - } - visColIdx++; - } - }; - ColResize.prototype.overrideClickHander = function (col, $th) { - var dtClickEvent = this.getColumnEvent($th.get(0), 'click', 'DT'); + $(this.s.dt.nTHead).find('*').off('.ColResize'); - //Remove the DataTables event so that ordering will not occur - if (dtClickEvent) { - $th.off('click.DT'); - this.$(document).one('click.ColResize', function (e) { - $th.on('click.DT', dtClickEvent.handler); + $.each(this.s.dt.aoColumns, function (i, column) { + $(column.nTh).removeAttr('data-column-index'); }); - } - }; - - ColResize.prototype.onDblClick = function (e, $th, col) { - if (e.target !== $th.get(0)) - return; - if ($th.css('cursor') != 'col-resize') - return; - - var width; - switch (this.settings.dblClick) { - case 'autoMinFit': - width = col.autoMinWidth; - break; - case 'autoFit': - width = col.autoWidth; - break; - default: - width = col.initWidth; - } - this.resize(col, width); - }; - - ColResize.prototype.onMouseDown = function (e, col) { - var _this = this; - if (e.target !== col.nTh && e.target !== col.fhTh) - return true; - - var $th = e.target === col.nTh ? this.$(col.nTh) : this.$(col.fhTh); - - if ($th.css('cursor') != 'col-resize' || col.resizable === false) { - var colReorder = this.dt.settings._colReorder; - if (colReorder) { - colReorder._fnMouseDown.call(colReorder, e, e.target); //Here we fix the e.preventDefault() in ColReorder so that we can have working inputs in header - } - return true; - } - this.dom.mouse.startX = e.pageX; - this.dom.mouse.prevX = e.pageX; - this.dom.mouse.startWidth = $th.width(); - this.dom.resize = true; - this.beforeResizing(col); + this.s.dt._colResize = null; + this.s = null; + }, - /* Add event handlers to the document */ - this.$(document).on('mousemove.ColResize', function (event) { - _this.onMouseMove(event, col); - }); - this.overrideClickHander(col, $th); - this.$(document).one('mouseup.ColResize', function (event) { - _this.onMouseUp(event, col); - }); - - return false; - }; - - ColResize.prototype.resize = function (col, width) { - var colWidth = this.$(col.nTh).width(); - var moveLength = width - this.$(col.nTh).width(); - this.beforeResizing(col); - var resized = this.resizeColumn(col, colWidth, moveLength, moveLength); - this.afterResizing(); - return resized; - }; - - ColResize.prototype.beforeResizing = function (col) { - //if (this.settings.fixedLayout && !this.dom.fixedLayout) - // this.setTablesLayout('fixed'); - }; - - ColResize.prototype.afterResizing = function () { - var i; - var columns = this.dt.settings.aoColumns; - for (i = 0; i < columns.length; i++) { - if (!columns[i].bVisible) - continue; - columns[i].sWidth = this.$(columns[i].nTh).css('width'); - } - - //Update the internal storage of the table's width (in case we changed it because the user resized some column and scrollX was enabled - this.updateTableSize(); - - //Save the state - this.dt.settings.oInstance.oApi._fnSaveState(this.dt.settings); - this.dom.origState = false; - }; - ColResize.prototype.onMouseUp = function (e, col) { - this.$(document).off('mousemove.ColResize'); - if (!this.dom.resize) - return; - this.dom.resize = false; - this.afterResizing(); - }; - - ColResize.prototype.canResizeColumn = function (col, newWidth) { - return (col.resizable === undefined || col.resizable) && this.settings.minWidth <= newWidth && (!col.minWidth || col.minWidth <= newWidth) && (!this.settings.maxWidth || this.settings.maxWidth >= newWidth) && (!col.maxWidth || col.maxWidth >= newWidth); - }; - - ColResize.prototype.getColumnMaxWidth = function (col) { - return col.maxWidth ? col.maxWidth : this.settings.maxWidth; - }; - - ColResize.prototype.getColumnMinWidth = function (col) { - return col.minWidth ? col.minWidth : this.settings.minWidth; - }; - - ColResize.prototype.getPrevResizableColumnIdx = function (col, moveLength) { - var columns = this.dt.settings.aoColumns; - var colIdx = ColResizeHelper.indexOf(columns, col); - for (var i = colIdx; i >= 0; i--) { - if (!columns[i].bVisible) - continue; - var newWidth = this.$(columns[i].nTh).width() + moveLength; - if (this.canResizeColumn(columns[i], newWidth)) - return i; - } - return -1; - }; - - ColResize.prototype.getNextResizableColumnIdx = function (col, moveLength) { - var columns = this.dt.settings.aoColumns; - var colIdx = ColResizeHelper.indexOf(columns, col); - for (var i = (colIdx + 1); i < columns.length; i++) { - if (!columns[i].bVisible) - continue; - var newWidth = this.$(columns[i].nTh).width() - moveLength; - if (this.canResizeColumn(columns[i], newWidth)) - return i; + /** + * Add a data attribute to the column headers, so we know the index of + * the row to be reordered. This allows fast detection of the index, and + * for this plug-in to work with FixedHeader which clones the nodes. + * @private + */ + "_fnSetColumnIndexes": function () { + $.each(this.s.dt.aoColumns, function (i, column) { + $(column.nTh).attr('data-column-index', i); + }); } - return -1; }; - ColResize.prototype.resizeColumn = function (col, startWidth, moveLength, lastMoveLength) { - if (moveLength == 0 || lastMoveLength == 0 || col.resizable === false) - return false; - var i; - var columns = this.dt.settings.aoColumns; - var headCol = this.$(col.nTh); - var headColNext = headCol.next(); - var colIdx = this.getColumnIndex(col); - var thWidth = startWidth + moveLength; - var thNextWidth; - var nextColIdx; - - if (!this.dom.scrollX) { - if (lastMoveLength < 0) { - thWidth = headColNext.width() - lastMoveLength; - nextColIdx = this.getPrevResizableColumnIdx(col, lastMoveLength); - if (nextColIdx < 0) - return false; - headCol = headColNext; - colIdx = colIdx + 1; - headColNext = this.$(columns[nextColIdx].nTh); - thNextWidth = headColNext.width() + lastMoveLength; - } else { - thWidth = headCol.width() + lastMoveLength; - nextColIdx = this.getNextResizableColumnIdx(col, lastMoveLength); - - //If there is no columns that can be shrinked dont resize anymore - if (nextColIdx < 0) - return false; - headColNext = this.$(columns[nextColIdx].nTh); - thNextWidth = headColNext.width() - lastMoveLength; - if ((this.settings.maxWidth && this.settings.maxWidth < thWidth) || col.maxWidth && col.maxWidth < thWidth) - return false; - } - if (!this.canResizeColumn(columns[nextColIdx], thNextWidth) || !this.canResizeColumn(columns[colIdx], thWidth)) - return false; - headColNext.width(thNextWidth); - - //If fixed header is present we have to resize the cloned column too - if (this.dom.fixedHeader) { - this.$(columns[nextColIdx].fhTh).width(thNextWidth); - this.$(columns[colIdx].fhTh).width(thWidth); - - //If fixedfooter was enabled resize that too - if (columns[nextColIdx].fhTf) { - this.$(columns[nextColIdx].fhTf).width(thNextWidth); - this.$(columns[colIdx].fhTf).width(thWidth); + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Static parameters + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + + /** + * ColResize default settings for initialisation + * @namespace + * @static + */ + ColResize.defaults = { + /** + * Callback function that is fired when columns are resized + * @type function():void + * @default null + * @static + */ + "resizeCallback": null, + + /** + * Exclude array for columns that are not resizable + * @property exclude + * @type array of indexes that are excluded from resizing + * @default [] + */ + "exclude": [], + + /** + * Check to see if user is using a fixed table width or dynamic + * if true: + * -Columns will resize themselves and their neighbour + * -If neighbour is excluded resize will not occur + * if false: + * -Columns will resize themselves and increase or decrease the width of the table accordingly + */ + "tableWidthFixed": true, + + /** + * Width of the resize handle in pixels + * @property handleWidth + * @type int (pixels) + * @default 10 + */ + "handleWidth": 10, + + /** + * Right to left support, when true flips which column they are resizing on mouse down + * @property rtl + * @type bool + * @default false + */ + "rtl": false + }; + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Constants + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * ColResize version + * @constant version + * @type String + * @default As code + */ + ColResize.version = "0.0.10"; + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables interfaces + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + // Expose + $.fn.dataTable.ColResize = ColResize; + $.fn.DataTable.ColResize = ColResize; + + + // Register a new feature with DataTables + if (typeof $.fn.dataTable == "function" && + typeof $.fn.dataTableExt.fnVersionCheck == "function" && + $.fn.dataTableExt.fnVersionCheck('1.9.3')) { + $.fn.dataTableExt.aoFeatures.push({ + "fnInit": function (settings) { + var table = settings.oInstance; + + if (!settings._colResize) { + var dtInit = settings.oInit; + var opts = dtInit.colResize || dtInit.oColResize || {}; + + new ColResize(settings, opts); + } + else { + table.oApi._fnLog(settings, 1, "ColResize attempted to initialise twice. Ignoring second"); } - } - } else { - if (!this.canResizeColumn(col, thWidth)) - return false; - var tSize = this.tableSize + moveLength + 'px'; - this.dom.scrollHeadInner.css('width', tSize); - this.dom.scrollHeadTable.css('width', tSize); - this.dom.scrollBodyTable.css('width', tSize); - this.dom.scrollFootTable.css('width', tSize); - } - headCol.width(thWidth); - - //scrollX or scrollY enabled - if (this.dom.scrollBody.length) { - var colDomIdx = 0; - for (i = 0; i < this.dt.settings.aoColumns.length && i != colIdx; i++) { - if (this.dt.settings.aoColumns[i].bVisible) - colDomIdx++; - } - //Get the table - var bodyCol = this.$('thead>tr>th:nth(' + colDomIdx + ')', this.dom.scrollBodyTable); - var footCol = this.$('thead>tr>th:nth(' + colDomIdx + ')', this.dom.scrollFootTable); + return null; + /* No node for DataTables to insert */ + }, + "cFeature": "Z", + "sFeature": "ColResize" + }); + } else { + alert("Warning: ColResize requires DataTables 1.9.3 or greater - www.datatables.net/download"); + } - //This will happen only when scrollY is used without scrollX - if (!this.dom.scrollX) { - var nextColDomIdx = 0; - for (i = 0; i < this.dt.settings.aoColumns.length && i != nextColIdx; i++) { - if (this.dt.settings.aoColumns[i].bVisible) - nextColDomIdx++; - } - var bodyColNext = this.$('thead>tr>th:nth(' + nextColDomIdx + ')', this.dom.scrollBodyTable); - var footColNext = this.$('thead>tr>th:nth(' + nextColDomIdx + ')', this.dom.scrollFootTable); - bodyColNext.width(thNextWidth); - if (thWidth > 0) - bodyCol.width(thWidth); +// API augmentation + if ($.fn.dataTable.Api) { + $.fn.dataTable.Api.register('colResize.reset()', function () { + return this.iterator('table', function (ctx) { + ctx._colResize.fnReset(); + }); + }); + } - footColNext.width(thNextWidth); - if (thWidth > 0) - footCol.width(thWidth); - } + return ColResize; + }; // /factory - //Resize the table and the column - if (this.dom.scrollX && thWidth > 0) { - bodyCol.width(thWidth); - footCol.width(thWidth); - } - } - return true; - }; - ColResize.prototype.onMouseMove = function (e, col) { - var moveLength = e.pageX - this.dom.mouse.startX; - var lastMoveLength = e.pageX - this.dom.mouse.prevX; - this.resizeColumn(col, this.dom.mouse.startWidth, moveLength, lastMoveLength); - this.dom.mouse.prevX = e.pageX; - }; +// Define as an AMD module if possible +if ( typeof define === 'function' && define.amd ) { + define( ['jquery', 'datatables'], factory ); +} +else if ( typeof exports === 'object' ) { + // Node/CommonJS + factory( require('jquery'), require('datatables') ); +} +else if (jQuery && !jQuery.fn.dataTable.ColResize) { + // Otherwise simply initialise as normal, stopping multiple evaluation + factory(jQuery, jQuery.fn.dataTable); +} - ColResize.prototype.destroy = function () { - }; - ColResize.defaultSettings = { - minWidth: 1, - maxWidth: null, - fixedLayout: true, - fixedHeader: null, - dblClick: 'initWidth' - }; - return ColResize; - })(); - dt.ColResize = ColResize; - var ColResizeHelper = (function () { - function ColResizeHelper() { - } - ColResizeHelper.indexOf = function (arr, item, equalFun) { - if (typeof equalFun === "undefined") { equalFun = null; } - for (var i = 0; i < arr.length; i++) { - if (equalFun) { - if (equalFun(arr[i], item)) - return i; - } else if (arr[i] === item) - return i; - } - return -1; - }; - return ColResizeHelper; - })(); - dt.ColResizeHelper = ColResizeHelper; -})(dt || (dt = {})); - -(function ($, window, document, undefined) { - //Register events - $.fn.DataTable.models.oSettings.colResizeInitCompleted = []; - - //Register api function - $.fn.DataTable.Api.register('colResize.init()', function (settings) { - var colResize = new dt.ColResize($, this, settings); - if (this.settings()[0]._bInitComplete) - colResize.initialize(); - else - this.one('init.dt', function () { - colResize.initialize(); - }); - return null; - }); - - $.fn.DataTable.Api.register('column().resize()', function (width) { - var oSettings = this.settings()[0]; - var colResize = oSettings.colResize; - return colResize.resize(oSettings.aoColumns[this[0][0]], width); - }); - - //Add as feature - $.fn.dataTable.ext.feature.push({ - "fnInit": function (oSettings) { - return oSettings.oInstance.api().colResize.init(oSettings.oInit.colResize); - }, - "cFeature": "J", - "sFeature": "ColResize" - }); -}(jQuery, window, document, undefined)); \ No newline at end of file +})(window, document); \ No newline at end of file diff --git a/wqflask/wqflask/templates/collections/list.html b/wqflask/wqflask/templates/collections/list.html index a00878a0..c05b694b 100755 --- a/wqflask/wqflask/templates/collections/list.html +++ b/wqflask/wqflask/templates/collections/list.html @@ -4,8 +4,6 @@ - - {% endblock %} {% block content %} @@ -59,30 +57,20 @@ + - - {% endblock %} diff --git a/wqflask/wqflask/templates/collections/view.html b/wqflask/wqflask/templates/collections/view.html index 49df6af5..29c65058 100755 --- a/wqflask/wqflask/templates/collections/view.html +++ b/wqflask/wqflask/templates/collections/view.html @@ -4,8 +4,6 @@ - - {% endblock %} {% block content %} @@ -121,10 +119,9 @@ + - - diff --git a/wqflask/wqflask/templates/correlation_page.html b/wqflask/wqflask/templates/correlation_page.html index d53f930d..62407555 100755 --- a/wqflask/wqflask/templates/correlation_page.html +++ b/wqflask/wqflask/templates/correlation_page.html @@ -229,22 +229,26 @@ { "type": "natural" }, { "type": "natural" } ], - "sDom": "RJtir", + "sDom": "RZtir", "iDisplayLength": -1, "autoWidth": true, "bLengthChange": true, "bDeferRender": true, "bSortClasses": false, - "scrollY": "700px", - "scrollCollapse": false, + //"scrollY": "700px", + //"scrollCollapse": false, "colResize": { "tableWidthFixed": false }, "paging": false } ); + + var table = $('#corr_results').DataTable(); + new $.fn.dataTable.FixedHeader( table ); + {% elif target_dataset.type == "Publish" %} $('#corr_results').dataTable( { - "aoColumns": [ + "columns": [ { "type": "natural" }, { "type": "natural" }, { "type": "natural" }, @@ -257,7 +261,7 @@ { "type": "natural" }, { "type": "natural" } ], - "sDom": "RJtir", + "sDom": "RZtir", "iDisplayLength": -1, "autoWidth": true, "bLengthChange": true, @@ -280,7 +284,7 @@ { "type": "natural" }, { "type": "natural" } ], - "sDom": "RJtir", + "sDom": "RZtir", "iDisplayLength": -1, "autoWidth": true, "bLengthChange": true, diff --git a/wqflask/wqflask/templates/index_page.html b/wqflask/wqflask/templates/index_page.html index 49067e37..2bbfcd91 100755 --- a/wqflask/wqflask/templates/index_page.html +++ b/wqflask/wqflask/templates/index_page.html @@ -79,7 +79,7 @@
- +
@@ -100,7 +100,7 @@
- +
@@ -265,4 +265,15 @@ {% block js %} + + + {% endblock %} \ No newline at end of file diff --git a/wqflask/wqflask/templates/marker_regression.html b/wqflask/wqflask/templates/marker_regression.html index d8f64c20..91808fcf 100755 --- a/wqflask/wqflask/templates/marker_regression.html +++ b/wqflask/wqflask/templates/marker_regression.html @@ -26,26 +26,36 @@ -
+

Results

- +
- - - - - + + + + + - {% for marker in filtered_markers %} - {% if marker.lod_score > lod_cutoff %} + {% for marker in qtl_results %} + {% if (score_type == "LOD" and marker.lod_score > cutoff) or + (score_type == "LRS" and marker.lrs_value > cutoff) %} - + + {% if score_type == "LOD" %} + {% else %} + + {% endif %} @@ -70,26 +80,24 @@ $(document).ready( function () { console.time("Creating table"); $('#qtl_results').dataTable( { - //"sDom": "<<'span3'l><'span3'T><'span4'f>'row-fluid'r>t<'row-fluid'<'span6'i><'span6'p>>", - "sDom": "lTftipr", - "oTableTools": { - "aButtons": [ - "copy", - "print", - { - "sExtends": "collection", - "sButtonText": 'Save ', - "aButtons": [ "csv", "xls", "pdf" ] - } + "columns": [ + { "type": "natural" }, + { "type": "natural" }, + { "type": "natural" }, + { "type": "natural" }, + { "type": "natural" } ], - "sSwfPath": "/static/packages/TableTools/media/swf/copy_csv_xls_pdf.swf" - }, - "iDisplayLength": 50, - "bLengthChange": true, + "sDom": "ZRtir", + "iDisplayLength": -1, + "autoWidth": true, "bDeferRender": true, - "bSortClasses": false + "bSortClasses": false, + "scrollY": "700px", + "scrollCollapse": true, + "paging": false } ); console.timeEnd("Creating table"); + }); {% endblock %} diff --git a/wqflask/wqflask/templates/search_result_page.html b/wqflask/wqflask/templates/search_result_page.html index b9bb65fd..335ab213 100755 --- a/wqflask/wqflask/templates/search_result_page.html +++ b/wqflask/wqflask/templates/search_result_page.html @@ -188,19 +188,16 @@ { "type": "natural", "width": "15%" }, { "type": "natural" } ], - "sDom": "RJtir", + "sDom": "RZtir", "iDisplayLength": -1, "autoWidth": false, - "bLengthChange": true, "bDeferRender": true, "bSortClasses": false, "scrollY": "700px", "scrollCollapse": false, - "colResize": { - "tableWidthFixed": false, - }, "paging": false } ); + {% elif dataset.type == 'Publish' %} $('#trait_table').DataTable( { "columns": [ @@ -213,17 +210,13 @@ { "type": "natural", "width": "15%"}, { "type": "natural" } ], - "sDom": "RJtir", + "sDom": "RZtir", "iDisplayLength": -1, "autoWidth": false, - "bLengthChange": true, "bDeferRender": true, "bSortClasses": false, "scrollY": "700px", "scrollCollapse": false, - "colResize": { - "tableWidthFixed": false, - }, "paging": false } ); {% elif dataset.type == 'Geno' %} @@ -233,17 +226,13 @@ { "type": "natural" }, { "type": "natural", "width": "40%"} ], - "sDom": "RJtir", + "sDom": "RZtir", "iDisplayLength": -1, - "autoWidth": false, - "bLengthChange": true, + "autoWidth": true, "bDeferRender": true, "bSortClasses": false, "scrollY": "700px", "scrollCollapse": false, - "colResize": { - "tableWidthFixed": false, - }, "paging": false } ); {% endif %} diff --git a/wqflask/wqflask/templates/show_trait.html b/wqflask/wqflask/templates/show_trait.html index 40f6eafd..6199f931 100755 --- a/wqflask/wqflask/templates/show_trait.html +++ b/wqflask/wqflask/templates/show_trait.html @@ -13,8 +13,6 @@ - - {% endblock %} {% block content %} @@ -82,6 +80,7 @@
{% include 'show_trait_mapping_tools.html' %}
+
@@ -150,8 +149,6 @@ - -
IndexLOD ScoreChrMbLocusIndexLOD ScoreChrMbLocus
{{loop.index}} + {{loop.index}} + + {{marker.lod_score}}{{marker.lrs_value}}{{marker.chr}} {{marker.Mb}} {{marker.name}}