Trying to use JQuery to draw lines over table data

こ雲淡風輕ζ 提交于 2019-12-22 13:09:20

问题


I am trying to draw lines across a table when the data matches over specific time periods. like this:

The Black lines being matching numbers from Previous Row.
The Blue Lines being matching numbers from one row to two previous rows (ID# - 2).
The Red lines being matching numbers from one row to three previous rows (ID# - 3).

How do you add JQuery to Draw these line on a table with this kind of data:

<section>
        <article>
            <h3>Number Sets</h3>
            <table id="dataset">
                <thead><tr><th>ID</th><th>1st #</th><th>2nd #</th><th>3rd #</th><th>4th #</th><th>5th #</th><th>6th #</th><th>Sum of</th><th>Avg of</th></tr></thead>
                <tbody>
                <tr class="2405"><td># 2405</td><td class="v9">9</td><td class="v17">17</td><td class="v24">24</td><td class="v34">34</td><td class="v43">43</td><td class="v49">49</td><td class="v176">176</td><td class="v29.33">29.33</td></tr>
                <tr class="2404"><td># 2404</td><td class="v22">22</td><td class="v26">26</td><td class="v31">31</td><td class="v32">32</td><td class="v43">43</td><td class="v45">45</td><td class="v198">198</td><td class="v33.00">33.00</td></tr>
                <tr class="2403"><td># 2403</td><td class="v7">7</td><td class="v11">11</td><td class="v18">18</td><td class="v44">44</td><td class="v53">53</td><td class="v54">54</td><td class="v187">187</td><td class="v31.17">31.17</td></tr>
                <tr class="2402"><td># 2402</td><td class="v14">14</td><td class="v15">15</td><td class="v27">27</td><td class="v37">37</td><td class="v44">44</td><td class="v47">47</td><td class="v184">184</td><td class="v30.67">30.67</td></tr>
                <tr class="2401"><td># 2401</td><td class="v37">37</td><td class="v54">54</td><td class="v31">31</td><td class="v6">6</td><td class="v26">26</td><td class="v15">15</td><td class="v169">169</td><td class="v28.17">28.17</td></tr>
                <tr class="2400"><td># 2400</td><td class="v39">39</td><td class="v35">35</td><td class="v38">38</td><td class="v41">41</td><td class="v22">22</td><td class="v34">34</td><td class="v209">209</td><td class="v34.83">34.83</td></tr>
                <tr class="2399"><td># 2399</td><td class="v9">9</td><td class="v12">12</td><td class="v18">18</td><td class="v31">31</td><td class="v34">34</td><td class="v51">51</td><td class="v155">155</td><td class="v25.83">25.83</td></tr>
                <tr class="2398"><td># 2398</td><td class="v1">1</td><td class="v29">29</td><td class="v14">14</td><td class="v46">46</td><td class="v38">38</td><td class="v26">26</td><td class="v154">154</td><td class="v25.67">25.67</td></tr>
                <tr class="2397"><td># 2397</td><td class="v35">35</td><td class="v6">6</td><td class="v8">8</td><td class="v30">30</td><td class="v47">47</td><td class="v42">42</td><td class="v168">168</td><td class="v28.00">28.00</td></tr>
                <tr class="2396"><td># 2396</td><td class="v45">45</td><td class="v25">25</td><td class="v4">4</td><td class="v33">33</td><td class="v49">49</td><td class="v48">48</td><td class="v204">204</td><td class="v34.00">34.00</td></tr>
                <tr class="2395"><td># 2395</td><td class="v11">11</td><td class="v9">9</td><td class="v37">37</td><td class="v44">44</td><td class="v25">25</td><td class="v17">17</td><td class="v143">143</td><td class="v23.83">23.83</td></tr>
                <tr class="2394"><td># 2394</td><td class="v48">48</td><td class="v12">12</td><td class="v7">7</td><td class="v14">14</td><td class="v41">41</td><td class="v21">21</td><td class="v143">143</td><td class="v23.83">23.83</td></tr>
                <tr class="2393"><td># 2393</td><td class="v2">2</td><td class="v14">14</td><td class="v9">9</td><td class="v35">35</td><td class="v22">22</td><td class="v36">36</td><td class="v118">118</td><td class="v19.67">19.67</td></tr>
                <tr class="2392"><td># 2392</td><td class="v37">37</td><td class="v49">49</td><td class="v36">36</td><td class="v52">52</td><td class="v16">16</td><td class="v45">45</td><td class="v235">235</td><td class="v39.17">39.17</td></tr>
                <tr class="2391"><td># 2391</td><td class="v14">14</td><td class="v36">36</td><td class="v2">2</td><td class="v6">6</td><td class="v50">50</td><td class="v26">26</td><td class="v134">134</td><td class="v22.33">22.33</td></tr>              
                </tbody>
            </table>
        </article>
    </section>

Assuming i have the JQuery library linked to the page, what JQuery code grabs the row, analyzes what it matches, then draws a line to those two numbers?

I found this article on how to make lines with JQuery and .js, but i do not know enough .js to fit this to my application. http://www.monkeyandcrow.com/blog/drawing_lines_with_css3/

My thoughts were that i could alter the div,page,&line from the code below to fit my actual table and rows.

var line = $('<div>')
.appendTo('#page')
 .addClass('line')

from this code

function createLine(x1,y1, x2,y2){
    var length = Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
  var angle  = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
  var transform = 'rotate('+angle+'deg)';

    var line = $('<div>')
        .appendTo('#page')
        .addClass('line')
        .css({
          'position': 'absolute',
          'transform': transform
        })
        .width(length)
        .offset({left: x1, top: y1});

    return line;
}

however I'm not sure what they are doing. I did add variable specific class names to the <tr> and <td> to help this. I don't know maybe they are not needed.

Any Ideas of what needs to change to make this auto generate the lines over the table cells?


回答1:


I guess I ended up writing the code for you LOL... it was an interesting puzzle :D

In this demo, you can modify the first few lines as options - target the table, table wrapper, starting & end columns, and distance contains the css class names.

Once all the lines are added to the table, it looks like it was attacked by a spaghetti monster. So I added a little bit of extra code at the bottom to allow hovering over matching lines.

CSS

article {
    position: relative;
}
table, th, td {
    border-collapsed: collapse;
    border: #000 1px solid;
    padding: 3px;
}
.line {
    transform-origin: 0 100%;
    height: 3px;
    border: 0;
}
.blue {
    background-color: blue;
}
.red {
    background-color: red;
}
.black {
    background-color: black;
}

Script

var $table = $('table'),
    $attachLinesTo = $('#dataset-wrap'),
    startColumn = 1,
    endColumn = 6,

    // black = 1 line, blue = 2, red = 3+
    distance = [ 'black', 'blue', 'red' ],

    // adjust line position (pixels)
    xAdj = 0,
    yAdj = 0;

// don't modify anything below
var $rows = $table.children('tbody').children('tr');

function createLine(x1, y1, x2, y2, colorClass) {
    var length = Math.sqrt( ( x1 - x2 ) * ( x1 - x2 ) + ( y1 - y2 ) * ( y1 - y2 ) ),
        angle = Math.atan2( y2 - y1, x2 - x1 ) * 180 / Math.PI;
    return $( '<div>' )
        .appendTo( $attachLinesTo )
        .addClass( 'line ' + colorClass )
        .css({
            position : 'absolute',
            transform : 'rotate(' + angle + 'deg)'
        })
        .width( length )
        .offset({
            left : x1,
            top : y1
        });
}

function getValues() {
    var indx, row, col,
        data = [],
        rowsLen = $rows.length;
    for ( indx = 0; indx < rowsLen; indx++ ) {
        row = [];
        for ( col = startColumn; col <= endColumn; col++ ) {
            // save cell contents for row
            row.push( parseInt( $rows.eq( indx ).children().eq( col ).text(), 10 ) );
        }
        // save row array
        data.push( row );
    }
    return data;
}
function findDuplicates() {
    var indx, row, rowArry, col, val, index,
        array = getValues(),
        len = array.length,
        xref = {};
    for ( row = 0; row < len - 1; row++ ) {
        rowArry = array[ row ];
        for ( col = 0; col < rowArry.length; col++ ) {
            val = rowArry[ col ];
            if ( $.isEmptyObject( xref[ val ] ) ) {
                // each value in the table gets a cross reference with a row & col index
                // (col starts from "startColumn" value, not zero)
                xref[ val ] = { row: [], col: [] };
            }
            for ( indx = row; indx < len; indx++ ) {
                // indexOf (array) not supported in IE8... but neither are css3 transforms
                index = array[ indx ].indexOf( val );
                if ( index > -1 ) {
                    // don't add duplicates in cross reference
                    // *** NOTE *** this will cause issues if two of the same value is in the same row
                    if ( xref[ val ].row.indexOf( indx ) < 0 ) {
                        xref[ val ].row.push( indx );
                        xref[ val ].col.push( index );
                    }
                }
            }
        }
    }
    return xref;
}
function getCoords( row, col ) {
    var $cell = $rows.eq( row ).children().eq( col ),
        width = $cell.width(),
        height = $cell.height(),
        pos = $cell.offset();
    // return x & y pixel coordinates from center of table cell
    return {
        x: pos.left + width/2 + xAdj,
        y: pos.top + height/2 + yAdj
    };
}
function draw() {
    var val, value, indx, len, pos, x, y, color,
        maxDist = distance.length - 1,
        data = findDuplicates();
    for ( val in data ) {
        if ( data[ val ].row ) {
            value = data[ val ];
            len = value.row.length - 1;
            // ignore if value is unique
            if ( len > 0 ) {
                for ( indx = 0; indx < len; indx++ ) {
                    // get line starting position
                    pos = getCoords( value.row[ indx ], value.col[ indx ] + startColumn );
                    x = pos.x;
                    y = pos.y;
                    // get line ending position
                    pos = getCoords( value.row[ indx + 1 ], value.col[ indx + 1 ] + startColumn );
                    // adjust colors... add 1 to index so distance array doesn't need to have "" at the zero index
                    color = distance[ Math.abs( value.row[ indx ] - value.row[ indx + 1 ] + 1 ) ] || distance[ maxDist ];
                    // draw line - add color + cell value for hovering code
                    createLine( x, y, pos.x, pos.y, color + ' ' + color + val );
                }
            }
        }
    }
}
// Initialize draw
draw();
var $lines = $('.line');
// hover over line to isolate it
$('#dataset-wrap').on('mouseover mouseleave', '.line', function(e){
    if ( e.type === 'mouseover' ) {
        // hide all lines except current
        $lines.not(this).hide();
        // find number in class name (e.g. get "9" from "red9")
        var number = this.className.match( /[a-z]+(\d+)/ ),
        // make regular expression to match word + number ( word could be "blue", "black" or "red" from distance value )
        // add \b at end to prevent matching "red26" when we only wanted "red2"
        regex = new RegExp( '[a-z]+' + ( number ? number[1] : '' ) + '\\b' );
        // find matching lines & show
        $lines.filter(function(){
            return regex.test( this.className );
        }).show();
    } else {
        $lines.show();
    }
});

Update: One issue I forgot to mention, but I did add as a comment in the code, is that if a row contains the same number twice, the second value will be ignored.... but this looks like a sort of lottery comparison, so I don't think it'll be a problem.



来源:https://stackoverflow.com/questions/33988943/trying-to-use-jquery-to-draw-lines-over-table-data

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!