next unless "#{d}/" == mydir
if p =~ %r{/$}
- sz = Dir.children(File.dirname(rep.raw_path)).length - 1
- type = "DIR"
+ displaysize = Dir.children(File.dirname(rep.raw_path)).length - 1
+ size = displaysize - 1000000
+ type = :DIR
else
- sz = human_filesize(File.size(rep.raw_path))
+ size = File.size(rep.raw_path)
+ displaysize = human_filesize(size)
type = nil
end
files[f] = {
- mtime: if t then t.getutc.strftime "%Y-%m-%d %H:%M UTC" end,
- size: sz,
+ sorttime: if t then t.to_f else 0.0 end,
+ displaytime: if t then t.getutc.strftime "%Y-%m-%d %H:%M UTC" end,
+ displaysize: displaysize,
+ size: size,
type: type,
}
end
end
if @items["#{File.dirname(mydir)}/index.lst"]
- files[".."] = { type: "UP" }
+ files[".."] = { type: :UP }
+end
+
+def render_entry(files, key)
+ f = files[key]
+ return <<~EOF
+ <td>#{if f[:type]
+ "<img alt='#{f[:type]}' width='16' height='16' src='#{case f[:type]
+ when :DIR; "/images/folder.svg"
+ when :UP; "/images/return.svg"
+ else raise "no icon for filetype #{f[:type]}"
+ end}' />"
+ end}</td>
+ <td><a href='#{key}'>#{
+ if key == ".." then "[Parent Directory]" else key end
+ }</a></td>
+ <td>#{f[:displaytime]}</td>
+ <td>#{f[:displaysize]}</td>
+ EOF
end
%>
+<div>
+<script type='x'><![CDATA[]]x><!--]]></script>
+<input style='display: none' type='radio' name='filelist-sort' id='filelist-name-sort' checked='checked' />
+<input style='display: none' type='radio' name='filelist-sort' id='filelist-date-sort' />
+<input style='display: none' type='radio' name='filelist-sort' id='filelist-size-sort' />
+<input style='display: none' type='checkbox' id='filelist-name-rev' />
+<input style='display: none' type='checkbox' id='filelist-date-rev' />
+<input style='display: none' type='checkbox' id='filelist-size-rev' />
+<script type='x'>--></script>
<table class='filelist'>
<thead>
- <tr><th /><th>Name</th><th>Last Modified</th><th>Size</th></tr>
+ <tr>
+ <th />
+ <th class='name'>
+ <label for='filelist-name-sort'><span>Name</span></label>
+ <script type='x'><![CDATA[]]x><!--]]></script>
+ <label for='filelist-name-rev' style='display: none'>
+ <span>Name</span>
+ <img alt='FWD' width='16' height='16' src='/images/down.svg' />
+ <img alt='REV' width='16' height='16' src='/images/up.svg' style='display: none' />
+ </label>
+ <script type='x'>--></script>
+ </th>
+ <th class='date'>
+ <label for='filelist-date-sort'><span>Last Modified</span></label>
+ <script type='x'><![CDATA[]]x><!--]]></script>
+ <label for='filelist-date-rev' style='display: none'>
+ <span>Last Modified</span>
+ <img alt='FWD' width='16' height='16' src='/images/down.svg' />
+ <img alt='REV' width='16' height='16' src='/images/up.svg' style='display: none' />
+ </label>
+ <script type='x'>--></script>
+ </th>
+ <th class='size'>
+ <label for='filelist-size-sort'><span>Size</span></label>
+ <script type='x'><![CDATA[]]x><!--]]></script>
+ <label for='filelist-size-rev' style='display: none'>
+ <span>Size</span>
+ <img alt='FWD' width='16' height='16' src='/images/down.svg' />
+ <img alt='REV' width='16' height='16' src='/images/up.svg' style='display: none' />
+ </label>
+ <script type='x'>--></script>
+ </th>
+ </tr>
</thead>
<tbody>
-<% files.keys.sort{ |a, b| strverscmp(a, b) }.each do |key| %>
- <tr>
- <td>
-<% if files[key][:type] %>
- <div>
- <img src='<%=
- case files[key][:type]
- when "DIR"; "/images/folder.svg"
- when "UP"; "/images/return.svg"
- else raise "no icon for filetype #{files[key][:type]}"
- end %>' alt='<%= files[key][:type] %>' width='16' height='16' />
- </div>
+<%=
+ parentrow = if files[".."] then "#{render_entry(files, "..")}" end
+ files.delete("..")
+ if parentrow then "<tr>#{parentrow}</tr>" end
+%>
+<%
+by_name = files.keys.sort{ |a, b| strverscmp(a, b) }
+by_name.each_index do |i|
+ entry = render_entry(files, by_name[i])
+ if i+1 == by_name.length
+ entry.sub!(%r{(.*)</td>}m,
+ "\\1<script type='x'><![CDATA[]]x><!--]]></script></td>")
+ end
+%>
+ <tr><%= entry %></tr>
<% end %>
- </td>
- <td><a href='<%= key %>'><%=
- if key == ".." then "[Parent Directory]" else key end
- %></a></td>
- <td><%= files[key][:mtime] %></td>
- <td><%= files[key][:size] %></td>
+ </tbody>
+
+ <tbody style='display: none'>
+<%
+def meta_cmp(files, key, a, b)
+ av, bv = files[a][key], files[b][key]
+ return av <=> bv if av != bv
+ return strverscmp(a, b)
+end
+
+by_date = files.keys.sort { |a, b| meta_cmp(files, :sorttime, a, b) }
+by_size = files.keys.sort { |a, b| meta_cmp(files, :size, a, b) }
+
+listnames = [ "namerev", "date", "daterev", "size", "sizerev" ]
+lists = [ by_name.reverse, by_date, by_date.reverse, by_size, by_size.reverse ]
+if parentrow
+%>
+ <tr class='<%= listnames.join(" ") %>'><%= parentrow %></tr>
+<%
+end
+evenmap = (0..(lists.length-1)).map { false }
+even = false
+
+while not (elems = lists.map(&:first)).compact.empty?
+ matches = (0..(lists.length-1)).to_a.keep_if { |x| evenmap[x] == even }
+ if !matches.empty?
+ elems = elems.values_at(*matches).compact
+ mode = elems.group_by{|a| a}.max{|a, b| a[1].length <=> b[1].length}[0]
+ matches = []
+
+ lists.each_index do |i|
+ if evenmap[i] == even and lists[i].first.eql? mode
+ lists[i].shift
+ evenmap[i] ^= true
+ evenmap[i] = nil if lists[i].empty?
+
+ matches << i
+ end
+ end
+%>
+ <tr class='<%= listnames.values_at(*matches).join(" ") %>'>
+ <%= render_entry(files, mode) %>
</tr>
-<% end %>
+<%
+ else
+%>
+ <tr><td /></tr>
+<%
+ end
+
+ even ^= true
+end
+%>
+ <tr><td><script type='x'>--></script></tr>
</tbody>
</table>
+</div>