Edgewall Software

Ticket #7074: 7074-directory-expand-and-nav.2.patch

File 7074-directory-expand-and-nav.2.patch, 9.4 KB (added by cboos, 4 years ago)

Incredible how posting code helps you to find bugs immediately afterwards ;-) Same as before, also re-expands correctly when browsing from another place than the root and when there are query arguments (non-default sort order, fixed rev, etc.)

  • trac/htdocs/js/keyboard_nav.js

     
    55  $(document).keydown(function(event) { 
    66    if (!ENABLE_KEY_NAV) 
    77      return true; 
     8    if (event.ctrlKey) 
     9      return true; // let CTRL+R do its job 
    810    var selection = SELECTED_FILE_ELEM; 
    911    switch (event.keyCode) { 
    10       case 74: // j 
     12      case 74: // j - next line 
    1113        if (selection == null) { 
    1214          selection = $('#f0'); 
     15          if ( !selection.length )  
     16            selection = $($("#dirlist tr").get(1)) 
    1317        } else { 
    1418          do { 
    1519            selection = selection.next(); 
    1620          } while (selection.length > 0 && selection.css('display') == 'none'); 
    1721        } 
    1822        break; 
    19       case 75: // k 
     23      case 75: // k - previous line 
    2024        if (selection == null) { 
    2125          selection = $('#f0'); 
    2226        } else { 
     
    2630        } 
    2731        break; 
    2832      case 13: // Enter 
    29       case 79: // o 
     33      case 65: // 'a'nnotate 
     34      case 79: // 'o'pen 
     35      case 82: // 'r'eload 
    3036        if (selection != null) { 
    3137          var expander = selection.find('.expander'); 
    3238          if (expander.length > 0) { 
     39            if (event.keyCode == 82) { 
     40              selection.removeClass("expanded").removeClass("collapsed") 
     41                .siblings("tr."+selection.get(0).id).not(selection).remove(); 
     42            } 
    3343            expander.click(); 
    3444          } else { 
    35             window.location = selection.find('a.file').attr('href'); 
     45            var href = selection.find('a.file').attr('href'); 
     46            if (href) { 
     47              if (event.keyCode == 65) 
     48                href += '?annotate=blame'; 
     49            } else { 
     50              href = selection.find('a.parent').attr('href'); 
     51            } 
     52            if (href) 
     53              window.location = href; 
    3654          } 
    3755        } 
    3856        return false; 
    3957        break; 
     58      case 76: // 'l'og 
     59        if (selection != null) { 
     60          window.location = selection.find('td.rev a').attr('href'); 
     61        } 
     62        break; 
    4063      default: 
    4164        return true; 
    4265    } 
  • trac/htdocs/js/trac.js

     
    4747    }); 
    4848  } 
    4949   
     50  $.template = function(str, dict) {  
     51    return str.replace(/\${?(\w+)}?/g, function(_, k) { return dict[k]; });  
     52  } 
     53 
    5054  // Used for dynamically updating the height of a textarea 
    5155  window.resizeTextArea = function (id, rows) { 
    5256    var textarea = $("#" + id).get(0); 
     
    7276    return $(elem).parents(tagName).get(0); 
    7377  } 
    7478 
    75 })(jQuery); 
    76  No newline at end of file 
     79})(jQuery); 
  • trac/htdocs/js/expand_dir.js

     
    44  var FOLDERID_COUNTER = 0; 
    55  var SUBFOLDER_INDENT = 20; 
    66   
    7   // enableExpandDir adds the capability to folder rows to be expanded and folded 
     7  // enableExpandDir adds the capability to ''folder'' rows in a table 
     8  // to be expanded and folded. 
     9  // 
    810  // It also teach the rows about their ancestors. It expects: 
    911  //  - `parent_tr`, the logical parent row (`null` if there's no ancestor) 
    1012  //  - a `rows` jQuery object matching the newly created entry rows 
    1113  //  - `qargs`, additional parameters to send to the server when expanding 
     14  //  - `autoexpand`, an optional array corresponding to a splitted sub-path 
     15  //    of entries that will be expanded automatically. 
    1216   
    13   window.enableExpandDir = function(parent_tr, rows, qargs) { 
     17  window.enableExpandDir = function(parent_tr, rows, qargs, autoexpand) { 
    1418    // the ancestors folder ids are present in the parent_tr class attribute 
    1519    var ancestor_folderids = []; 
    16     if (parent_tr) 
     20 
     21    if (parent_tr) // rows are logical children of the parent_tr row 
    1722      ancestor_folderids = $.grep(parent_tr.attr("class").split(" "),  
    1823                                  function(c) { return c.match(/^f\d+$/)}); 
     24    else { // rows are toplevel rows, this is the initial call 
     25      var anchor = window.location.hash.substr(1); 
     26      if (anchor) 
     27        autoexpand = anchor.split("/"); 
     28    } 
     29 
     30    var autoexpand_expander = null; 
    1931    rows.each(function () { 
    2032      var a = $(this).find("a.dir"); 
    2133   
     
    2638        $(this).addClass(folderid); 
    2739   
    2840        // add the expander icon 
    29         a.wrap('<div></div>'); 
    30         var expander = a.before('<span class="expander">&nbsp;</span>').prev(); 
    31         expander.attr("title", "Expand sub-directory in place") 
    32           .click(function() { toggleDir($(this), qargs); }); 
     41        var expander = $('<span class="expander">&nbsp;</span>') 
     42          .attr("title", "Expand sub-directory in place") 
     43          .click(function() { toggleDir($(this), qargs); }) 
     44        a.wrap('<div></div>').before(expander); 
     45        if (autoexpand && a.text() == autoexpand[0]) 
     46          autoexpand_expander = expander; 
    3347      } 
    3448   
    3549      // tie that row to ancestor folders 
    3650      if (parent_tr) 
    3751        $(this).addClass(ancestor_folderids.join(" ")); 
    3852    }); 
     53     
     54    if ( autoexpand_expander ) 
     55      toggleDir(autoexpand_expander, qargs, autoexpand.slice(1)); 
    3956  } 
    4057   
    4158  // handler for click event on the expander icons 
    42   window.toggleDir = function(expander, qargs) { 
     59  window.toggleDir = function(expander, qargs, autoexpand) { 
    4360    var tr = expander.parents("tr:first"); 
    4461    var folderid = tr.get(0).id; 
    4562   
    46     if ( tr.filter(".expanded").length ) { // then *fold* 
    47       tr.removeClass("expanded").addClass("collapsed"); 
    48       tr.siblings("tr."+folderid).hide(); 
     63    if ( tr.hasClass("expanded") ) { // then *fold* 
     64      tr.removeClass("expanded"); 
     65      if (tr.next().hasClass("error")) { 
     66        tr.next().remove(); 
     67      } else { 
     68        tr.addClass("collapsed"); 
     69        tr.siblings("tr."+folderid).hide(); 
     70      } 
    4971      expander.attr("title", "Re-expand directory"); 
    5072      return; 
    5173    } 
    52    
    53     if ( tr.filter(".collapsed").length ) { // then *expand* 
     74 
     75    // update location, unless autoexpand in progress 
     76    var a = expander.next("a"); 
     77    if ( !autoexpand ) 
     78      window.location.hash = a.attr("href") 
     79        .substr(window.location.pathname.length+1) 
     80        .replace(/([^?]*)(\?.*)?$/, '$1');     
     81 
     82    if ( tr.hasClass("collapsed") ) { // then *expand* 
    5483      tr.removeClass("collapsed").addClass("expanded"); 
    5584      tr.siblings("tr."+folderid).show(); 
    56       // Note that the above will show all the already fetched subtree, 
     85      // Note that the above will show all the already fetched subtrees, 
    5786      // so we have to fold again the folders which were already collapsed. 
    5887      tr.siblings("tr.collapsed").each(function() { 
    5988        tr.siblings("tr."+this.id).not(this).hide(); 
     
    6190    } else {                                // then *fetch* 
    6291      var td = expander.parents("td"); 
    6392      var td_class = td.attr("class"); 
    64       var a = expander.next("a"); 
    6593      var depth =  
    6694        parseFloat(td.css("padding-left").replace(/^(\d*\.\d*).*$/, "$1")) +  
    6795        SUBFOLDER_INDENT; 
    6896   
    6997      tr.addClass("expanded"); 
    7098      // insert "Loading ..." row 
    71       tr.after('<tr><td><span class="loading"></span></td></tr>'); 
    72       var loading_row = tr.next(); 
    73       loading_row.children("td").addClass(td_class) 
    74         .attr("colspan", tr.children("td").length) 
    75         .css("padding-left", depth); 
    76       loading_row.find("span.loading").text("Loading " + a.text() + "..."); 
     99      var loading_row = $($.template( 
     100        '<tr>'+ 
     101        ' <td class="$td_class" colspan="$colspan" '+ 
     102        '     style="padding-left: ${depth}px">'+ 
     103        '  <span class="loading">Loading $entry...</span>'+ 
     104        ' </td>'+ 
     105        '</tr>', { 
     106        td_class: td_class,  
     107        colspan: tr.children("td").length,  
     108        depth: depth,  
     109        entry: a.text() 
     110      })); 
     111      tr.after(loading_row); 
    77112   
    78113      // XHR for getting the rows corresponding to the folder entries 
    79114      $.ajax({ 
     
    91126              row = $(this+"</tr>"); 
    92127              row.children("td."+td_class).css("padding-left", depth); 
    93128              // make all entry rows collapsible but only subdir rows expandable 
    94               enableExpandDir(tr, row, qargs);  
    95129              loading_row.before(row); 
     130              enableExpandDir(tr, row, qargs, autoexpand);  
    96131            }); 
    97132            // remove "Loading ..." row 
    98133            loading_row.remove(); 
    99134          } else { 
    100             loading_row.find("span.loading").text("").append("<i>(empty)</i>") 
    101               .removeClass("loading"); 
    102             // make the (empty) row collapsible 
    103             enableExpandDir(tr, loading_row, qargs);  
     135            loading_row.find("span.loading") 
     136              .text("").append("<i>(empty)</i>").removeClass("loading"); 
     137            enableExpandDir(tr, loading_row, qargs); // make it collapsible 
    104138          } 
    105139        }, 
    106140        error: function(req, err, exc) { 
    107           loading_row.find("span.loading").text("").append("<i>(error)</i>") 
    108             .removeClass("loading"); 
    109           enableExpandDir(tr, loading_row, qargs); 
     141          loading_row.find("span.loading") 
     142            .text("").append("<i>(error)</i>").removeClass("loading"); 
     143          loading_row.addClass("error"); 
     144          enableExpandDir(tr, loading_row, qargs); // make it collapsible 
    110145        } 
    111146      }); 
    112147    }