Index: htdocs/js/ticketchangesets.js
===================================================================
--- htdocs/js/ticketchangesets.js	(revision 0)
+++ htdocs/js/ticketchangesets.js	(revision 0)
@@ -0,0 +1,31 @@
+jQuery(document).ready(function($) {
+    var separator = " ";
+    function recalculate_output(inputs) {
+        var div = $('.ticketchangesets');
+        var container = $('#selectedtickets');
+        if (!container.length) {
+            div.append('<div id="selectedtickets"></div>');
+            container = $('#selectedtickets');
+        }
+        var content = ""
+        inputs.each(function(index, item) {
+            console.log(item.checked);
+            if (item.checked) {
+                var td = $(item).parent('td').next('td');
+                var data = td.find('a').text().replace(/[\[\]]+/g, "");
+                content += separator + data;
+            }
+        });
+        if (content) {
+            container.html("Selected changesets: " + content);
+        }
+    }
+    
+    var inputs = $('.ticketchangesets input[type=checkbox]');
+    inputs.click(function(e) {
+        if (this.id == "all") {
+            inputs.attr('checked', this.checked)
+        }
+        recalculate_output(inputs);
+    });
+}); 
Index: setup.py
===================================================================
--- setup.py	(revision 10745)
+++ setup.py	(working copy)
@@ -43,7 +43,8 @@
     package_data = {
         'ticketchangesets': [
             'locale/*.*',
-            'locale/*/LC_MESSAGES/*.mo'
+            'locale/*/LC_MESSAGES/*.mo',
+            'htdocs/js/*.js'
         ],
     },
     
Index: ticketchangesets/admin.py
===================================================================
--- ticketchangesets/admin.py	(revision 10745)
+++ ticketchangesets/admin.py	(working copy)
@@ -23,6 +23,7 @@
 # ----------------------------------------------------------------------------
 
 import re
+import pytz
 
 from trac.admin import IAdminCommandProvider
 from trac.core import *
@@ -146,12 +147,12 @@
             cursor.execute('SELECT ticket FROM ticket_changesets')
             for tkt_id, in cursor:
                 csets = TicketChangesets(self.env).get(tkt_id)
-                for (reponame, changesets) in csets:
-                    r[tkt_id] = changesets.list_revs(reponame)
+                for (repo, changesets) in csets:
+                    r[tkt_id] = changesets.list_revs(repo)
         else:
             csets = TicketChangesets(self.env).get(tkt_id)
-            for (reponame, changesets) in csets:
-                r[tkt_id] = changesets.list_revs(reponame)
+            for (repo, changesets) in csets:
+                r[tkt_id] = changesets.list_revs(repo)
         if r:
             for tkt_id, revs in r.iteritems():
                 printout('#%s: %s' % (tkt_id, ','.join(revs)))
@@ -183,10 +184,9 @@
             return row and int(row[0]) or 0
         
         for repos in repositories:
-            rev_start = repos.get_changeset(repos.get_oldest_rev())
-            rev_end = repos.get_changeset(repos.get_youngest_rev())
-            changesets = repos.get_changesets(rev_start.date, rev_end.date)
-            i = 1
+            date_start = repos.get_changeset(repos.get_oldest_rev()).date
+            date_end = datetime.utcnow().replace(tzinfo = pytz.utc)
+            changesets = repos.get_changesets(date_start, date_end)
             for changeset in changesets:        
                 tickets = ticket_updater.parse_message(changeset.message)
                 match = False
@@ -256,4 +256,4 @@
             printout('%d messages reformatted' % n_matches[0])
         else:
             printout('%d messages to be reformatted' % n_matches[0])
-            
\ No newline at end of file
+            
Index: ticketchangesets/api.py
===================================================================
--- ticketchangesets/api.py	(revision 10745)
+++ ticketchangesets/api.py	(working copy)
@@ -92,7 +92,7 @@
         for repo in sorted(repos, key=lambda r: r.reponame):
             c = self._read(tkt_id, repo.id)
             if c.exists:
-                changesets.append((repo.reponame, c))
+                changesets.append((repo, c))
         return changesets
 
 
@@ -115,11 +115,21 @@
                     self.revs = []
         else:
             self.revs = []
+            
+    def _shorten_rev(self, repo, r):
+        if hasattr(repo, 'short_rev'):
+            return repo.short_rev(r)
+        return r
 
+    def _pretty_rev(self, repo, r):
+        if hasattr(repo, 'display_rev'):
+            return repo.display_rev(r)
+        return r
+
     def __str__(self):
         return ','.join([str(r) for r in self.revs])
 
