ImprovedTableParser

Changeset

7:a285ae825ba3
2012-02-19 Paul Boddie raw files shortlog changelog graph Changed the sort controls to be a list of columns, with the selected column appearing as an insertion marker alongside the list where the column could be inserted to change the criteria, and with the column appearing as a link in the list if already part of the criteria, enabling the column to be removed from the criteria. If appropriate, a link permitting the column to be added or moved to the end of the list is also shown.
ImprovedTableParser.py (file)
     1.1 --- a/ImprovedTableParser.py	Sun Feb 19 13:38:53 2012 +0100
     1.2 +++ b/ImprovedTableParser.py	Sun Feb 19 18:48:42 2012 +0100
     1.3 @@ -354,68 +354,113 @@
     1.4  
     1.5          return 0
     1.6  
     1.7 -def write_sort_control(columnnumber, write, sort_columns, column_types, columns, table_name, data_start, start=0):
     1.8 +def write_sort_control(request, columnnumber, fmt, write, sort_columns, column_types, columns, table_name, start=0):
     1.9  
    1.10      """
    1.11 -    Write a sort control in its own form which provides a list of sort
    1.12 -    descriptions, modifying the 'sort_columns' provided by introducing the given
    1.13 -    column in different positions.
    1.14 +    Write a sort control in a pop-up element which provides a list of links
    1.15 +    corresponding to modified sort criteria.
    1.16      """
    1.17  
    1.18 -    option_html = """\
    1.19 -        <option value="%(value)s" %(selected)s>%(label)s</option>
    1.20 -"""
    1.21 +    _ = request.getText
    1.22 +
    1.23 +    write(fmt.div(1, css_class="sortcolumns"))
    1.24  
    1.25      # Start with the existing criteria without this column being involved.
    1.26  
    1.27 -    current_sort_columns = [(column + start, suffixes[fn], not ascending and "d" or "")
    1.28 -        for (column, fn, ascending) in sort_columns]
    1.29 -    revised_sort_columns = [(column + start, suffixes[fn], not ascending and "d" or "")
    1.30 +    revised_sort_columns = [(column, fn, ascending)
    1.31          for (column, fn, ascending) in sort_columns if column != columnnumber]
    1.32 -    values = [revised_sort_columns]
    1.33 -    revised_sort_labels = [columns[column][1].strip() for (column, fn, ascending) in revised_sort_columns]
    1.34 -    labels = [revised_sort_labels]
    1.35 +
    1.36 +    # Get the specification of this column.
    1.37 +
    1.38 +    columnfn, columnascending = column_types.get(columnnumber, (str, True))
    1.39 +    newsortcolumn = columnnumber, columnfn, columnascending
    1.40 +    newlabel = columns[columnnumber][1].strip()
    1.41 +
    1.42 +    # Show this column in all possible places in the sorting criteria.
    1.43  
    1.44 -    # Add this column in all possible places in the sorting criteria.
    1.45 +    write(fmt.number_list(1))
    1.46 +
    1.47 +    already_have_this_column = len(sort_columns) != len(revised_sort_columns)
    1.48 +    just_had_this_column = False
    1.49 +
    1.50 +    for i, (column, fn, ascending) in enumerate(sort_columns):
    1.51 +        new_sort_columns = revised_sort_columns[:]
    1.52 +        new_sort_columns.insert(i, newsortcolumn)
    1.53 +        label = columns[column][1].strip()
    1.54  
    1.55 -    i = 0
    1.56 -    while i <= len(revised_sort_columns):
    1.57 -        value = revised_sort_columns[:]
    1.58 -        label = revised_sort_labels[:]
    1.59 -        fn, ascending = column_types.get(columnnumber, (str, True))
    1.60 -        value.insert(i, (columnnumber + start, suffixes[fn], not ascending and "d" or ""))
    1.61 -        label.insert(i, columns[columnnumber][1].strip())
    1.62 -        values.append(value)
    1.63 -        labels.append(label)
    1.64 -        i += 1
    1.65 +        # Pop-up element showing the column inserted before the sort column.
    1.66 +
    1.67 +        if column != columnnumber and not just_had_this_column:
    1.68 +            write(fmt.listitem(1, css_class="sortcolumn"))
    1.69 +
    1.70 +            write(fmt.span(1, css_class="sortcolumn-container"))
    1.71 +            write(fmt.span(1, css_class="newsortcolumn"))
    1.72 +            write(fmt.text(newlabel))
    1.73 +            write(fmt.span(0))
    1.74 +            write(fmt.span(0))
    1.75  
    1.76 -    # Make the list of options.
    1.77 +            # Link for selection of the modified sort criteria.
    1.78 +
    1.79 +            write(fmt.url(1, "?%s-sortcolumns=%s" % (table_name, get_sort_column_output(new_sort_columns))))
    1.80 +            write(fmt.text(label))
    1.81 +            write(fmt.url(0))
    1.82 +
    1.83 +        else:
    1.84 +            write(fmt.listitem(1))
    1.85 +
    1.86 +            # Either show the column without a link, since the column to be
    1.87 +            # inserted is already before the current column.
    1.88  
    1.89 -    options_html = []
    1.90 -    for value, label in zip(values, labels):
    1.91 -        options_html.append(option_html % {
    1.92 -            "value"     : ",".join([("%d%s%s" % spec) for spec in value]),
    1.93 -            "label"     : ", ".join(label),
    1.94 -            "selected"  : value == current_sort_columns and 'selected="selected"' or "",
    1.95 -            })
    1.96 +            if just_had_this_column:
    1.97 +                just_had_this_column = False
    1.98 +                write(fmt.span(1, css_class="unlinkedcolumn"))
    1.99 +                write(fmt.text(label))
   1.100 +                write(fmt.span(0))
   1.101 +
   1.102 +            # Or show the column with a link for its removal.
   1.103  
   1.104 -    # Write the form.
   1.105 +            else:
   1.106 +                just_had_this_column = True
   1.107 +                write(fmt.url(1, "?%s-sortcolumns=%s" % (table_name, get_sort_column_output(revised_sort_columns)),
   1.108 +                    css_class="removecolumn"))
   1.109 +                write(fmt.text(label))
   1.110 +                write(fmt.url(0))
   1.111 +
   1.112 +        write(fmt.listitem(0))
   1.113 +
   1.114 +    if not already_have_this_column:
   1.115 +
   1.116 +        # Write the sorting criteria with this column at the end.
   1.117 +
   1.118 +        new_sort_columns = revised_sort_columns[:]
   1.119 +        new_sort_columns.append(newsortcolumn)
   1.120  
   1.121 -    d = {
   1.122 -        "table_name"    : table_name,
   1.123 -        "options"       : "".join(options_html),
   1.124 -        "data_start"    : data_start,
   1.125 -        }
   1.126 +        write(fmt.listitem(1, css_class="sortcolumn", style="list-style-type: none"))
   1.127 +
   1.128 +        # Pop-up element showing the column inserted before the sort column.
   1.129 +
   1.130 +        write(fmt.span(1, css_class="sortcolumn-container"))
   1.131 +        write(fmt.span(1, css_class="newsortcolumn"))
   1.132 +        write(fmt.text(newlabel))
   1.133 +        write(fmt.span(0))
   1.134 +        write(fmt.span(0))
   1.135  
   1.136 -    write("""\
   1.137 -<form method="post">
   1.138 -    <input name="tablename" value="%(table_name)s" type="hidden" />
   1.139 -    <input name="%(table_name)s-headers" value="%(data_start)s" type="hidden" />
   1.140 -    <select name="%(table_name)s-sortcolumns" onchange="this.form.submit()">
   1.141 -%(options)s
   1.142 -    </select>
   1.143 -</form>
   1.144 -""" % d)
   1.145 +        write(fmt.url(1, "?%s-sortcolumns=%s" % (table_name, get_sort_column_output(new_sort_columns))))
   1.146 +        write(fmt.text(_("...")))
   1.147 +        write(fmt.url(0))
   1.148 +
   1.149 +        write(fmt.listitem(0))
   1.150 +
   1.151 +    write(fmt.number_list(0))
   1.152 +
   1.153 +    write(fmt.div(0))
   1.154 +
   1.155 +def get_sort_column_output(columns, start=0):
   1.156 +
   1.157 +    "Return the output criteria for the given 'columns' indexed from 'start'."
   1.158 +
   1.159 +    return ",".join([("%d%s%s" % (column + start, suffixes[fn], not ascending and "d" or ""))
   1.160 +        for (column, fn, ascending) in columns])
   1.161  
   1.162  # Sorting-related tables.
   1.163  
   1.164 @@ -471,21 +516,26 @@
   1.165  
   1.166      # Write the table.
   1.167  
   1.168 -    writing_html = request.page.output_mimetype == "text/html"
   1.169      write = request.write
   1.170      write(fmt.table(1, table_attrs))
   1.171  
   1.172      for rownumber, (row_attrs, columns) in enumerate(table):
   1.173          write(fmt.table_row(1, row_attrs))
   1.174 +        sortable = sortcolumns and rownumber == data_start - 1
   1.175  
   1.176          for columnnumber, (column_attrs, column_text) in enumerate(columns):
   1.177              write(fmt.table_cell(1, column_attrs))
   1.178 +
   1.179 +            if sortable:
   1.180 +                write(fmt.div(1, css_class="sortablecolumn"))
   1.181 +
   1.182              write(formatText(column_text, request, fmt))
   1.183  
   1.184              # Add sorting controls, if appropriate.
   1.185  
   1.186 -            if writing_html and sortcolumns and rownumber == data_start - 1:
   1.187 -                write_sort_control(columnnumber, write, sort_columns, column_types, columns, table_name, data_start)
   1.188 +            if sortable:
   1.189 +                write_sort_control(request, columnnumber, fmt, write, sort_columns, column_types, columns, table_name)
   1.190 +                write(fmt.div(0))
   1.191  
   1.192              write(fmt.table_cell(0))
   1.193