Is there a more efficient way to regex match/replace dates in an HTML table?

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);
}

Answers


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/


Need Your Help

Centralize vendor folder in Laravel 4.1.x

php laravel-4 composer-php directory-structure

I wonder if is possibile to "move" the vendor folder to another location. I mean, I've a structure like this

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.