Anonymous avatar Anonymous committed fc4af13

Put Ergo's grid helper in unfinished directory.

Comments (0)

Files changed (4)

-WebHelpers
+Untested.)WebHelpers
 ++++++++++++
 
 WebHelpers is package aimed at providing helper functions for use within web applications.

unfinished/grid.py

+from routes.util import url_for
+from pylons import request
+
+class Grid(object):
+    
+    def __init__(self, itemlist, *args, **kwargs):
+        self.default_column_format = '\n\t<td>%s</td>'
+        self.default_row_format = '\n\t<tr class="%s">%s</tr>'
+        self.custom_row_format = None
+        self.default_header_row_format = '\n<tr class="header">\n%s\n</tr>'
+        self.default_header_ordered_column_format = '<td class="column%s ordering %s">%s<span class="marker"></span></td>'
+        self.default_header_column_format = '<td class="column%s">%s</td>'
+        self.default_header_link = '<a href="%s">%s</a>'
+        
+        self.labels = {}
+        self.exclude_ordering = ['_numbered']
+        self.itemlist = itemlist
+        columns = kwargs['columns']
+        if '_numbered' in columns:
+            self.labels['_numbered'] = 'no.'            
+        self.columns = columns
+        if 'format' in kwargs:
+            self.format = kwargs['format']
+        else:
+            self.format = {}
+        if 'start_number' in kwargs:
+            self._start_number = kwargs['start_number']
+        else:
+            self._start_number = 1
+
+    def __make_header_columns(self):
+        header_columns = []
+        request_copy = request.copy()
+        if 'order_by' in request_copy.GET:
+            self.order_column = request_copy.GET.pop('order_by')
+        else:
+            self.order_column = None
+            
+        for i,column in enumerate(self.columns):
+            #lets generate header column contents
+            label_text = ''
+            if column in self.labels:
+                label_text = self.labels[column]
+            else:
+                label_text = column.replace('_', ' ').title()
+            if column not in self.exclude_ordering:
+                if self.order_column and column == self.order_column[0:-4] and self.order_column[-3:] == 'asc':
+                    new_ordering = column + '_dsc'
+                else:
+                    new_ordering = column + '_asc'
+                label_text = self.default_header_link % (url_for(order_by=new_ordering, **request_copy.GET), label_text)
+                #lets test if the column we try to order on is this column
+                if self.order_column and column == self.order_column[0:-4] and self.order_column[-3:] == 'asc':
+                    header_columns.append(self.default_header_ordered_column_format % (i+1,'asc', label_text))
+                elif self.order_column and column == self.order_column[0:-4] and self.order_column[-3:] == 'dsc':
+                    header_columns.append(self.default_header_ordered_column_format % (i+1,'dsc', label_text))
+                else:
+                    header_columns.append(self.default_header_column_format % (i+1,label_text))    
+            else:
+                header_columns.append(self.default_header_column_format % (i+1,label_text))
+        return ''.join(header_columns)
+    
+    def __make_columns(self, i, row):
+        columns = []
+        if '_numbered' in self.columns:
+            columns.append(self.default_column_format % (i + self._start_number))
+            for column in self.columns[1:]:
+                if column in self.format:
+                    pass
+                    columns.append(self.format[column](i, row))
+                else:
+                    columns.append(self.default_column_format % row[column])        
+        else:
+            for i,column in enumerate(self.columns):
+                if column in self.format:
+                    pass
+                    columns.append(self.format[column](i, row))
+                else:
+                    columns.append(self.default_column_format % row[column]) 
+        return ''.join(columns)
+    
+    def render(self):
+        ''' renders the grid '''
+        rows = []
+        #first render headers row
+        rows.append(self.default_header_row_format % self.__make_header_columns())
+        if self.custom_row_format is None:
+            for i, row in enumerate(self.itemlist):
+                if i % 2 == 0:
+                    class_name = 'even'
+                else:
+                    class_name = 'odd'
+                rows.append(self.default_row_format % (class_name,self.__make_columns(i, row)))
+        else:
+            for i, row in enumerate(self.itemlist):
+                if i % 2 == 0:
+                    class_name = 'even'
+                else:
+                    class_name = 'odd'
+                rows.append(self.custom_row_format(class_name,i, row, self.__make_columns(i, row)))
+        return ''.join(rows)

