diff options
Diffstat (limited to 'js')
| -rw-r--r-- | js/cabinet.js | 71 | ||||
| -rw-r--r-- | js/cheesesteak.js | 343 | ||||
| -rw-r--r-- | js/pomf.js | 302 |
3 files changed, 364 insertions, 352 deletions
diff --git a/js/cabinet.js b/js/cabinet.js index ebbae4f..cb8039b 100644 --- a/js/cabinet.js +++ b/js/cabinet.js @@ -1,36 +1,43 @@ -;(function($){ - $.hasFileAPI = function hasFileAPI () { - return (window.FormData !== undefined) - } - $.fn.cabinet = function (input) { - input = $(input) +/* jshint browser:true, jquery:true */ +(function($) { + $.hasFileAPI = function hasFileAPI() { + return (window.FormData !== undefined); + }; - var _this = this - var passthrough = function (outer, inner, prevent, fn) { - _this.on(outer, function (e) { - if (inner === 'click') - input[0].click() - else - input.trigger(inner) - if (prevent) e.preventDefault() - if (fn) fn(e) - }, false) - } + $.fn.cabinet = function(input) { + input = $(input); - input[0].filelist = Object.create(FileList) + var _this = this; + var passthrough = function(outer, inner, prevent, fn) { + _this.on(outer, function(e) { + if (inner === 'click') { + input[0].click(); + } else { + input.trigger(inner); + } + if (prevent) { + e.preventDefault(); + } + if (fn) { + fn(e); + } + }, false); + }; - input.on('change', function (e) { - this.filelist = e.target.files - _this.change() - }) + input[0].filelist = Object.create(FileList); - passthrough('dragenter', 'dragenter', true) - passthrough('dragover', 'dragover', true) - passthrough('dragleave', 'dragleave', true) - passthrough('click', 'click', false) - passthrough('drop', 'dragleave', true, function (e) { - input[0].filelist = e.dataTransfer.files - _this.change() - }) - } -})($) + input.on('change', function(e) { + this.filelist = e.target.files; + _this.change(); + }); + + passthrough('dragenter', 'dragenter', true); + passthrough('dragover', 'dragover', true); + passthrough('dragleave', 'dragleave', true); + passthrough('click', 'click', false); + passthrough('drop', 'dragleave', true, function(e) { + input[0].filelist = e.dataTransfer.files; + _this.change(); + }); + }; +})($); diff --git a/js/cheesesteak.js b/js/cheesesteak.js index d4a1acf..47aee93 100644 --- a/js/cheesesteak.js +++ b/js/cheesesteak.js @@ -1,172 +1,171 @@ -;(function () { - /* Lightweight EventEmitter implementation */ - EventEmitter = function () {} - EventEmitter.prototype.on = function (evt, fn) { - this._events = this._events || {} - this._events[evt] = this._events[evt] || [] - this._events[evt].push(fn) - } - EventEmitter.prototype.off = function (evt, fn) { - if (!this.hasOwnProperty('_events')) return - if (evt in this._events === false) return - this._events[evt].splice(this._events[evt].indexOf(fn), 1) - } - EventEmitter.prototype.emit = function (evt) { - if (!this.hasOwnProperty('_events')) return - if (evt in this._events === false) return - - for (var i = 0, l = this._events[evt].length; i < l; i++) { - this._events[evt][i].apply(this, Array.prototype.slice.call(arguments, 1)) - } - } - - /* Copy the stuff from Array to FileList */ - FileList.prototype.forEach = Array.prototype.forEach - FileList.prototype.every = Array.prototype.every - FileList.prototype.some = Array.prototype.some - FileList.prototype.filter = Array.prototype.filter - FileList.prototype.map = Array.prototype.map - FileList.prototype.reduce = Array.prototype.reduce - FileList.prototype.reduceRight = Array.prototype.reduceRight - - Object.defineProperty(FileList.prototype, "size", { - get: function getSize () { - return this.reduce(function (prev, curr) { - return prev + curr.size - }, 0) - } - }) - - /* Utility to convert bytes into human units */ - var humanSize = { - get: function humanSize () { - var units = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"] - var e = Math.floor(Math.log(this.size) / Math.log(1024)) - return (this.size / Math.pow(1024, e)).toFixed(2) + " " + units[e] - } - } - Object.defineProperty(FileList.prototype, "humanSize", humanSize) - Object.defineProperty(File.prototype, "humanSize", humanSize) - - var percentUploaded = { - get: function percentUploaded () { - return this.uploadedSize / this.size - } - } - Object.defineProperty(FileList.prototype, "percentUploaded", percentUploaded) - Object.defineProperty(File.prototype, "percentUploaded", percentUploaded) - - Object.defineProperty(FileList.prototype, "uploadedSize", { - get: function getUploadedSize () { - return this.reduce(function (prev, curr) { - return prev + (curr.uploadedSize || 0) - }, 0) - } - }) - - /* Object URL stuff */ - Object.defineProperty(File.prototype, "url", { - get: function getURL () { - return window.URL.createObjectURL(this); - } - }) - File.revokeURL = function revokeURL (url) { - window.URL.revokeObjectURL(url) - } - - // We manipulate this instead of files, because the fucking geniuses at - // Mozilla interpreted the spec to mean that HTMLInputElement.prototype.files - // is read-only. It isn't, read for yourself: - // http://www.w3.org/html/wg/drafts/html/master/forms.html#dom-input-files - //HTMLInputElement.prototype.filelist = Object.create(FileList); - /* - Object.defineProperty(HTMLInputElement.prototype, "filelist", { - get: function getFileList () { - return this.filelist = this._filelist || this.files - }, - set: function (files) { - r - } - })*/ - -/* HTMLInputElement.prototype.addEventListener("change", function (e) { - this.filelist = e.target.files - })*/ - - // b gets merged as defaults for a - var merge = function merge (base, overlay) { - var out = base - for (var key in overlay) { - if (typeof overlay[key] === 'object') - out[key] = merge(base[key], overlay[key]); - else - out[key] = overlay[key] - } - return out - } - - var FileListUploader = function (url, files, opts) { - this.url = url - this.files = files - - opts = opts || {} - - this.opts = merge({ - 'field': 'files[]', - 'method': 'POST', - 'data': {} - }, opts) - } - FileListUploader.prototype = Object.create(EventEmitter.prototype) - FileListUploader.prototype.upload = function (cb) { - if (cb) this.on('uploadcomplete', cb) - - var opts = this.opts - var files = this.files - var events = this - - var data = new FormData() - files.forEach(function (file) { - data.append(opts.field, file) - }) - - var xhr = new XMLHttpRequest() - - xhr.open(opts.method, this.url, true) - xhr.upload.addEventListener('loadstart', function (e) { - for (var i = 0, l = files.length; i < l; i++) { - files[i].uploadedSize = 0 - } - }) - xhr.upload.addEventListener('progress', function (e) { - if (e.lengthComputable) { - size = e.loaded - // We know the size of the files, the order they're in, and how - // much we've uploaded. Based on this data, we can do some magic - // to figure out which file we're on, and how much we've uploaded - // of that file. - // TODO: This math has trouble on later uploads. Leak somewhere - for (var i = 0, l = files.length; i < l; i++) { - files[i].uploadedSize = Math.min(size, files[i].size) - size -= files[i].uploadedSize - if (size <= 0) { - files.current = files[i] - size = 0 - } - } - } - events.emit('uploadprogress', e, files) - }, false) - xhr.upload.addEventListener('loadstart', function (e) { events.emit('uploadstart', e) }) - xhr.upload.addEventListener('load', function (e) { events.emit('uploadcomplete', e) }) - xhr.addEventListener('progress', function (e) { events.emit('progress', e) }) - xhr.addEventListener('load', function (e) { events.emit('load', e, xhr.responseText) }) - - xhr.send(data) - /* TODO: Add more event passthroughs, maybe abstract it into a helper? */ - } - - FileList.prototype.upload = function uploadFileList (url, opts) { - return new FileListUploader(url, this, opts) - } -})() +/* jshint browser:true, jquery:true */ +(function() { + /* Lightweight EventEmitter implementation */ + EventEmitter = function() {}; + EventEmitter.prototype.on = function(evt, fn) { + this._events = this._events || {}; + this._events[evt] = this._events[evt] || []; + this._events[evt].push(fn); + }; + EventEmitter.prototype.off = function(evt, fn) { + if (!this.hasOwnProperty('_events') || evt in this._events === false) { + return; + } + this._events[evt].splice(this._events[evt].indexOf(fn), 1); + }; + EventEmitter.prototype.emit = function(evt) { + if (!this.hasOwnProperty('_events') || evt in this._events === false) { + return; + } + + for (var i = 0, l = this._events[evt].length; i < l; i++) { + this._events[evt][i].apply(this, Array.prototype.slice.call(arguments, + 1)); + } + }; + + /* Copy the stuff from Array to FileList */ + FileList.prototype.forEach = Array.prototype.forEach; + FileList.prototype.every = Array.prototype.every; + FileList.prototype.some = Array.prototype.some; + FileList.prototype.filter = Array.prototype.filter; + FileList.prototype.map = Array.prototype.map; + FileList.prototype.reduce = Array.prototype.reduce; + FileList.prototype.reduceRight = Array.prototype.reduceRight; + + Object.defineProperty(FileList.prototype, "size", { + get: function getSize() { + return this.reduce(function(prev, curr) { + return prev + curr.size; + }, 0); + } + }); + + /* Utility to convert bytes into human units */ + var humanSize = { + get: function humanSize() { + var units = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", + "YiB" + ]; + var e = Math.floor(Math.log(this.size) / Math.log(1024)); + return (this.size / Math.pow(1024, e)).toFixed(2) + " " + units[e]; + } + }; + Object.defineProperty(FileList.prototype, "humanSize", humanSize); + Object.defineProperty(File.prototype, "humanSize", humanSize); + + var percentUploaded = { + get: function percentUploaded() { + return this.uploadedSize / this.size; + } + }; + Object.defineProperty(FileList.prototype, "percentUploaded", + percentUploaded); + Object.defineProperty(File.prototype, "percentUploaded", percentUploaded); + + Object.defineProperty(FileList.prototype, "uploadedSize", { + get: function getUploadedSize() { + return this.reduce(function(prev, curr) { + return prev + (curr.uploadedSize || 0); + }, 0); + } + }); + + /* Object URL stuff */ + Object.defineProperty(File.prototype, "url", { + get: function getURL() { + return window.URL.createObjectURL(this); + } + }); + File.revokeURL = function revokeURL(url) { + window.URL.revokeObjectURL(url); + }; + + // b gets merged as defaults for a + var merge = function merge(base, overlay) { + var out = base; + for (var key in overlay) { + if (typeof overlay[key] === 'object') { + out[key] = merge(base[key], overlay[key]); + } else { + out[key] = overlay[key]; + } + } + return out; + }; + + var FileListUploader = function(url, files, opts) { + this.url = url; + this.files = files; + + opts = opts || {}; + + this.opts = merge({ + 'field': 'files[]', + 'method': 'POST', + 'data': {} + }, opts); + }; + FileListUploader.prototype = Object.create(EventEmitter.prototype); + FileListUploader.prototype.upload = function(cb) { + if (cb) { + this.on('uploadcomplete', cb); + } + + var opts = this.opts; + var files = this.files; + var events = this; + + var data = new FormData(); + files.forEach(function(file) { + data.append(opts.field, file); + }); + + var xhr = new XMLHttpRequest(); + + xhr.open(opts.method, this.url, true); + xhr.upload.addEventListener('loadstart', function(e) { + for (var i = 0, l = files.length; i < l; i++) { + files[i].uploadedSize = 0; + } + }); + xhr.upload.addEventListener('progress', function(e) { + if (e.lengthComputable) { + size = e.loaded; + // We know the size of the files, the order they're in, and how + // much we've uploaded. Based on this data, we can do some magic + // to figure out which file we're on, and how much we've uploaded + // of that file. + // TODO: This math has trouble on later uploads. Leak somewhere + for (var i = 0, l = files.length; i < l; i++) { + files[i].uploadedSize = Math.min(size, files[i].size); + size -= files[i].uploadedSize; + if (size <= 0) { + files.current = files[i]; + size = 0; + } + } + } + events.emit('uploadprogress', e, files); + }, false); + xhr.upload.addEventListener('loadstart', function(e) { + events.emit('uploadstart', e); + }); + xhr.upload.addEventListener('load', function(e) { + events.emit('uploadcomplete', e); + }); + xhr.addEventListener('progress', function(e) { + events.emit('progress', e); + }); + xhr.addEventListener('load', function(e) { + events.emit('load', e, xhr.responseText); + }); + + xhr.send(data); + /* TODO: Add more event passthroughs, maybe abstract it into a helper? */ + }; + + FileList.prototype.upload = function uploadFileList(url, opts) { + return new FileListUploader(url, this, opts); + }; +})(); @@ -1,148 +1,154 @@ -$(function () { - var uploadInput = $('#upload-input') - , uploadBtn = $('#upload-btn') - , uploadFiles = $('#upload-filelist') - - var btnContent = "" - - if (!$.hasFileAPI()) { - $('#no-file-api').show() - uploadBtn.hide() - } - - uploadBtn.cabinet(uploadInput) - - uploadBtn.on('dragenter', function (e) { - if (this === e.target) { - $(this).addClass('drop') - btnContent = $(this).html() - $(this).html('Drop it here~') - } - }) - - uploadBtn.on('drop', function (e) { - $(this).trigger('dragleave') - }) - - uploadBtn.on('dragleave', function (e) { - node = e.target - do { - if (node === this) { - $(this).removeClass('drop') - $(this).html(btnContent) - break - } - } while (node = node.parentNode) - }) - - var MAX_SIZE = (function (node) { - var max = node.attr('data-max-size') || '120MiB' - var num = parseInt(/([0-9,]+).*/.exec(max)[1].replace(',', '')) - var unit = /(?:([KMGTPEZY])(i)?B|([BKMGTPEZY]))/.exec(max) || ["B","",""] - - var oneUnit = Math.pow( - (unit[2] === "i" ? 1024 : 1000), - 'BKMGTPEZY'.indexOf(unit[1]) - ) - - return num * oneUnit - })(uploadInput) - - var createRow = function (filename, size, extra) { - var rowItem = $('<li class=file>') - , rowName = $('<span class=file-name>') - , rowProg = $('<div class="file-progress progress-outer">') - , rowSize = $('<span class=file-size>') - , rowUrl = $('<span class=file-url>') - - rowItem.addClass(extra || '') - - $('<div class=progress-inner>').appendTo(rowProg) - - rowItem.attr('data-filename', escape(filename)) - rowName.text(filename) - rowSize.text(size) - - rowItem.append(rowName, rowProg, rowSize, rowUrl) - - return rowItem - } - - uploadBtn.on('change', function (e) { - uploadFiles.empty().removeClass('error completed') - - var files = uploadInput[0].filelist; - - files.forEach(function (file) { - createRow(file.name, file.humanSize).appendTo(uploadFiles) - }) - - var totalRow = createRow('', files.humanSize, 'total') - totalRow.appendTo(uploadFiles) - - if (files.size > MAX_SIZE) { - uploadFiles.addClass('error') - - $('.file-name', totalRow).html('onii-chan y-your upload is t-too big…'); - return - } - - var up = files.upload("upload.php") - - var eachRow = function (files, fn) { - var hits = {} - files.forEach(function (file) { - ++hits[file.name] || (hits[file.name] = 0) - var row = $($('li[data-filename="' + escape(file.name) + '"]')[hits[file.name] || 0]) - fn.call(row, row, file, files) - }) - } - - var totalName = $('.file-name', totalRow) - - up.on('uploadprogress', function (e, files) { - eachRow(files, function (row, file, files) { - $('.progress-inner', row).width((file.percentUploaded * 100) + '%') - }) - $('.progress-inner', totalRow).width((files.percentUploaded * 100) + '%') - }) - - up.on('uploadcomplete', function (e) { - $('.progress-inner').width('100%') - totalName.text('Grabbing URLs...') - }) - - up.on('load', function (e, res) { - switch (e.target.status) { - case 200: - var res = JSON.parse(res) - if (!res.success) { - uploadFiles.addClass('error') - $('.file-name', totalRow).text('Something went wrong; try again later.') - break - } - eachRow(res.files, function (row, file, files) { - var link = $('<a>') - - link.attr('href', file.url) - .attr('target', '_BLANK') - .text(file.url.replace("http://","").replace("https://","")) - - $('.file-url', row).append(link) - }) - uploadFiles.addClass('completed') - totalName.text('Done!') - break - case 413: - uploadFiles.addClass('error completed') - // Terrible work-around, but necessary since otherwise the '…' entity is left decoded - totalName.html($('<div/>').html('onii-chan, y-your upload is t-too big…').text()); - break - default: - uploadFiles.addClass('error completed') - totalName.text('Something went wrong; try again later.') - } - }) - up.upload() - }) -}) +/* jshint browser:true, jquery:true */ +$(function() { + var uploadInput = $('#upload-input'), + uploadBtn = $('#upload-btn'), + uploadFiles = $('#upload-filelist'); + + var btnContent = ''; + + if (!$.hasFileAPI()) { + $('#no-file-api').show(); + uploadBtn.hide(); + } + + uploadBtn.cabinet(uploadInput); + + uploadBtn.on('dragenter', function(e) { + if (this === e.target) { + $(this).addClass('drop'); + btnContent = $(this).html(); + $(this).html('Drop it here~'); + } + }); + + uploadBtn.on('drop', function(e) { + $(this).trigger('dragleave'); + }); + + uploadBtn.on('dragleave', function(e) { + node = e.target; + do { + if (node === this) { + $(this).removeClass('drop'); + $(this).html(btnContent); + break; + } + } while (node = node.parentNode); + }); + + var MAX_SIZE = (function(node) { + var max = node.attr('data-max-size') || '120MiB'; + var num = parseInt(/([0-9,]+).*/.exec(max)[1].replace(',', '')); + var unit = /(?:([KMGTPEZY])(i)?B|([BKMGTPEZY]))/.exec(max) || ['B', '', '']; + + var oneUnit = Math.pow( + (unit[2] === 'i' ? 1024 : 1000), + 'BKMGTPEZY'.indexOf(unit[1]) + ); + + return num * oneUnit; + })(uploadInput); + + var createRow = function(filename, size, extra) { + var rowItem = $('<li class=file>'), + rowName = $('<span class=file-name>'), + rowProg = $('<div class="file-progress progress-outer">'), + rowSize = $('<span class=file-size>'), + rowUrl = $('<span class=file-url>'); + + rowItem.addClass(extra || ''); + + $('<div class=progress-inner>').appendTo(rowProg); + + rowItem.attr('data-filename', escape(filename)); + rowName.text(filename); + rowSize.text(size); + + rowItem.append(rowName, rowProg, rowSize, rowUrl); + + return rowItem; + }; + + uploadBtn.on('change', function(e) { + uploadFiles.empty().removeClass('error completed'); + + var files = uploadInput[0].filelist; + + files.forEach(function(file) { + createRow(file.name, file.humanSize).appendTo(uploadFiles); + }); + + var totalRow = createRow('', files.humanSize, 'total'); + totalRow.appendTo(uploadFiles); + + if (files.size > MAX_SIZE) { + uploadFiles.addClass('error'); + + $('.file-name', totalRow).html('onii-chan y-your upload is t-too ' + + 'big…'); + return; + } + + var up = files.upload('upload.php'); + + var eachRow = function(files, fn) { + var hits = {}; + files.forEach(function(file) { + ++hits[file.name] || (hits[file.name] = 0); + var row = $($('li[data-filename="' + escape(file.name) + '"]') + + [hits[file.name] || 0]); + fn.call(row, row, file, files); + }); + }; + + var totalName = $('.file-name', totalRow); + + up.on('uploadprogress', function(e, files) { + eachRow(files, function(row, file, files) { + $('.progress-inner', row).width((file.percentUploaded * 100) + '%'); + }); + $('.progress-inner', totalRow).width((files.percentUploaded * 100) + '%'); + }); + + up.on('uploadcomplete', function(e) { + $('.progress-inner').width('100%'); + totalName.text('Grabbing URLs...'); + }); + + up.on('load', function(e, res) { + switch (e.target.status) { + case 200: + var res = JSON.parse(res); + if (!res.success) { + uploadFiles.addClass('error'); + $('.file-name', totalRow).text('Something went wrong; try again ' + + 'later.'); + break; + } + eachRow(res.files, function(row, file, files) { + var link = $('<a>'); + + link.attr('href', file.url) + .attr('target', '_BLANK') + .text(file.url.replace('http://', '').replace('https://', '')); + + $('.file-url', row).append(link); + }); + uploadFiles.addClass('completed'); + totalName.text('Done!'); + break; + case 413: + uploadFiles.addClass('error completed'); + // Terrible work-around, but necessary since otherwise the '…' + // entity is left decoded. + totalName.html($('<div/>').html('onii-chan, y-your upload is t-too ' + + 'big…').text()); + break; + default: + uploadFiles.addClass('error completed'); + totalName.text('Something went wrong; try again later.'); + } + }); + up.upload(); + }); +}); |
