10
\$\begingroup\$

I've wrote this CoffeScript function to compare values in a table, but it turned out to be a HUGE function.

Since the code is really really long, you can find it here as well.

Code explanation:

The code searches for all the values in a dynamically created datatable and appends the comparison values in another column, Moreover, I had to clone the same statements (because the number of columns is different based on window size) to get it to work on mobile as well.

Is there any way I can reduce the size of this function?

  comparekeys = ->
    if $("#keys tbody tr").length > 1 
      $.expr[":"].exactly = (e, i, m) ->
        $(e).text() is m[3]
      $("#keys tbody tr td:nth-child(2):exactly(0)").html ""
      $("#keys tbody tr").each(->
        width = $(window).width()
        if width > 1025
          a = Number($(this).find("td")[1].innerHTML)
          b = Number($(this).find("td")[3].innerHTML)
          c = Number($(this).find("td")[4].innerHTML)
          d = Number($(this).find("td")[5].innerHTML)
          changes = $(this).find("td:eq(2)")
          row1 = $(this).find("td:eq(1)")
          row2 = $(this).find("td:eq(3)")
          row3 = $(this).find("td:eq(4)")
          row4 = $(this).find("td:eq(5)")
          css = 'color':'white', 'cursor':'default'
          notranking = "<span rel='tooltip' title='Never Ranked' class='notranking'> <b>Not Ranking</b> </span>"
          notranking_today = "<span rel='tooltip' title='Compared with today' class='notranking'> <b>Not Ranking</b> </span>"
          sortboxarrowup = "sortboxup fa fa-arrow-up"
          sortboxarrowdown = "sortboxdown fa fa-arrow-down"
          sortboxbarseq = "sortboxeq fa fa-bars"
          $("[rel=tooltip]").tooltip placement: "top"
          $("#keys > tbody > tr > td.sorting_1 > a").attr
            rel: "tooltip"
            title: "View keyword data"  
          if a is 0
            if b > 0
              $("<span class='dropped' rel='tooltip' title='Compared with yesterday'> <b>Dropped</b> </span>").addClass("sortboxdrop").css(css).appendTo(row1)
            else
              $("<span rel='tooltip' title='Compared with yesterday' class='notranking'> <b>Not Ranking</b> </span>").addClass("sortboxeq").css(css).appendTo(row1)            
          # else if a > 0 && b is 0 && c is 0 && d is 0
            # $("<span rel='tooltip' title='Started Ranking' class='today'> <b>new</b> </span>").addClass("sortboxnew").css(css).appendTo(row1)  
          if a > b && b > 0
            $("<span rel='tooltip' title='Decreased' class='yesterday'> <b>#{a - b}</b> </span>").addClass(sortboxarrowdown).css(css).appendTo(changes)
          else if a > b && b is 0
            $("<span rel='tooltip' title='Started Ranking' class='yesterday'> <b>new</b> </span>").addClass("sortboxnew").css(css).appendTo(changes)
          else if a < b && a is 0 && b > 0
            $("<span class='yesterday' rel='tooltip' title='Dropped'> <b>Dropped</b> </span>").addClass("sortboxdrop").css(css).appendTo(changes)
          else if a < b
            $("<span rel='tooltip' title='Increased' class='yesterday'> <b>#{b - a}</b> </span>").addClass(sortboxarrowup).css(css).appendTo(changes)
          else if a is b
            $("<span rel='tooltip' title='No Change' class='yesterday'>  </span>").addClass(sortboxbarseq).css(css).appendTo(changes)                    
          $("select[name=keycompare]").change ->
            $("[rel=tooltip]").tooltip placement: "top" 
            if $(this).val() is "1" 
              $(changes).empty() 
              if a > b && b > 0
                $("<span rel='tooltip' title='Decreased' class='yesterday'> <b>#{a - b}</b> </span>").addClass(sortboxarrowdown).css(css).appendTo(changes)
              else if a > b && b is 0
                $("<span rel='tooltip' title='Started Ranking' class='yesterday'> <b>new</b> </span>").addClass("sortboxnew").css(css).appendTo(changes)
              else if a < b && a is 0 && b > 0
                $("<span class='yesterday' rel='tooltip' title='Dropped'> <b>Dropped</b> </span>").addClass("sortboxdrop").css(css).appendTo(changes)
              else if a < b
                $("<span rel='tooltip' title='Increased' class='yesterday'> <b>#{b - a}</b> </span>").addClass(sortboxarrowup).css(css).appendTo(changes)
              else if a is b
                $("<span rel='tooltip' title='No Change' class='yesterday'>  </span>").addClass(sortboxbarseq).css(css).appendTo(changes)
            if $(this).val() is "2"
              $(changes).empty()  
              if a > c && c > 0
                $("<span rel='tooltip' title='Decreased' class='lastweek'> <b>#{a - c}</b> </span>").addClass(sortboxarrowdown).css(css).appendTo(changes)
              else if a > c && c is 0
                $("<span rel='tooltip' title='Started Ranking' class='lastweek'> <b>new</b> </span>").addClass("sortboxnew").css(css).appendTo(changes)
              else if a < c && a is 0 && c > 0
                $("<span class='lastweek' rel='tooltip' title='Dropped'> <b>Dropped</b> </span>").addClass("sortboxdrop").css(css).appendTo(changes)
              else if a < c
                $("<span rel='tooltip' title='Increased' class='lastweek'> <b>#{c - a}</b> </span>").addClass(sortboxarrowup).css(css).appendTo(changes)
              else if a is c
                $("<span rel='tooltip' title='No Change' class='lastweek'>  </span>").addClass(sortboxbarseq).css(css).appendTo(changes)
            if $(this).val() is "3"
              $(changes).empty() 
              if a > d && d > 0
                $("<span rel='tooltip' title='Decreased' class='lastmonth'> <b>#{a - d}</b> </span>").addClass(sortboxarrowdown).css(css).appendTo(changes)
              else if a > d && d is 0
                $("<span rel='tooltip' title='Started Ranking' class='lastmonth'> <b>new</b> </span>").addClass("sortboxnew").css(css).appendTo(changes)
              else if a < d && a is 0 && d > 0
                $("<span class='lastmonth' rel='tooltip' title='Dropped'> <b>Dropped</b> </span>").addClass("sortboxdrop").css(css).appendTo(changes)
              else if a < d
                $("<span rel='tooltip' title='Increased' class='lastmonth'> <b>#{d - a}</b> </span>").addClass(sortboxarrowup).css(css).appendTo(changes)
              else if a is d
                $("<span rel='tooltip' title='No Change' class='lastmonth'>  </span>").addClass(sortboxbarseq).css(css).appendTo(changes) 
          return

        else if width < 1025 && width > 481
          $("select[name=keycompare] option[value='3']").remove();
          a = Number($(this).find("td")[1].innerHTML)
          b = Number($(this).find("td")[3].innerHTML)
          c = Number($(this).find("td")[4].innerHTML)
          row1 = $(this).find("td:eq(1)")
          changes = $(this).find("td:eq(2)")
          row2 = $(this).find("td:eq(3)")
          row3 = $(this).find("td:eq(4)")
          css = 'color':'white', 'cursor':'default'
          notranking = "<span rel='tooltip' title='Never Ranked' class='notranking'> <b>Not Ranking</b> </span>"
          notranking_today = "<span rel='tooltip' title='Compared with today' class='notranking'> <b>Not Ranking</b> </span>"
          sortboxarrowup = "sortboxup fa fa-arrow-up"
          sortboxarrowdown = "sortboxdown fa fa-arrow-down"
          sortboxbarseq = "sortboxeq fa fa-bars"
          $("[rel=tooltip]").tooltip placement: "top"
          $("#keys > tbody > tr > td.sorting_1 > a").attr
            rel: "tooltip"
            title: "View keyword data"  
          if a is 0
            if b > 0
              $("<span class='dropped' rel='tooltip' title='Compared with yesterday'> <b>Dropped</b> </span>").addClass("sortboxdrop").css(css).appendTo(row1)
            else
              $("<span rel='tooltip' title='Compared with yesterday' class='notranking'> <b>Not Ranking</b> </span>").addClass("sortboxeq").css(css).appendTo(row1)            
          # else if a > 0 && b is 0 && c is 0 && d is 0
            # $("<span rel='tooltip' title='Started Ranking' class='today'> <b>new</b> </span>").addClass("sortboxnew").css(css).appendTo(row1)  
          if a > b && b > 0
            $("<span rel='tooltip' title='Decreased' class='yesterday'> <b>#{a - b}</b> </span>").addClass(sortboxarrowdown).css(css).appendTo(changes)
          else if a > b && b is 0
            $("<span rel='tooltip' title='Started Ranking' class='yesterday'> <b>new</b> </span>").addClass("sortboxnew").css(css).appendTo(changes)
          else if a < b && a is 0 && b > 0
            $("<span class='yesterday' rel='tooltip' title='Dropped'> <b>Dropped</b> </span>").addClass("sortboxdrop").css(css).appendTo(changes)
          else if a < b
            $("<span rel='tooltip' title='Increased' class='yesterday'> <b>#{b - a}</b> </span>").addClass(sortboxarrowup).css(css).appendTo(changes)
          else if a is b
            $("<span rel='tooltip' title='No Change' class='yesterday'>  </span>").addClass(sortboxbarseq).css(css).appendTo(changes)                    
          $("select[name=keycompare]").change ->
            $("[rel=tooltip]").tooltip placement: "top" 
            if $(this).val() is "1" 
              $(changes).empty() 
              if a > b && b > 0
                $("<span rel='tooltip' title='Decreased' class='yesterday'> <b>#{a - b}</b> </span>").addClass(sortboxarrowdown).css(css).appendTo(changes)
              else if a > b && b is 0
                $("<span rel='tooltip' title='Started Ranking' class='yesterday'> <b>new</b> </span>").addClass("sortboxnew").css(css).appendTo(changes)
              else if a < b && a is 0 && b > 0
                $("<span class='yesterday' rel='tooltip' title='Dropped'> <b>Dropped</b> </span>").addClass("sortboxdrop").css(css).appendTo(changes)
              else if a < b
                $("<span rel='tooltip' title='Increased' class='yesterday'> <b>#{b - a}</b> </span>").addClass(sortboxarrowup).css(css).appendTo(changes)
              else if a is b
                $("<span rel='tooltip' title='No Change' class='yesterday'>  </span>").addClass(sortboxbarseq).css(css).appendTo(changes)
            if $(this).val() is "2"
              $(changes).empty()  
              if a > c && c > 0
                $("<span rel='tooltip' title='Decreased' class='lastweek'> <b>#{a - c}</b> </span>").addClass(sortboxarrowdown).css(css).appendTo(changes)
              else if a > c && c is 0
                $("<span rel='tooltip' title='Started Ranking' class='lastweek'> <b>new</b> </span>").addClass("sortboxnew").css(css).appendTo(changes)
              else if a < c && a is 0 && c > 0
                $("<span class='lastweek' rel='tooltip' title='Dropped'> <b>Dropped</b> </span>").addClass("sortboxdrop").css(css).appendTo(changes)
              else if a < c
                $("<span rel='tooltip' title='Increased' class='lastweek'> <b>#{c - a}</b> </span>").addClass(sortboxarrowup).css(css).appendTo(changes)
              else if a is c
                $("<span rel='tooltip' title='No Change' class='lastweek'>  </span>").addClass(sortboxbarseq).css(css).appendTo(changes)
          return
        else if width < 481
          $("select[name=keycompare]").remove(); 
          $(".remove-mob").remove();
      )          
    return