-    def get_compact(self):
+    def get_compact(self, repo):
         """Returns a compacted sequence of revisions.
         
         Example: 1,2,3,5,6,7 compacts to 1-3,5-7
@@ -128,12 +138,13 @@
         m = len(self.revs)
         a = self.revs[0]
         i = 1
-        while i <= m:
-            if i == m or self.revs[i-1]+1 < self.revs[i]:
-                if a == self.revs[i-1]:
+
+        while i <= m:            
+            if i == m or int(self._shorten_rev(repo, self.revs[i - 1])) + 1 < int(self._shorten_rev(repo, self.revs[i])):
+                if a == self.revs[i - 1]:
                     c += [a]
                 else:
-                    c += ["%s-%s" % (a, self.revs[i-1])]
+                    c += ["%s-%s" % (self._shorten_rev(repo, a), self._shorten_rev(repo, self.revs[i - 1]))]
                 if i < m:
                     a = self.revs[i]
             i += 1
@@ -150,31 +161,54 @@
         except:
             pass
 
-    def list_revs(self, reponame):
+    def list_revs(self, repo):
         """Make list of revisions for a given repo"""
         r = self.revs
-        if reponame and reponame != '(default)':
-            return ['%s/%s' % (c, reponame) for c in r]
+        if repo.reponame and repo.reponame != '(default)':
+            return ['%s/%s' % (c, repo.reponame) for c in r]
         else:
             return ['%s' % c for c in r]
 
-    def wiki_revs(self, reponame, compact):
+    def wiki_revs(self, repo, compact, full):
         """Make wiki text of revisions for a given repo"""
         if compact:
-            r = self.get_compact()
+            revs = self.get_compact(repo)
         else:
-            r = self.revs
-        if reponame and reponame != '(default)':
-            return ' '.join(['[%s/%s]' % (c, reponame) for c in r])
+            revs = self.revs
+            revs = sorted(revs, key=lambda rev: repo.get_changeset(rev).date)
+        
+        repos_is_default = repo.reponame and repo.reponame != '(default)'
+        revisions = []
+        if full:
+            revisions.append('{{{#!table class="wiki listing" style="margin-top: 0;"')
+            revisions.append("{{{#!th\n{{{#!html\n<input type=checkbox id=all>\n}}}\n}}}")
+            revisions.append('||= Changeset =||= Branch =||= Message =||')
+        for rev in revs:
+            pretty_rev = self._pretty_rev(repo, rev)
+            if repos_is_default:
+                rev_part = "[%s/%s]" % (pretty_rev, repo.reponame)
+            else:
+                rev_part = "[%s]" % (pretty_rev)
+
+            if full:
+                changeset = repo.get_changeset(rev)
+                revisions.append("{{{#!td\n{{{#!html\n<input type='checkbox'>\n}}}\n}}}")
+                revisions.append('|| %s || %s || %s ||' % (rev_part, changeset.branch, changeset.message.split("\n")[0]))
+            else:
+                revisions.append(rev_part)
+        if full:
+            revisions.append('}}}')
+            separator = "\n"
         else:
-            return ' '.join(['[%s]' % c for c in r])
+            separator = " "
+        return separator.join(revisions)
 
-    def wiki_log(self, reponame):
+    def wiki_log(self, repo):
         """Make wiki text of link to revision log for given repo"""
-        if reponame and reponame != '(default)':
-            return '[log:%s@%s %s/%s]' % (reponame, ','.join([str(r) for r in
-                   self.get_compact()]), _("Revision Log"), reponame)
+        if repo.reponame and repo.reponame != '(default)':
+            return '[log:%s@%s %s/%s]' % (repo.reponame, ','.join([str(self._shorten_rev(repo, r)) for r in
+                   self.revs]), _("Revision Log"), repo.reponame)
         else:
-            return '[log:@%s %s]' % (','.join([str(r) for r in
-                                     self.get_compact()]),
+            return '[log:@%s %s]' % (','.join([str(self._shorten_rev(repo, r)) for r in
+                                     self.revs]),
                                      _("Revision Log"))
Index: ticketchangesets/web_ui.py
===================================================================
--- ticketchangesets/web_ui.py	(revision 10745)
+++ ticketchangesets/web_ui.py	(working copy)
@@ -14,6 +14,9 @@
 #     http://trac-hacks.org/wiki/CloneTicketPlugin
 # ----------------------------------------------------------------------------
 
+import pkg_resources
+import re
+
 from genshi.builder import tag
 from genshi.filters import Transformer
 
@@ -23,7 +26,8 @@
 from trac.util.compat import any
 from trac.versioncontrol import RepositoryManager
 from trac.versioncontrol.web_ui.changeset import ChangesetModule
-from trac.web.api import ITemplateStreamFilter
+from trac.web.api import ITemplateStreamFilter, IRequestFilter
+from trac.web.chrome import add_script, ITemplateProvider
 from trac.wiki.formatter import format_to_html, format_to_oneliner
 from trac.wiki.macros import WikiMacroBase
 
@@ -68,6 +72,10 @@
         """Make compact presentation of revision ranges, for example ![1-3]
         instead of ![1] ![2] ![3].""")
         
+    full = BoolOption('ticket-changesets', 'full', 'false',
+        """Show complete information about changesets instead of just the 
+        revision ranges/numbers""")
+        
     showrevlog = BoolOption('ticket-changesets', 'showrevlog', 'true',
         """Show 'Revision Log' link after revisions range.""")
     
@@ -75,11 +83,25 @@
         """Hide section on ticket page when no changesets relates to the
         ticket.""")
     
-    implements(ITemplateStreamFilter)
-
+    implements(ITemplateStreamFilter, IRequestFilter, ITemplateProvider)
+	
     def __init__(self):
         init_translation(self.env.path)
 
+    def get_htdocs_dirs(self):
+        return [('ticketchangesets', pkg_resources.resource_filename(__name__, 'htdocs'))]
+        
+    def get_templates_dirs(self):
+        return []
+
+    def pre_process_request(self, req, handler):
+ 	    return handler
+        
+    def post_process_request(self, req, template, data, content_type):
+        if req.path_info.startswith('/ticket'):
+            add_script(req, 'ticketchangesets/js/ticketchangesets.js')
+        return (template, data, content_type)
+
     # ITemplateStreamFilter methods
 
     def filter_stream(self, req, method, filename, stream, data):
@@ -99,9 +121,10 @@
     def _render(self, req, ticket, exists):
         if exists:
             message = self.changesets.format()
+            id = self.full and "changelog-full" or "changelog"
             return tag.div(tag.h2(_("Repository Changesets"),
                                   class_='foldable'),
-                           tag.div(message, id='changelog'),
+                           tag.div(message, id=id),
                            class_=self.collapsed and 'collapsed')
         else:
             message = _("(none)")
@@ -119,8 +142,9 @@
         self.context = context
         self.tkt_id = tkt_id
         self.hint = hint
-        self.compact =  env.config.getbool('ticket-changesets', 'compact')
-        self.showrevlog =  env.config.getbool('ticket-changesets', 'showrevlog')        
+        self.full = env.config.getbool('ticket-changesets', 'full')
+        self.compact = env.config.getbool('ticket-changesets', 'compact')
+        self.showrevlog = env.config.getbool('ticket-changesets', 'showrevlog')        
         self.changesets = TicketChangesets(env).get(tkt_id)
 
     def exists(self):
@@ -135,23 +159,31 @@
             return
         n = len(self.changesets)
         ix = 0 # current index for adding separation markers between repos
-        for (reponame, changesets) in self.changesets:
+        for (repo, changesets) in self.changesets:
             if n > 1:
                 if self.hint == 'ticket':
-                    if reponame and reponame != '(default)':
-                        yield tag.h3(reponame, class_='change')
+                    if repo.reponame and repo.reponame != '(default)':
+                        yield tag.h3(repo.reponame, class_='change')
                     else:
                         yield tag.h3(_("Default Repository"), class_='change')
                 elif ix > 0:
                     yield ', '
-            revs = changesets.wiki_revs(reponame, self.compact)
-            message = revs
+            
+            revs = changesets.wiki_revs(repo, self.compact, self.full)
+            log = None
             if self.showrevlog:
-                log = changesets.wiki_log(reponame, self.showrevlog)            
-                message += ' (' + log + ')'
-            yield tag.span(format_to_oneliner(self.env, self.context, message,
+                log = changesets.wiki_log(repo)
+            content = ""
+            content += revs
+            if self.showrevlog:
+                content += "\n^" + changesets.wiki_log(repo) + "^"
+            if self.full:
+                yield tag.div(format_to_html(self.env, self.context, content),
+                               class_='ticketchangesets')
+            else:
+                yield tag.span(format_to_oneliner(self.env, self.context, content,
                                               shorten=False),
-                           class_='ticketchangesets')  
+                               class_='ticketchangesets')  
             ix += 1
 
 
