Edgewall Software

Ticket #2647: select-or-ticket-2647-r8675.patch

File select-or-ticket-2647-r8675.patch, 7.0 KB (added by ebray, 3 years ago)

This patch takes a different approach from the "disable-or" patch. It replaces the "Or" button with a select, similar to the one for adding a new filter. So now, creating a new clause always creates one with at least one filter, on the selected field. This patch also incorporates the fix-separator patch.

  • trac/ticket/query.py

     
    953953                        index = int(match.group(2)) 
    954954                    remove_constraints[k[10:match.end(1)]] = index 
    955955             
    956             # Get constraints from form fields, and add a coonstraint if 
     956            # Get constraints from form fields, and add a constraint if 
    957957            # requested for clients without JavaScript 
    958958            add_num = None 
    959959            constraints = {} 
     
    992992                    clause = constraints.setdefault(clause_num, {}) 
    993993                    clause.setdefault(field, []).extend(vals) 
    994994            if add_num is not None: 
    995                 field = req.args.get('add_filter_' + add_num) 
     995                field = req.args.get('add_filter_' + add_num, 
     996                                     req.args.get('add_clause_' + add_num)) 
    996997                if field: 
    997998                    clause = constraints.setdefault(int(add_num), {}) 
    998999                    modes = Query.get_modes().get(fields[field]['type']) 
     
    10091010                clauses[-1].setdefault(field, []).append(val) 
    10101011        clauses = filter(None, clauses) 
    10111012         
    1012         # Add a new empty clause for non-JavaScript clients if requested 
    1013         if req is not None and req.args.get('add_clause'): 
    1014             clauses.append({}) 
    1015          
    10161013        return clauses 
    10171014 
    10181015    def display_html(self, req, query): 
  • trac/ticket/templates/query.html

     
    122122                    </tr> 
    123123                  </tbody> 
    124124 
    125                   <tbody py:with="last_clause = clause_num == len(clauses) - 1"> 
     125                  <tbody py:with="last_clause = clause_num == (len(clauses) or 1) - 1"> 
    126126                    <tr class="actions"> 
    127127                      <td class="and" colspan="2"> 
    128128                        &nbsp;<label for="add_filter_${clause_num}">And</label>&nbsp; 
     
    132132                                  value="$field_name" 
    133133                                  disabled="${(field.type in ('radio', 'checkbox', 'id') and 
    134134                                               field_name in constraints and 
    135                                                len(constraints[field_name])) or None}">${fields[field_name].label}</option> 
     135                                               len(constraints[field_name])) or None}">${field.label}</option> 
    136136                        </select> 
    137137                        <div class="inlinebuttons"> 
    138138                          <input type="submit" name="add_${clause_num}" value="+" /> 
    139139                        </div> 
    140140                      </td> 
    141141                      <td py:if="last_clause" class="or" colspan="2"> 
     142                        <label for="add_clause">Or</label>&nbsp; 
     143                        <select name="add_clause_${clause_num + 1}" id="add_clause"> 
     144                          <option></option> 
     145                          <option py:for="field_name in field_names" value="$field_name"> 
     146                            ${fields[field_name].label} 
     147                          </option> 
     148                        </select> 
    142149                        <div class="inlinebuttons"> 
    143                           <input type="submit" name="add_clause" id="add_clause" value="Or..." /> 
     150                          <input type="submit" name="add_${clause_num + 1}" value="+" /> 
    144151                        </div> 
    145152                      </td> 
    146153                    </tr> 
  • trac/htdocs/js/query.js

     
    3333        var ctbody = table.closest("tbody"); 
    3434        if (table.children().length > 2 || !ctbody.siblings().length) { 
    3535          tbody.remove(); 
     36          if (!ctbody.siblings().length && table.children().length == 1) { 
     37            $("#add_clause").attr("disabled", true); 
     38          } 
    3639        } else { 
    3740          var add_clause = $("#add_clause", ctbody); 
    3841          if (add_clause.length) 
     
    110113    $("#filters select[name^=add_filter_]").change(function() { 
    111114      if (this.selectedIndex < 1) 
    112115        return; 
    113        
     116 
    114117      if (this.options[this.selectedIndex].disabled) { 
    115118        // IE doesn't support disabled options 
    116119        alert("A filter already exists for that property"); 
     
    219222        this.options[this.selectedIndex].disabled = true; 
    220223       
    221224      this.selectedIndex = 0; 
     225 
     226      // Enable the Or... button if it's been disabled 
     227      $("#add_clause").attr("disabled", false); 
    222228    }).next("div.inlinebuttons").remove(); 
    223229     
    224230    // Add a new empty clause at the end by cloning the current last clause 
    225     function addClause(button) { 
    226       var tbody = $(button).closest("tbody"); 
    227       var clauseNum = parseInt($("select[name^=add_filter_]", tbody) 
    228                                .attr("name").split("_").pop()) + 1; 
    229       tbody = tbody.parents("tbody").eq(0); 
     231    function addClause(select) { 
     232      var tbody = $(select).closest("tbody"); 
     233      var clauseNum = parseInt($(select).attr("name").split("_").pop()); 
     234      var tbody = $(select).closest("tbody").parents("tbody").eq(0); 
    230235      var copy = tbody.clone(true); 
    231       $(button).closest("td").next().attr("colSpan", 4).end().remove(); 
    232       $("td.trac-clause-sep", copy).parent().removeAttr("style"); 
     236      $(select).closest("td").next().attr("colSpan", 4).end().remove(); 
     237      $("tr:first", copy).removeAttr("style"); 
    233238      $("tr tbody:not(:last)", copy).remove(); 
    234239      var newId = "add_filter_" + clauseNum; 
    235       $("select", copy).attr("id", newId).attr("name", newId) 
     240      $("select[name^=add_filter_]", copy).attr("id", newId) 
     241        .attr("name", newId) 
    236242        .children().enable().end() 
    237243        .prev().attr("for", newId); 
     244      $("select[name^=add_clause_]", copy) 
     245        .attr("name", "add_clause_" + (clauseNum + 1)); 
    238246      tbody.after(copy); 
    239247    } 
    240248     
    241     // Make the button for adding a clause a client-side trigger 
    242     var add_clause = $("#filters input[name=add_clause]"); 
    243     add_clause.replaceWith( 
    244       $($.template('<input type="button" id="add_clause" value="$1">',  
    245                    add_clause.val())).click(function() { 
     249    var add_clause = $("#add_clause"); 
     250    add_clause.change(function() { 
     251      // Add a new clause and fire a change event on the new clause's 
     252      // add_filter select. 
     253      var field = $(this).val(); 
    246254      addClause(this); 
    247       return false; 
    248     })); 
     255      $("#add_clause").closest("tr").find("select[name^=add_filter_]") 
     256        .val(field).change(); 
     257    }).next("div.inlinebuttons").remove(); 
     258    if (!add_clause.closest("tbody").siblings().length) { 
     259      // That is, if there are no filters added to this clause 
     260      add_clause.attr("disabled", true); 
     261    } 
    249262  } 
    250263 
    251264})(jQuery);