\$\endgroup\$
0
13
\$\begingroup\$

You don't seem to have a representation of your table as data, just in the DOM. That's making this a really cumbersome job. This will be more legible if you follow the Rule of Representation. Represent your table as an array of objects. Make judgements about those objects based on their properties, and then render them as DOM elements.

It should go something like this:

Get your rows as data.

# these can come from an api, database, or wherever they're coming from now
rows = [
  {today: 1, yesterday: 0, started: 0}
  {today: 2, yesterday: 4, started: 1}
  # ... etc
]

Add properties you need for rendering to the rows.

computeChange = (row) ->
  [a, b] = [row.today, row.yesterday]

  if a > b and b > 0
    'decreased'
  else if a > b and b is 0
    'new'
  else if a < b and a is 0 and b > 0
    'dropped'
  else if a < b
    'increased'
  else if a is b
    'same'

# add a "change" property to each row for use in rendering
row.change = computeChange(row) for row in rows

You can add css classes in a similar fashion.

cssClasses =
  decreased: 'sortboxdown fa fa-arrow-down'
  same: 'sortboxeq fa fa-bars'
  # ... etc

row.className = cssClasses[row.change] for row in rows

Once every row have enough information to be rendered, pass the to something that draws rows.

renderRow = (row) ->
  $("<span></span>").attr
    'rel': 'tooltip'
    'title': row.title
    'class': row.className

$('body').append (renderRow row for row in rows)

Delegate events to an element that contains everything you drew

$('body').on 'change', 'select[name=keycompare]', (event) ->
  # event handling code here

Styling that you want on every element should be added to the document, not each element.

<!-- in <head> -->
<style type="text/css">
  td {
    color: white;
    cursor: default;
  }
</style>
\$\endgroup\$
1
  • 5
    \$\begingroup\$ Welcome to code review with this great answer. \$\endgroup\$
    – chillworld
    May 21 '14 at 18:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.