From d76fad3a51727fa3f86ab94a7414c0e1976bb129 Mon Sep 17 00:00:00 2001 From: Lars Jung Date: Thu, 9 Aug 2012 11:34:20 +0200 Subject: [PATCH] Adds drag'n'drop upload. --- src/_h5ai/config.js | 6 +- src/_h5ai/css/inc/dropbox.less | 100 +++++ src/_h5ai/css/inc/preview-img.less | 11 + src/_h5ai/css/styles.less | 1 + src/_h5ai/images/delete.png | Bin 0 -> 616 bytes src/_h5ai/js/inc/ext/dropbox.js | 139 +++++++ src/_h5ai/js/inc/ext/preview-img.js | 29 +- src/_h5ai/js/inc/ext/preview-txt.js | 30 +- src/_h5ai/js/inc/ext/thumbnails.js | 7 +- src/_h5ai/js/inc/main.js | 1 + src/_h5ai/js/inc/view/extended.js | 2 +- src/_h5ai/js/lib/jquery.filedrop-0.1.0.js | 424 ++++++++++++++++++++++ src/_h5ai/js/scripts.js | 1 + src/_h5ai/php/api.php | 35 ++ src/_h5ai/uploads/README.md | 7 + 15 files changed, 766 insertions(+), 27 deletions(-) create mode 100644 src/_h5ai/css/inc/dropbox.less create mode 100644 src/_h5ai/images/delete.png create mode 100644 src/_h5ai/js/inc/ext/dropbox.js create mode 100755 src/_h5ai/js/lib/jquery.filedrop-0.1.0.js create mode 100644 src/_h5ai/uploads/README.md diff --git a/src/_h5ai/config.js b/src/_h5ai/config.js index bb64c0fa..86dc8053 100644 --- a/src/_h5ai/config.js +++ b/src/_h5ai/config.js @@ -60,7 +60,7 @@ var H5AI_CONFIG = { */ "autoupdate": { "enabled": true, - "interval": 5000 + "interval": 1000 }, /* @@ -213,7 +213,7 @@ var H5AI_CONFIG = { "java": "java", "makefile": "xml", "markdown": "plain", - "php": "php", + /*"php": "php",*/ "python": "python", "readme": "plain", "rb": "ruby", @@ -331,7 +331,7 @@ var H5AI_CONFIG = { "hpp": [".hpp"], "html": [".htm", ".html", ".shtml"], "ico": [".ico"], - "image": [".xpm"], + "image": [".svg", ".xpm"], "install": ["install"], "java": [".java"], "jpg": [".jpg", ".jpeg"], diff --git a/src/_h5ai/css/inc/dropbox.less b/src/_h5ai/css/inc/dropbox.less new file mode 100644 index 00000000..d87a2f6c --- /dev/null +++ b/src/_h5ai/css/inc/dropbox.less @@ -0,0 +1,100 @@ + +#dropbox { + margin: 48px 24px; + padding: 24px 12px; + overflow: hidden; + + background-color: #f8f8f8; + border: 1px dashed #ccc; + border-radius: 10px; + + .transition(all 0.2s ease-in-out); + + .label { + text-align: center; + color: #eee; + font-size: 5em; + font-weight: bold; + } + + &.hint { + // color: #ccc; + // border-color: #aaa; + } + + &.match { + border-color: #555; + + .label { + color: #999; + } + } +} + +#uploads { + width: 450px; + margin: 12px auto; + padding: 0; + list-style: none; + + .upload { + color: #555; + font-size: 0.9em; + + .name { + display: inline-block; + white-space: nowrap; + width: 320px; + overflow: hidden; + + &:before { + display: inline-block; + content: '•'; + color: #55c; + width: 1em; + text-align: center; + padding-right: 1em; + } + } + + .size { + // display: inline-block; + display: none; + float: right; + white-space: nowrap; + + &:after { + content: ' bytes' + } + } + + .progress { + display: inline-block; + margin: 4px 8px; + + width: 84px; + height: 8px; + background-color: #ddd; + overflow: hidden; + float: right; + + .bar { + width: 0%; + height: 100%; + background-color: #999; + } + } + + &.finished .name:before { + // content: '✓✔'; + content: '✔'; + color: #008200; + } + &.error .name:before { + content: '✖'; + color: #c55; + } + } + +} + diff --git a/src/_h5ai/css/inc/preview-img.less b/src/_h5ai/css/inc/preview-img.less index 7e6f9540..6946de74 100644 --- a/src/_h5ai/css/inc/preview-img.less +++ b/src/_h5ai/css/inc/preview-img.less @@ -18,11 +18,22 @@ } +// @check-white: rgba(255,255,255,0.5); +// @check-black: rgba(0,0,0,0.2); +@check-white: #f8f8f8; +@check-black: #e8e8e8; #pv-img-image { max-width: 100%; max-height: 100%; border: 2px solid #fff; .border-radius(4px); + + background-color: @check-white; + background-image: + -webkit-linear-gradient(45deg, @check-black 25%, transparent 25%, transparent 75%, @check-black 75%, @check-black), + -webkit-linear-gradient(45deg, @check-black 25%, transparent 25%, transparent 75%, @check-black 75%, @check-black); + background-size: 60px 60px; + background-position: 0 0, 30px 30px } #pv-img-overlay.fullscreen { diff --git a/src/_h5ai/css/styles.less b/src/_h5ai/css/styles.less index 39281b71..427acd71 100644 --- a/src/_h5ai/css/styles.less +++ b/src/_h5ai/css/styles.less @@ -23,6 +23,7 @@ body { @import "inc/content"; @import "inc/extended"; +@import "inc/dropbox"; @import "inc/bottombar"; @import "inc/l10n"; diff --git a/src/_h5ai/images/delete.png b/src/_h5ai/images/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..9d8afaef4d4ffccb64e545646b2d9f33ab7c0e3c GIT binary patch literal 616 zcmV-u0+;=XP)NB#Epidy%J1W{)3X5}5#^IHZUR05b?N5Wi}Np!0bGUwV#lekRQ3D$Zo|m} zK)dGy03@CR00@d|WlA3kQB^Ag_!$NOfYfoEhxXG4`OdfBkl{q*s+D~Ez7SQ_3V`;g z5Pj#=vTL3<%@~j1);w?8Ikjv6{-_qjdc{m1Z>$yNzPB*R1O!*^dke=KYsGrS9JcdU z3yF7`JEi$pG;@Oq008cmYyp7(y_p4oAJ<)+Uv;Was$cbCh`|@QOIthpT0G`5CP19k zEP3~^AnzU)#97T^On?@Txl3C+`vBZOE+Pu' + + '
' + + '' + + '', + + init = function () { + + if (!settings.enabled) { + return; + } + + var $dropbox = $(template).appendTo('#content'); + + var uploads = {}; + + $dropbox.filedrop({ + + // The name of the $_FILES entry: + paramname: 'userfile', + + maxfiles: 24, + maxfilesize: 1024, + url: allsettings.h5aiAbsHref + 'php/api.php', + data: { + action: 'upload', + href: entry.absHref + }, + + dragOver: function () { + + $dropbox.addClass('match'); + }, + + dragLeave: function () { + + $dropbox.removeClass('match'); + }, + + docOver: function () { + + $dropbox.addClass('hint'); + }, + + docLeave: function () { + + $dropbox.removeClass('hint'); + }, + + drop: function () { + + $dropbox.removeClass('match hint'); + }, + + + beforeEach: function (file) { + + uploads[file.name] = $(uploadTemplate).appendTo('#uploads') + .find('.name').text(file.name).end() + .find('.size').text(file.size).end() + .find('.progress .bar').css('width', 0).end(); + + console.log('beforeEach', file); + }, + + uploadStarted: function (i, file, len) { + + console.log('uploadStarted', i, file, len); + }, + + progressUpdated: function (i, file, progress) { + + uploads[file.name] + .find('.progress .bar').css('width', '' + progress + '%'); + console.log('progressUpdated', i, file, progress); + }, + + uploadFinished: function (i, file, response) { + + uploads[file.name].addClass(response.code ? 'error' : 'finished'); + setTimeout(function () { + uploads[file.name].slideUp(400, function () { + + uploads[file.name].remove(); + }); + }, 5000); + console.log('uploadFinished', i, file, response); + }, + + afterAll: function () { + + // $('#uploads .upload').remove(); + }, + + + error: function (err, file) { + + uploads[file.name].addClass('error'); + setTimeout(function () { + uploads[file.name].slideUp(400, function () { + + uploads[file.name].remove(); + }); + }, 5000); + switch (err) { + case 'BrowserNotSupported': + console.log('ERROR', 'Your browser does not support HTML5 file uploads!'); + break; + case 'TooManyFiles': + console.log('ERROR', 'Too many files! Please select 5 at most! (configurable)'); + break; + case 'FileTooLarge': + console.log('ERROR', file.name + ' is too large! Please upload files up to 2mb (configurable).'); + break; + default: + break; + } + console.log('error', err, file); + } + }); + + + + + }; + + init(); +}); diff --git a/src/_h5ai/js/inc/ext/preview-img.js b/src/_h5ai/js/inc/ext/preview-img.js index 1ae586e2..64c50a71 100644 --- a/src/_h5ai/js/inc/ext/preview-img.js +++ b/src/_h5ai/js/inc/ext/preview-img.js @@ -1,5 +1,5 @@ -modulejs.define('ext/preview-img', ['_', '$', 'core/settings', 'core/resource', 'core/store', 'core/entry'], function (_, $, allsettings, resource, store, entry) { +modulejs.define('ext/preview-img', ['_', '$', 'core/settings', 'core/resource', 'core/store', 'core/event', 'core/entry'], function (_, $, allsettings, resource, store, event, entry) { var defaults = { enabled: false, @@ -149,7 +149,6 @@ modulejs.define('ext/preview-img', ['_', '$', 'core/settings', 'core/resource', $('#pv-img-bar-original').find('a').attr('href', currentEntries[currentIdx].absHref); }, 1); }); - }); }, @@ -201,13 +200,20 @@ modulejs.define('ext/preview-img', ['_', '$', 'core/settings', 'core/resource', } }, - initEntry = function (entries, entry, idx) { + initEntry = function (entry) { - if (entry.$extended) { + if (entry.$extended && _.indexOf(settings.types, entry.type) >= 0) { entry.$extended.find('a').on('click', function (event) { event.preventDefault(); - onEnter(entries, idx); + + var matchedEntries = _.compact(_.map($('#extended .entry'), function (entry) { + + entry = $(entry).data('entry'); + return _.indexOf(settings.types, entry.type) >= 0 ? entry : null; + })); + + onEnter(matchedEntries, _.indexOf(matchedEntries, entry)); }); } }, @@ -218,13 +224,9 @@ modulejs.define('ext/preview-img', ['_', '$', 'core/settings', 'core/resource', return; } - var imageEntries = _.filter(entry.content, function (entry) { + _.each(entry.content, function (e) { - return _.indexOf(settings.types, entry.type) >= 0; - }); - _.each(imageEntries, function (e, idx) { - - initEntry(imageEntries, e, idx); + initEntry(e); }); $(template).appendTo('body'); @@ -277,6 +279,11 @@ modulejs.define('ext/preview-img', ['_', '$', 'core/settings', 'core/resource', } }); + event.sub('entry.created', function (entry) { + + initEntry(entry); + }); + $(window).on('resize load', adjustSize); }; diff --git a/src/_h5ai/js/inc/ext/preview-txt.js b/src/_h5ai/js/inc/ext/preview-txt.js index 8463e073..cfc6429b 100644 --- a/src/_h5ai/js/inc/ext/preview-txt.js +++ b/src/_h5ai/js/inc/ext/preview-txt.js @@ -1,5 +1,5 @@ -modulejs.define('ext/preview-txt', ['_', '$', 'core/settings', 'core/resource', 'core/store', 'core/entry'], function (_, $, allsettings, resource, store, entry) { +modulejs.define('ext/preview-txt', ['_', '$', 'core/settings', 'core/resource', 'core/store', 'core/event', 'core/entry'], function (_, $, allsettings, resource, store, event, entry) { var defaults = { enabled: false, @@ -16,7 +16,7 @@ modulejs.define('ext/preview-txt', ['_', '$', 'core/settings', 'core/resource', java: 'java', makefile: 'xml', markdown: 'plain', - php: 'php', + // php: 'php', python: 'python', readme: 'plain', rb: 'ruby', @@ -207,13 +207,20 @@ modulejs.define('ext/preview-txt', ['_', '$', 'core/settings', 'core/resource', } }, - initEntry = function (entries, entry, idx) { + initEntry = function (entry) { - if (entry.$extended) { + if (entry.$extended && _.indexOf(_.keys(settings.types), entry.type) >= 0) { entry.$extended.find('a').on('click', function (event) { event.preventDefault(); - onEnter(entries, idx); + + var matchedEntries = _.compact(_.map($('#extended .entry'), function (entry) { + + entry = $(entry).data('entry'); + return _.indexOf(_.keys(settings.types), entry.type) >= 0 ? entry : null; + })); + + onEnter(matchedEntries, _.indexOf(matchedEntries, entry)); }); } }, @@ -224,13 +231,9 @@ modulejs.define('ext/preview-txt', ['_', '$', 'core/settings', 'core/resource', return; } - var imageEntries = _.filter(entry.content, function (entry) { + _.each(entry.content, function (e) { - return _.indexOf(_.keys(settings.types), entry.type) >= 0; - }); - _.each(imageEntries, function (e, idx) { - - initEntry(imageEntries, e, idx); + initEntry(e); }); $(template).appendTo('body'); @@ -254,6 +257,11 @@ modulejs.define('ext/preview-txt', ['_', '$', 'core/settings', 'core/resource', event.stopPropagation(); }); + event.sub('entry.created', function (entry) { + + initEntry(entry); + }); + $(window).on('resize load', adjustSize); }; diff --git a/src/_h5ai/js/inc/ext/thumbnails.js b/src/_h5ai/js/inc/ext/thumbnails.js index 468e5a37..8bd87fdc 100644 --- a/src/_h5ai/js/inc/ext/thumbnails.js +++ b/src/_h5ai/js/inc/ext/thumbnails.js @@ -1,5 +1,5 @@ -modulejs.define('ext/thumbnails', ['_', 'core/settings', 'core/entry', 'core/ajax'], function (_, allsettings, entry, ajax) { +modulejs.define('ext/thumbnails', ['_', 'core/settings', 'core/entry', 'core/event', 'core/ajax'], function (_, allsettings, entry, event, ajax) { var defaults = { enabled: false, @@ -52,6 +52,11 @@ modulejs.define('ext/thumbnails', ['_', 'core/settings', 'core/entry', 'core/aja _.each(entry.content, checkEntry); }, settings.delay); + + event.sub('entry.created', function (entry) { + + checkEntry(entry); + }); }; init(entry); diff --git a/src/_h5ai/js/inc/main.js b/src/_h5ai/js/inc/main.js index e192f2db..6821c3e2 100644 --- a/src/_h5ai/js/inc/main.js +++ b/src/_h5ai/js/inc/main.js @@ -27,6 +27,7 @@ // @include "ext/crumb.js" // @include "ext/custom.js" // @include "ext/download.js" + // @include "ext/dropbox.js" // @include "ext/filter.js" // @include "ext/folderstatus.js" // @include "ext/google-analytics.js" diff --git a/src/_h5ai/js/inc/view/extended.js b/src/_h5ai/js/inc/view/extended.js index 5f561c2f..f8ff27bd 100644 --- a/src/_h5ai/js/inc/view/extended.js +++ b/src/_h5ai/js/inc/view/extended.js @@ -18,7 +18,7 @@ modulejs.define('view/extended', ['_', '$', 'core/settings', 'core/resource', 'c '' + '', hintTemplate = '', - listTemplate = '
    ' + + listTemplate = '
      ' + '
    • ' + '' + '' + diff --git a/src/_h5ai/js/lib/jquery.filedrop-0.1.0.js b/src/_h5ai/js/lib/jquery.filedrop-0.1.0.js new file mode 100755 index 00000000..2d87013b --- /dev/null +++ b/src/_h5ai/js/lib/jquery.filedrop-0.1.0.js @@ -0,0 +1,424 @@ +/* + * Default text - jQuery plugin for html5 dragging files from desktop to browser + * + * Author: Weixi Yen + * + * Email: [Firstname][Lastname]@gmail.com + * + * Copyright (c) 2010 Resopollution + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/mit-license.php + * + * Project home: + * http://www.github.com/weixiyen/jquery-filedrop + * + * Version: 0.1.0 + * + * Features: + * Allows sending of extra parameters with file. + * Works with Firefox 3.6+ + * Future-compliant with HTML5 spec (will work with Webkit browsers and IE9) + * Usage: + * See README at project homepage + * + */ +;(function($) { + + jQuery.event.props.push("dataTransfer"); + + var default_opts = { + fallback_id: '', + url: '', + refresh: 1000, + paramname: 'userfile', + allowedfiletypes:[], + maxfiles: 25, // Ignored if queuefiles is set > 0 + maxfilesize: 1, // MB file size limit + queuefiles: 0, // Max files before queueing (for large volume uploads) + queuewait: 200, // Queue wait time if full + data: {}, + headers: {}, + drop: empty, + dragEnter: empty, + dragOver: empty, + dragLeave: empty, + docEnter: empty, + docOver: empty, + docLeave: empty, + beforeEach: empty, + afterAll: empty, + rename: empty, + error: function(err, file, i) { + alert(err); + }, + uploadStarted: empty, + uploadFinished: empty, + progressUpdated: empty, + speedUpdated: empty + }, + errors = ["BrowserNotSupported", "TooManyFiles", "FileTooLarge", "FileTypeNotAllowed"], + doc_leave_timer, stop_loop = false, + files_count = 0, + files; + + $.fn.filedrop = function(options) { + var opts = $.extend({}, default_opts, options); + + this.on('drop', drop).on('dragenter', dragEnter).on('dragover', dragOver).on('dragleave', dragLeave); + $(document).on('drop', docDrop).on('dragenter', docEnter).on('dragover', docOver).on('dragleave', docLeave); + + $('#' + opts.fallback_id).change(function(e) { + opts.drop(e); + files = e.target.files; + files_count = files.length; + upload(); + }); + + function drop(e) { + opts.drop(e); + files = e.dataTransfer.files; + if (files === null || files === undefined) { + opts.error(errors[0]); + return false; + } + files_count = files.length; + upload(); + e.preventDefault(); + return false; + } + + function getBuilder(filename, filedata, mime, boundary) { + var dashdash = '--', + crlf = '\r\n', + builder = ''; + + if (opts.data) { + var params = $.param(opts.data).split(/&/); + + $.each(params, function() { + var pair = this.split(/=/, 2); + var name = decodeURIComponent(pair[0]); + var val = decodeURIComponent(pair[1]); + + builder += dashdash; + builder += boundary; + builder += crlf; + builder += 'Content-Disposition: form-data; name="' + name + '"'; + builder += crlf; + builder += crlf; + builder += val; + builder += crlf; + }); + } + + builder += dashdash; + builder += boundary; + builder += crlf; + builder += 'Content-Disposition: form-data; name="' + opts.paramname + '"'; + builder += '; filename="' + filename + '"'; + builder += crlf; + + builder += 'Content-Type: ' + mime; + builder += crlf; + builder += crlf; + + builder += filedata; + builder += crlf; + + builder += dashdash; + builder += boundary; + builder += dashdash; + builder += crlf; + return builder; + } + + function progress(e) { + if (e.lengthComputable) { + var percentage = Math.round((e.loaded * 100) / e.total); + if (this.currentProgress != percentage) { + + this.currentProgress = percentage; + opts.progressUpdated(this.index, this.file, this.currentProgress); + + var elapsed = new Date().getTime(); + var diffTime = elapsed - this.currentStart; + if (diffTime >= opts.refresh) { + var diffData = e.loaded - this.startData; + var speed = diffData / diffTime; // KB per second + opts.speedUpdated(this.index, this.file, speed); + this.startData = e.loaded; + this.currentStart = elapsed; + } + } + } + } + + // Respond to an upload + function upload() { + + stop_loop = false; + + if (!files) { + opts.error(errors[0]); + return false; + } + if(opts.allowedfiletypes.push && opts.allowedfiletypes.length){ + for(var fileIndex = files.length;fileIndex--;){ + if(!files[fileIndex].type || $.inArray(files[fileIndex].type, opts.allowedfiletypes) < 0){ + opts.error(errors[3]); + return false; + } + } + } + + var filesDone = 0, + filesRejected = 0; + + if (files_count > opts.maxfiles && opts.queuefiles === 0) { + opts.error(errors[1]); + return false; + } + + // Define queues to manage upload process + var workQueue = []; + var processingQueue = []; + var doneQueue = []; + + // Add everything to the workQueue + for (var i = 0; i < files_count; i++) { + workQueue.push(i); + } + + // Helper function to enable pause of processing to wait + // for in process queue to complete + var pause = function(timeout) { + setTimeout(process, timeout); + return; + } + + // Process an upload, recursive + var process = function() { + + var fileIndex; + + if (stop_loop) return false; + + // Check to see if are in queue mode + if (opts.queuefiles > 0 && processingQueue.length >= opts.queuefiles) { + + return pause(opts.queuewait); + + } else { + + // Take first thing off work queue + fileIndex = workQueue[0]; + workQueue.splice(0, 1); + + // Add to processing queue + processingQueue.push(fileIndex); + + } + + try { + if (beforeEach(files[fileIndex]) != false) { + if (fileIndex === files_count) return; + var reader = new FileReader(), + max_file_size = 1048576 * opts.maxfilesize; + + reader.index = fileIndex; + if (files[fileIndex].size > max_file_size) { + opts.error(errors[2], files[fileIndex], fileIndex); + // Remove from queue + processingQueue.forEach(function(value, key) { + if (value === fileIndex) processingQueue.splice(key, 1); + }); + filesRejected++; + return true; + } + reader.onloadend = send; + reader.readAsBinaryString(files[fileIndex]); + + } else { + filesRejected++; + } + } catch (err) { + // Remove from queue + processingQueue.forEach(function(value, key) { + if (value === fileIndex) processingQueue.splice(key, 1); + }); + opts.error(errors[0]); + return false; + } + + // If we still have work to do, + if (workQueue.length > 0) { + process(); + } + + }; + + var send = function(e) { + + var fileIndex = ((typeof(e.srcElement) === "undefined") ? e.target : e.srcElement).index + + // Sometimes the index is not attached to the + // event object. Find it by size. Hack for sure. + if (e.target.index == undefined) { + e.target.index = getIndexBySize(e.total); + } + + var xhr = new XMLHttpRequest(), + upload = xhr.upload, + file = files[e.target.index], + index = e.target.index, + start_time = new Date().getTime(), + boundary = '------multipartformboundary' + (new Date).getTime(), + builder; + + newName = rename(file.name); + mime = file.type + if (typeof newName === "string") { + builder = getBuilder(newName, e.target.result, mime, boundary); + } else { + builder = getBuilder(file.name, e.target.result, mime, boundary); + } + + upload.index = index; + upload.file = file; + upload.downloadStartTime = start_time; + upload.currentStart = start_time; + upload.currentProgress = 0; + upload.startData = 0; + upload.addEventListener("progress", progress, false); + + xhr.open("POST", opts.url, true); + xhr.setRequestHeader('content-type', 'multipart/form-data; boundary=' + boundary); + + // Add headers + $.each(opts.headers, function(k, v) { + xhr.setRequestHeader(k, v); + }); + + xhr.sendAsBinary(builder); + + opts.uploadStarted(index, file, files_count); + + xhr.onload = function() { + if (xhr.responseText) { + var now = new Date().getTime(), + timeDiff = now - start_time, + result = opts.uploadFinished(index, file, jQuery.parseJSON(xhr.responseText), timeDiff, xhr); + filesDone++; + + // Remove from processing queue + processingQueue.forEach(function(value, key) { + if (value === fileIndex) processingQueue.splice(key, 1); + }); + + // Add to donequeue + doneQueue.push(fileIndex); + + if (filesDone == files_count - filesRejected) { + afterAll(); + } + if (result === false) stop_loop = true; + } + + //Pass any errors to the error option + if(xhr.status != 200){ + opts.error(xhr.statusText); + } + + }; + + } + + // Initiate the processing loop + process(); + + } + + function getIndexBySize(size) { + for (var i = 0; i < files_count; i++) { + if (files[i].size == size) { + return i; + } + } + + return undefined; + } + + function rename(name) { + return opts.rename(name); + } + + function beforeEach(file) { + return opts.beforeEach(file); + } + + function afterAll() { + return opts.afterAll(); + } + + function dragEnter(e) { + clearTimeout(doc_leave_timer); + e.preventDefault(); + opts.dragEnter(e); + } + + function dragOver(e) { + clearTimeout(doc_leave_timer); + e.preventDefault(); + opts.docOver(e); + opts.dragOver(e); + } + + function dragLeave(e) { + clearTimeout(doc_leave_timer); + opts.dragLeave(e); + e.stopPropagation(); + } + + function docDrop(e) { + e.preventDefault(); + opts.docLeave(e); + return false; + } + + function docEnter(e) { + clearTimeout(doc_leave_timer); + e.preventDefault(); + opts.docEnter(e); + return false; + } + + function docOver(e) { + clearTimeout(doc_leave_timer); + e.preventDefault(); + opts.docOver(e); + return false; + } + + function docLeave(e) { + doc_leave_timer = setTimeout(function() { + opts.docLeave(e); + }, 200); + } + return this; + }; + function empty() {} + + try { + if (XMLHttpRequest.prototype.sendAsBinary) return; + XMLHttpRequest.prototype.sendAsBinary = function(datastr) { + function byteValue(x) { + return x.charCodeAt(0) & 0xff; + } + var ords = Array.prototype.map.call(datastr, byteValue); + var ui8a = new Uint8Array(ords); + this.send(ui8a.buffer); + } + } catch (e) {} + +})(jQuery); diff --git a/src/_h5ai/js/scripts.js b/src/_h5ai/js/scripts.js index 2ce2f379..74f4beef 100644 --- a/src/_h5ai/js/scripts.js +++ b/src/_h5ai/js/scripts.js @@ -2,6 +2,7 @@ // jQuery libs // ----------- // @include "lib/jquery-1.7.2.min.js" +// @include "lib/jquery.filedrop-0.1.0.js" // @include "lib/jquery.fracs-0.11.min.js" // @include "lib/jquery.mousewheel-3.0.6.js" // @include "lib/jquery.qrcode-0.2.min.js" diff --git a/src/_h5ai/php/api.php b/src/_h5ai/php/api.php index e3d1a73a..306c405d 100644 --- a/src/_h5ai/php/api.php +++ b/src/_h5ai/php/api.php @@ -138,6 +138,41 @@ else if ($action === "getentries") { } +else if ($action === "upload") { + + list($href) = check_keys(array("href")); + + json_fail(1, "wrong HTTP method", strtolower($_SERVER["REQUEST_METHOD"]) !== "post"); + json_fail(2, "something went wrong", !array_key_exists("userfile", $_FILES)); + + $userfile = $_FILES["userfile"]; + + json_fail(3, "something went wrong: " . $userfile["error"], $userfile["error"] !== 0); + + $upload_dir = $h5ai->getAbsPath($href); + $dest = $upload_dir . "/" . $userfile["name"]; + + json_fail(4, "already exists: " . $userfile["name"], file_exists($dest)); + json_fail(5, "can't move uploaded file", !move_uploaded_file($userfile["tmp_name"], $dest)); + + json_exit(); +} + + +else if ($action === "delete") { + + list($href) = check_keys(array("href")); + + $absPath = $h5ai->getAbsPath($href); + + if (unlink($absPath)) { + json_exit(); + } else { + json_fail(1, "deletion failed"); + } +} + + else { json_fail(100, "unsupported action"); } diff --git a/src/_h5ai/uploads/README.md b/src/_h5ai/uploads/README.md new file mode 100644 index 00000000..f0fbb3dc --- /dev/null +++ b/src/_h5ai/uploads/README.md @@ -0,0 +1,7 @@ +# Cache + +This directory is used for server side caching. To use caching make this +directory writable for your webserver. + +There is no critical data in here. You can savely remove any content. This +will clear the cache.