0

I've been tasked with unifying date formats of an HTML table that has different databases feeding into it. Utilizing a SQL procedure is not an option. The known truths are the cells in the TBODY will be plain text or plain text wrapped in one link.

I wrote a jQuery plugin that does the job, but I'm wondering if would make sense to do innerHTML versus looping through each TD.

original plugin:

$.fn.reformatAllDates = function () {
  var $txt = $(this).text();

  var reformatDate = function ($str) {
    var $parts = $str.split('/'),
        $year = $parts[2],
        $month = $parts[0],
        $day = $parts[1];
    if ($parts.length === 3) {
      $month = $month.length < 2 ? '0' + $month : $month;
      $day = $day.length < 2 ? '0' + $day : $day;

      //Returns dates in sort friendly format [YYYY-MM-DD]
      return $year + '-' + $month + '-' + $day;
    }
    return $str;
  };

  var $result, $reg = new RegExp(/^\d{1,2}\/\d{1,2}\/\d{4}$/);

  while (($result = $reg.exec($txt)) !== null) {
    var $match = $reg.exec($txt)[0];
    var $newFormat = reformatDate($match);
    $txt = $txt.replace($match, $newFormat);
  }
  return $(this).html($txt);
}

original implementation:

$('table.display tbody tr td').each(function () {
  if ($(this).html().indexOf('href') >= 0)
    $(this).find('a:first').reformatAllDates();
  else
    $(this).reformatAllDates();
});

innerHTML implementation:

$('table.display tbody').reformatAllDates();

This works, though I haven't yet tested how big the innerHTML can be before it fails and prepared the fallback steps in...

$.fn.reformatAllDates = function () {
  var $result, 
      $reg = new RegExp(/\d{1,2}\/\d{1,2}\/\d{4}/),
      $r2 = new RegExp(/[\n\r\f]/g),
      $html = $(this).html();
  $html = $html.replace($r2,'');
  $html = $html.replace($r2,'');

  var reformatDate = function ($str) {
    var $parts = $str.split('/'),
        $year = $parts[2],
        $month = $parts[0],
        $day = $parts[1];
    if ($parts.length === 3) {
      $month = $month.length < 2 ? '0' + $month : $month;
      $day = $day.length < 2 ? '0' + $day : $day;
      return $year + '-' + $month + '-' + $day;
    }
    return $str;
  };

  var $match, $newFormat, $msg;
  while (($result = $reg.exec($html)) !== null) {
    $match = $reg.exec($html)[0];
    $newFormat = reformatDate($match);
    var $re = new RegExp($match,"g");
    $html = $html.replace($re, $newFormat);
  }
  return $(this).html($html);
}
22
  • you can move the td selection and loop into the plugin without changing your method of accessing the data, giving you the "ideal implementation" Commented Apr 6, 2012 at 18:50
  • @Mathletics, i was actually trying to avoid the looping, for instance I already use this on non tables, like Data Definition Lists as well. My logic is thinking if 1000 dates, but only 25 unique dates, doing a regex on the innterHTML would make a lot more sense. but when I try: this, myregex doesn't match at all Commented Apr 7, 2012 at 13:57
  • 1
    I think you might be putting the reformatAllDates() on the wrong element. See: jsfiddle.net/userdude/gkeL6 Commented Apr 7, 2012 at 15:38
  • 1
    Something that might be a little easier to play around with: jsfiddle.net/userdude/gkeL6/2 Commented Apr 7, 2012 at 15:50
  • 1
    And the times seem better for all browsers using $.html() instead of $.text() to set the reformatted date: .9 seconds to reformat in FF, 0.43 in Chrome. Looks like $this.html(formatted date) is the winner at this point. The fiddle in question: jsfiddle.net/userdude/gkeL6/10 Commented Apr 8, 2012 at 13:22

1 Answer 1

1

Below is what I came up with. To understand how I came to the following, read through the comments under the question.

jQuery(document).ready(function($) {
    var reg = new RegExp(/^\d{1,2}\/\d{1,2}\/\d{4}$/);

    $.fn.reformatAllDates = function (subselect) {
        var $this = $(this),
            $nodes,
            $node,
            text,
            matched;

        if (subselect) {
            $nodes = $this.find(subselect);
        } else if ($this.is('table')) {
            $nodes = $this.find('td');
        } else if ($this.is('dl')) {
            $nodes = $this.find('dt, dd');
        } else {
            $nodes = $this.children();
        }

        for (var i = 0, l = $nodes.size(); i < l; i++) {
            $node = $($nodes[i]);
            text = $node.text();
            matched = text.match(/\//g);

            if (matched !== null && matched.length == 2) {
                $node.reformatDate(text);
            }
        }
    };

    $.fn.reformatDate = function(text, parts) {
        var $this = $(this),
            matched,
            year,
            month,
            day;

        if (!parts) {
            text = text ? text : $this.text();
            matched = reg.exec(text);
            parts = matched !== null ? matched[0].split('/') : [];
        }

        if (parts.length === 3) {
            month = parts[0];
            day = parts[1];
            year = parts[2];

            month = month.length < 2 ? '0' + month : month;
            day = day.length < 2 ? '0' + day : day;

            //Returns dates in sort friendly format [YYYY-MM-DD]
            $this.html(year + '-' + month + '-' + day);
        }
    };

    $('#trigger').click(function(){
        $('#tabledata').reformatAllDates();
    });
});

http://jsfiddle.net/userdude/gkeL6/10/

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.