diff --git a/src/_h5ai/config.js b/src/_h5ai/config.js
index 9e94c144..1ce1e655 100644
--- a/src/_h5ai/config.js
+++ b/src/_h5ai/config.js
@@ -61,11 +61,10 @@ var H5AI_CONFIG = {
},
/*
- Show a context menu when hovering a file entry.
+ Allow entry deletion.
*/
- "context-menu": {
- "enabled": true,
- "deleteBtn": true
+ "delete": {
+ "enabled": true
},
/*
diff --git a/src/_h5ai/css/inc/delete.less b/src/_h5ai/css/inc/delete.less
new file mode 100644
index 00000000..6008c9d4
--- /dev/null
+++ b/src/_h5ai/css/inc/delete.less
@@ -0,0 +1,30 @@
+
+#delete {
+ display: none;
+ .topbar-right;
+ .transition(all 0.2s ease-in-out);
+
+ &.failed {
+ background-color: rgba(255,0,0,0.5);
+ }
+}
+
+#delete-auth {
+ display: none;
+ position: fixed;
+ z-index: 5;
+ left: 0;
+ top: 0;
+ .vert-gradient(rgb(241,241,241), rgb(228,228,228));
+ border: 1px solid rgb(210,210,210);
+
+ input {
+ display: block;
+ margin: 4px 6px;
+ border: 1px solid rgb(210,210,210);
+ font-family: Ubuntu, sans-serif;
+ color: #555;
+ background-color: rgba(255,255,255,1);
+ width: 100px;
+ }
+}
diff --git a/src/_h5ai/css/styles.less b/src/_h5ai/css/styles.less
index d1e5d46d..5aa4a380 100644
--- a/src/_h5ai/css/styles.less
+++ b/src/_h5ai/css/styles.less
@@ -19,6 +19,7 @@ body {
@import "inc/topbar";
@import "inc/download";
+@import "inc/delete";
@import "inc/filter";
@import "inc/content";
diff --git a/src/_h5ai/js/inc/ext/context-menu.js b/src/_h5ai/js/inc/ext/context-menu.js
deleted file mode 100644
index d0e3942d..00000000
--- a/src/_h5ai/js/inc/ext/context-menu.js
+++ /dev/null
@@ -1,84 +0,0 @@
-
-modulejs.define('ext/context-menu', ['_', '$', 'core/settings', 'core/entry', 'core/event', 'core/resource'], function (_, $, allsettings, entry, event, resource) {
-
- var defaults = {
- enabled: false,
- deleteBtn: false
- },
-
- settings = _.extend({}, defaults, allsettings['context-menu']),
-
- template = '
',
-
- // deleteTmp = 'delete',
- deleteTmp = '
delete',
- // deleteTmp = '
',
-
-
- createDeleteBtn = function (entry, $ul) {
-
- var $del = $(deleteTmp).appendTo($ul);
-
- $del.on('click', function (event) {
-
- console.log('delete', entry.label);
- $.ajax({
- url: resource.api(),
- data: {
- action: 'delete',
- href: entry.absHref
- },
- dataType: 'json',
- success: function (json) {
-
- }
- });
- });
- },
-
- createMenu = function (entry) {
-
- var $html = $(template),
- $ul = $html.find('ul');
-
- $html.on('click', function (event) {
-
- event.stopPropagation();
- event.preventDefault();
- });
-
- createDeleteBtn(entry, $ul);
-
- entry.$extended.find('a').append($html);
- },
-
- init = function () {
-
- if (!settings.enabled) {
- return;
- }
-
- event.sub('entry.mouseenter', function (entry) {
-
- if (!entry.isFolder()) {
- var ctx = entry.$extended.find('.context-menu');
- if (ctx.length) {
- ctx.show();
- } else {
- createMenu(entry);
- }
- }
- });
-
- event.sub('entry.mouseleave', function (entry) {
-
- // entry.$extended.find('.context-menu').remove();
- entry.$extended.find('.context-menu').hide();
- });
-
- };
-
- init();
-});
diff --git a/src/_h5ai/js/inc/ext/delete.js b/src/_h5ai/js/inc/ext/delete.js
new file mode 100644
index 00000000..086c9087
--- /dev/null
+++ b/src/_h5ai/js/inc/ext/delete.js
@@ -0,0 +1,107 @@
+
+modulejs.define('ext/delete', ['_', '$', 'core/settings', 'core/entry', 'core/event', 'core/resource'], function (_, $, allsettings, entry, event, resource) {
+
+ var defaults = {
+ enabled: false
+ },
+
+ settings = _.extend({}, defaults, allsettings['delete']),
+
+ deleteBtnTemplate = '' +
+ '' +
+ '
' +
+ 'delete' +
+ '' +
+ '',
+ authTemplate = '' +
+ '' +
+ '' +
+ '
',
+
+ selectedHrefsStr = '',
+ $delete, $img, $deleteAuth, $deleteUser, $deletePassword,
+
+ failed = function () {
+
+ $delete.addClass('failed');
+ setTimeout(function () {
+ $delete.removeClass('failed');
+ }, 1000);
+ },
+
+ handleResponse = function (json) {
+
+ $delete.removeClass('current');
+ $img.attr('src', resource.image('delete'));
+
+ if (!json || json.code) {
+ if (json && json.code === 401) {
+ $deleteAuth
+ .css({
+ left: $delete.offset().left,
+ top: $delete.offset().top + $delete.outerHeight()
+ })
+ .show();
+ $deleteUser.focus();
+ }
+ failed();
+ }
+ },
+
+ requestDeletion = function (hrefsStr) {
+
+ $delete.addClass('current');
+ $img.attr('src', resource.image('loading.gif', true));
+ $.ajax({
+ url: resource.api(),
+ data: {
+ action: 'delete',
+ hrefs: hrefsStr,
+ user: $deleteUser.val(),
+ password: $deletePassword.val()
+ },
+ dataType: 'json',
+ success: handleResponse
+ });
+ },
+
+ onSelection = function (entries) {
+
+ selectedHrefsStr = '';
+ if (entries.length) {
+ selectedHrefsStr = _.map(entries, function (entry) {
+
+ return entry.absHref;
+ }).join(':');
+ $delete.appendTo('#navbar').show();
+ } else {
+ $delete.hide();
+ $deleteAuth.hide();
+ }
+ },
+
+ init = function () {
+
+ if (!settings.enabled) {
+ return;
+ }
+
+ $delete = $(deleteBtnTemplate)
+ .find('a').on('click', function (event) {
+
+ event.preventDefault();
+ $deleteAuth.hide();
+ requestDeletion(selectedHrefsStr);
+ }).end()
+ .appendTo('#navbar');
+ $img = $delete.find('img');
+
+ $deleteAuth = $(authTemplate).appendTo('body');
+ $deleteUser = $deleteAuth.find('#delete-auth-user');
+ $deletePassword = $deleteAuth.find('#delete-auth-password');
+
+ event.sub('selection', onSelection);
+ };
+
+ init();
+});
diff --git a/src/_h5ai/js/inc/main.js b/src/_h5ai/js/inc/main.js
index c7ad2afe..efe0ba0d 100644
--- a/src/_h5ai/js/inc/main.js
+++ b/src/_h5ai/js/inc/main.js
@@ -24,9 +24,9 @@
// @include "view/viewmode.js"
// @include "ext/autoupdate.js"
- // @include "ext/context-menu.js"
// @include "ext/crumb.js"
// @include "ext/custom.js"
+ // @include "ext/delete.js"
// @include "ext/download.js"
// @include "ext/dropbox.js"
// @include "ext/filter.js"
diff --git a/src/_h5ai/php/api.php b/src/_h5ai/php/api.php
index 9f44d14c..c05fd0a1 100644
--- a/src/_h5ai/php/api.php
+++ b/src/_h5ai/php/api.php
@@ -162,14 +162,25 @@ else if ($action === "upload") {
else if ($action === "delete") {
- list($href) = check_keys(array("href"));
+ json_fail(1, "deletion disabled", !$options["delete"]["enabled"]);
- $absPath = $h5ai->getAbsPath($href);
+ list($hrefs) = check_keys(array("hrefs"));
- if (unlink($absPath)) {
- json_exit();
+ $hrefs = explode(":", trim($hrefs));
+ $errors = array();
+
+ foreach ($hrefs as $href) {
+ $absPath = $h5ai->getAbsPath($href);
+
+ if (!unlink($absPath)) {
+ $errors[] = $href;
+ }
+ }
+
+ if ($errors->size) {
+ json_fail(1, "deletion failed for some");
} else {
- json_fail(1, "deletion failed");
+ json_exit();
}
}