unfinished/grid_notes.txt

+Grid integration plan for WebHelpers
+====================================
+
+The main problem with table generators is that different people want different
+kinds of tables, and you want to try to accommodate them as much as possible,
+without making the simple case too cumbersome.  I'd suggest putting the
+row-number feature in a subclass because many tables won't need it.  
+
+I'd also suggest a subclass or option for a horizontal table: one with the
+headers in the left row.  These are often two-column tables, with the labels
+implied by the first column in the data.  E.g., dumping a dict.
+
+Generate all HTML using webhelpers.html.builder (examples in
+webhelpers.html.tags). This will also mark the HTML as a preformatted literal,
+so Mako's "|n" filter will no longer be necessary.
+
+Replace .render method with .__str__ .  This will make it automatically render
+when stringified, as Mako does with ${my_grid}.
+
+Write complete module docstring with usage and tests.  (See examples in
+webhelpers.html.tags.) Document that this generates only <tr> and below, not
+<table> or <call> etc.
+
+There doesn't seem to be much use for ``*args`` and ``**kwargs`` since you
+accept a small number of arguments with fixed meanings.  I would replace those
+with positional args, with default values for those that are optional.
+'columns' looks like it should be the second arg and required.  Does
+``.__make_header_columns`` work if 'columns' is missing?
+
+Double-underscore method names are unnecessary, because this is unlikely to be
+subclassed except to customize the formatting, and the subclass would not have
+conflicting names.
+
+I don't understand the ordering code, so I'm not sure what it's doing.  
+
+'labels' is ambiguous: is it a column header, form element <label>, row or cell
+label, etc?  Consider 'header' instead.
+
+Interesting that ``.labels`` is a dict rather than a list of headers.  I
+suppose that makes it easier to move columns around.
+
+
+Ergos's original comments from ticket
+=====================================
+
+http://bitbucket.org/bbangert/webhelpers/issue/3/table-from-list-helper
+
+Im,a beginner programmer in python so this may need some improving ;-)
+
+what this class can do:
+
+* ordering support for columns with get params
+* customizable row and column rendering via lambdas, support for adding new columns that dont exist in passed lists like row with links to perform actions,
+* any default column rendering style can be overwritten with something custom
+* rows can be overwritten so user can create something like <tr>columns_row</tr><tr>some_other_info</tr>
+* builtin support for even/odd class styling of rows
+* auto generation of nice headers from keys of sa rows, so something_label becoms Something Label
+* headers have nice styling support with smart class usage, for both ordered and unordered fields
+* support for overwriting any header with something else
+* support to specify what columns are rendered and in what order by columns argument
+* every custom row or column markup is specified by lambda/function that returns formattable string 
+
+the simpliest example usage for mako:
+
+<%
+from webreactor.lib.grid import Grid
+news_grid = Grid(c.news_page,columns=['title','date_of_creation'])
+%>
+
+<table class="stylized"> ${news_grid.render()|n} </table>
+
+more complex examples:
+
+<%
+from webreactor.lib.grid import Grid
+news_grid = Grid(c.news_page,columns=['title','date_of_creation','actions'])
+news_grid.exclude_ordering = news_grid.columns
+news_grid.label = {'title':'Some other title'}
+news_grid.format = {
+'actions':lambda i,item: '<td><a href="%s"><span class="icon newsUpdate"></span></a></td>' % (url())
+}
+%>
+
+<table class="stylized"> ${news_grid.render()|n} </table>
+
Add a comment to this file

unfinished/grid_screenshot.png

Added
New image
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.