Created
August 20, 2020 07:11
-
-
Save walokra/66391c2918d2d44c6532f305a37132e6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<!-- | |
Amazon S3 Bucket listing. | |
Copyright (C) 2008 Francesco Pasqualini | |
This program is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation, either version 3 of the License, or | |
(at your option) any later version. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program. If not, see <http://www.gnu.org/licenses/>. | |
--> | |
<!-- | |
Modified by Nolan Lawson! (http://nolanlawson.com). I'm keeping the spirit of the | |
GPL alive by issuing this with the same license! | |
--> | |
<title>Bucket loading...</title> | |
<link href="//netdna.bootstrapcdn.com/bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet"/> | |
<style> | |
.hide-while-loading { | |
display:none; | |
} | |
.i-expand-collapse { | |
opacity: 0.3; | |
} | |
.i-file-or-folder { | |
margin-right: 4px; | |
} | |
</style> | |
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.1.2/handlebars.min.js"></script> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.4.0/moment.min.js"></script> | |
</head> | |
<body> | |
<div class="container"> | |
<h1 id="h1-title">Bucket loading...</h1> | |
<table class="hide-while-loading table table-striped"> | |
<thead> | |
<tr> | |
<th>Name</th> | |
<th>Date Modified</th> | |
<th>Size</th> | |
<th>Type</th> | |
</tr> | |
</thead> | |
<tbody id="tbody-content"> | |
</tbody> | |
</table> | |
</div> | |
<script id="file-or-folder" type="text/x-handlebars-template"> | |
<tr> | |
{{#if isFolder}} | |
<td><i class="icon-chevron-down i-expand-collapse" style="margin-left:calc(({{numLevels}} - 1) * 16px)");></i><i class="icon-folder-open i-file-or-folder" style="margin-left:4px;"></i> | |
{{simpleFilename}}</td> | |
{{else}} | |
<td><i class="icon-file i-file-or-folder" style="margin-left:calc(({{numLevels}} * 16px) + 4px);"></i> | |
<a href="{{url}}">{{simpleFilename}}</a></td> | |
{{/if}} | |
<td>{{friendlyLastModified}}</td> | |
<td>{{friendlySizeName}}</td> | |
<td>{{type}}</td> | |
</tr> | |
</script> | |
<script> | |
(function($){ | |
"use strict"; | |
var FOLDER_PATTERN = new RegExp('_\\$folder\\$$'); | |
var TYPE_PATTERN = new RegExp('\\.([^\\.\\s]{1,10})$'); | |
var KB = 1024; | |
var MB = 1000000; | |
var GB = 1000000000; | |
// replace last /index.html to get bucket root | |
var bucketUrl = document.location.href.replace(/\/[^\/]+$/, ''); | |
var compiledTemplate; | |
// return e.g. 1.2KB, 1.3MB, 2GB, etc. | |
function toFriendlySizeName(size){ | |
if (size === 0) { | |
return ''; | |
} else if (size < KB) { | |
return size + ' B'; | |
} else if (size < MB) { | |
return (size / KB).toFixed(0) + ' KB'; | |
} else if (size < GB) { | |
return (size / MB).toFixed(2) + ' MB'; | |
} | |
return (size / GB).toFixed(2) + ' GB'; | |
} | |
// POJO describing a file or a folder | |
function FileOrFolder(lastModified, etag, size, key){ | |
var self = this; | |
self.lastModified = lastModified; | |
self.etag = etag; | |
self.size = size; | |
self.key = key; | |
// init logic | |
self.isFolder = FOLDER_PATTERN.test(self.key); | |
self.filename = self.isFolder ? self.key.replace(FOLDER_PATTERN,'') : self.key; | |
self.url = bucketUrl + '/' + self.key; | |
self.levels = self.filename.split('/'); | |
self.numLevels = self.levels.length; | |
self.simpleFilename = self.levels[self.numLevels - 1]; | |
self.friendlySizeName = toFriendlySizeName(parseInt(self.size,10)); | |
var foundTypes = TYPE_PATTERN.exec(self.simpleFilename); | |
self.type = self.isFolder ? 'Folder ' : (foundTypes ? (foundTypes[1].toUpperCase() + ' file') : 'Unknown'); | |
self.friendlyLastModified = moment(lastModified).format('MMM Do YYYY, hh:mm:ss a'); | |
} | |
function onAjaxSuccess(xml) { | |
var listBucketResult = $(xml).find('ListBucketResult'); | |
// set a reasonable title instead of "Bucket loading" | |
var title = 'Index of bucket "' + listBucketResult.find('Name').text() + '"'; | |
document.title = title; | |
$('#h1-title').text(title); | |
var $tbodyContent = $('#tbody-content'); | |
// create the file or folder objects | |
var filesOrFolders = []; | |
listBucketResult.find('Contents').each(function(idx, element){ | |
var $element = $(element); | |
var fileOrFolder = new FileOrFolder( | |
$element.find('LastModified').text(), | |
$element.find('ETag').text(), | |
$element.find('Size').text(), | |
$element.find('Key').text() | |
); | |
filesOrFolders.push(fileOrFolder); | |
}); | |
// sort | |
filesOrFolders.sort(function(left, right){ | |
if (left.levels === right.levels) { | |
return 0; | |
} else if (left.levels < right.levels) { | |
return -1; | |
} | |
return 1; | |
}); | |
// fill in the rows | |
var str = ''; | |
for (var i = 0; i < filesOrFolders.length; i ++) { | |
str += compiledTemplate(filesOrFolders[i]); | |
} | |
$tbodyContent.append(str); | |
$('.hide-while-loading').show(); | |
} | |
$.ajax({ | |
url: bucketUrl, | |
success: onAjaxSuccess | |
}); | |
// compile while ajax is in progress | |
compiledTemplate = Handlebars.compile($('#file-or-folder').html()); | |
})(jQuery); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment