我正在制作一个wicket应用程序,可以管理cashdesk应用程序的一些选项。其中一个选项是更改selected
产品的图像。
当选择此选项时,用户(管理员)可以从数据库中已存在的图像(SQL)中进行选择,或者如果不存在所需图像,则添加新图像。 不要提及测试名称和令人敬畏的图像(它仍然在测试中)
我更喜欢看到通过拖放实现的图像添加
的 html5 demo [dnd-upload]
(从桌面进入浏览器)
我目前正在使用 Wicket-6.2.0 和 wicket-dnd 0.5.0 ,我似乎无法正常工作!我能找到的所有例子都来自wicket 2.x或更低。
可以在Wicket-6.2中使用拖放功能,但我该如何实现呢?
wicket似乎有一些DraggableBehavior?欢迎任何帮助!
[UPDATE]
升级为 wicket-dnd 0.6
答案 0 :(得分:5)
根据您的代码,我编写了自定义Ajax行为。然而,我简化了它,它在没有拖动黑客的情况下为我工作。
AbstractFileDropAjaxBehavior.java
public abstract class AbstractFileDropAjaxBehavior extends AbstractDefaultAjaxBehavior
{
@Override
protected void respond(final AjaxRequestTarget target)
{
RequestCycle requestCycle = RequestCycle.get();
StringValue data = requestCycle.getRequest().getRequestParameters().getParameterValue("data");
String[] base64Data = data.toString().split(";");
String fileName = base64Data[0].substring(base64Data[0].indexOf(':') + 1, base64Data[0].length());
String dataType = base64Data[1].substring(base64Data[1].indexOf(':') + 1, base64Data[1].length());
String binaryData = base64Data[2].substring(base64Data[2].indexOf(',') + 1, base64Data[2].length());
byte[] rawData = DatatypeConverter.parseBase64Binary(binaryData);
processFile(fileName, dataType, rawData);
}
@Override
protected void onComponentTag(ComponentTag tag) {
tag.put("my:dropcontainer.callback", getCallbackUrl().toString());
tag.put("ondragover", "return false;");
tag.put("ondrop", "return AbstractFileDropAjaxBehavior_upload(event, '#" + tag.getId() + "');");
tag.put("ondragenter", "$('#" + tag.getId() + "').addClass('dropover')");
tag.put("ondragleave", "$('#" + tag.getId() + "').removeClass('dropover')");
}
@Override
public void renderHead(Component component, IHeaderResponse response) {
super.renderHead(component, response);
response.render(OnDomReadyHeaderItem.forScript("jQuery.event.props.push('dataTransfer');"));
response.render(JavaScriptContentHeaderItem.forScript("function AbstractFileDropAjaxBehavior_upload(e, selector) {\n" +
" var files = e.dataTransfer.files;\n" +
" \n" +
" $.each(files, function(i, file) {\n" +
" var reader = new FileReader();\n" +
" \n" +
" reader.onload = function(input) {\n" +
" var fileName = \"fileName:\" + file.name + \";\";\n" +
" var base64data = input.target.result;\n" +
" \n" +
" Wicket.Ajax.post({\n" +
" \"u\": $(selector).attr('my:dropcontainer.callback'),\n" +
" \"ep\": {\n" +
" \"data\" : fileName + base64data,\n" +
" },\n" +
" });\n" +
" \n" +
" };\n" +
"\n" +
" reader.readAsDataURL(file);\n" +
" });\n" +
" \n" +
" $(selector).removeClass('dropover');\n" +
" \n" +
" return false; \n" +
"}\n", "AbstractFileDropAjaxBehavior-script"));
}
protected abstract void processFile(String fileName, String dataType, byte[] rawData);
}
答案 1 :(得分:4)
所以这是答应的答案! (只有代码,但如果您熟悉检票口则易于理解)
代码可以将文件拖到某个区域,并将其发送到wicket服务器(无论它获得什么文件),这并不总是你想要的(但只是我需要的)。
如果您只想上传一种类型的文件,请在drop.js中添加以下javascript检查:// For each file: check if files are images
for (i = 0; i < files.length; i++) {
if (!files[i].type.match('image.*')) { // Replace with what you need
$('#dropAppearance p').html('Hey! Images only');
return false;
}
}
文件:
- MyPage.java
- MyPage.html
- DropZone.java
- DropZone.html
- DropZone.properties
- DropAjaxBehavior
- drop.js
- drop.css
二手Libs:
- jQuery.js
- jQuery-ui.js
- 检票口6.2
- slf4j-1.2.16
- log4j-1.2.16
- guava-13.0.1
我没有包含导入,因为我很懒惰
MyPage.java
public final class MyPage extends Page {
/**
* Constructor
*/
public HomePage() {
}
@Override
public void onInitialize() {
super.onInitialize();
add(new DropZone("dropZone", 300, 200));
}
}
的mypage.html
<!DOCTYPE html>
<html lang="en">
<body>
<wicket:extend>
// The following line adds a DropZone
<div wicket:id="dropZone"></div>
</wicket:extend>
</body>
</html>
DropZone.java
public class DropZone extends Panel {
private static final ResourceReference JS_DROP = new JavaScriptResourceReference(DropZone.class, "drop.js");
private static final ResourceReference CSS_DROP = new CssResourceReference(DropZone.class, "drop.css");
private static final ResourceReference JQUERY = new JavaScriptResourceReference(DropZone.class, "jQuery.js");
private static final ResourceReference JQUERY_UI = new JavaScriptResourceReference(DropZone.class, "jQuery-ui.js");
private static final String ID_DROPZONE = "drop-container";
/**
* Constructor
*
* @param id String The component id
* @param height int The height of the DropZone component [in pixels]
* @param width int The width of the DropZone component [in pixels]
*/
public DropZone(String id, int width, int height) {
super(id);
final WebMarkupContainer dropZone = new WebMarkupContainer(ID_DROPZONE);
final DropAjaxBehavior dropAjaxBehavior = new DropAjaxBehavior();
dropZone.add(dropAjaxBehavior);
dropZone.add(new AttributeModifier("style", new Model<String>("width:" + width + "px;height:" + height + "px;")));
add(dropZone);
}
@Override
public final void renderHead(IHeaderResponse response) {
super.renderHead(response);
// Important to add jQuery before own javascript
response.render(JavaScriptHeaderItem.forReference(JQUERY));
response.render(JavaScriptHeaderItem.forReference(JQUERY_UI));
response.render(JavaScriptHeaderItem.forReference(JS_DROP));
response.render(CssContentHeaderItem.forReference(CSS_DROP));
}
}
DropZone.html
<html>
<body>
<wicket:panel>
<div wicket:id="drop-container" id="dropContainer">
<div id="dropAppearance">
<p>
<wicket:message key="drop-message">[DROPZONE MESSAGE]</wicket:message>
</p>
</div>
</div>
</wicket:panel>
</body>
DropZone.properties
drop-message = Drop Files Here
DropAjaxBehavior.java
public class DropAjaxBehavior extends AbstractAjaxBehavior {
private static final Logger LOG = LoggerFactory.getLogger(DropAjaxBehavior.class);
@Override
public final void onRequest() {
LOG.debug("Received request");
final RequestCycle requestCycle = RequestCycle.get();
processRequest(requestCycle);
sendResponse(requestCycle);
}
private void processRequest(RequestCycle requestCycle) {
final WebRequest wr = (WebRequest)requestCycle.getRequest();
final HttpServletRequest hsr = (HttpServletRequest)wr.getContainerRequest();
try {
final byte[] data = new byte[hsr.getContentLength()];
ByteStreams.readFully(hsr.getInputStream(), data);
// filename:<NAME>;data:<TYPE>;base64,<FILEDATA>
final String[] base64Data = new String(data).split(";");
final String fileName = base64Data[0].substring(base64Data[0].indexOf(':') + 1, base64Data[0].length());
final String dataType = base64Data[1].substring(base64Data[1].indexOf(':') + 1, base64Data[1].length());
final String binaryData = base64Data[2].substring(base64Data[2].indexOf(',') + 1, base64Data[2].length());
// [in my case] do something if the fileType is an image
if (dataType.contains("image")) {
final byte[] image = DatatypeConverter.parseBase64Binary(binaryData);
DatabaseQuery.addImage(image, fileName);
}
// But you can make a local file
// final File file = new File(fileName);
// final ByteArrayInputStream binaryInputstream = new ByteArrayInputStream(image);
// final FileOutputStream outputStream = new FileOutputStream(file);
// ByteStreams.copy(binaryInputstream, outputStream);
// outputStream.close();
} catch (IOException ioe) {
LOG.error("IO error while reading HttpServletRequest: ", ioe);
}
}
private void sendResponse(RequestCycle requestCycle) {
// Just some response
requestCycle.scheduleRequestHandlerAfterCurrent(new TextRequestHandler("text/html", "UTF-8", "done"));
}
@Override
protected final void onComponentTag(ComponentTag tag) {
tag.put("my:dropcontainer.callback", getCallbackUrl().toString());
}
}
drop.css
#dropContainer {
background-color: #FFFFFF;
border: 4px dashed #C9C9C9;
-moz-box-sizing: border-box;
box-sizing: border-box;
position: absolute;
}
#dropAppearance {
height: 100%;
width: 100%;
display: table;
box-sizing: border-box;
}
#dropAppearance p {
display: table-cell;
vertical-align: middle;
text-align: center;
font-size: 2em;
color: #797979;
}
drop.js
$(document).ready(
function() {
// Makes sure the dataTransfer information is sent when we
// Drop the item in the drop box.
jQuery.event.props.push('dataTransfer');
// As far as i know Firefox needs to cancel this event (otherwise it
// opens
// dropped files in the browser)
$('#dropContainer').attr('ondragover', "return false");
$('#dropContainer').bind(
'drop',
function(e) {
// Files that have been dragged into the drop area
var files = e.dataTransfer.files;
// Upload each file
$.each(files, function(i, file) {
var reader = new FileReader();
reader.onload = function(input) {
var fileName = "fileName:" + file.name + ";";
var base64data = input.target.result;
$.ajax({
url : $('#dropContainer').attr(
'my:dropcontainer.callback'),
type : 'post',
cache : false,
// Add date before raw base64 file data
data : fileName + base64data,
processData : false,
contentType : false,
});
};
// decode into base64
reader.readAsDataURL(file);
});
return false;
});
// Using little dragging hack because of the HTML5 spec problem
// URL:
// http://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html
// works like:
// <parent element>
// dragging = 0
// <drop_container>
// dragging = 1
// <child>
// dragging = 2
// </child>
// dragging = 1
// </drop_container>
// dragging = 0
// </parent element>
var dragging = 0;
$('#dropContainer').bind('dragenter', function() {
dragging++;
setHoverDropContainer();
return false;
});
$('#dropContainer').bind('dragleave', function() {
dragging--;
if (dragging === 0) {
resetHoverDropContainer();
}
return false;
});
$('#dropContainer').bind('drop', function() {
dragging = 0; // reset dragging hack
resetHoverDropContainer();
return false;
});
});
function setHoverDropContainer() {
// change colors with smooth transition
setCSS('#dropContainer', {
'border-color' : '#0000FF',
'background-color' : '#EDF4FE',
'-webkit-transition' : 'background-color 0.6s ease',
'-moz-transition' : 'background-color 0.6s ease',
'-o-transition' : 'background-color 0.6s ease',
'transition' : 'background-color 0.6s ease',
'-webkit-transition' : 'border-color 0.6s ease',
'-moz-transition' : 'border-color 0.6s ease',
'-o-transition' : 'border-color 0.6s ease',
'transition' : 'border-color 0.6s ease'
});
}
function resetHoverDropContainer() {
// change colors with smooth transition
setCSS('#dropContainer', {
'border-color' : '#C9C9C9',
'background-color' : '#FFFFFF',
'-webkit-transition' : 'background-color 0.6s ease',
'-moz-transition' : 'background-color 0.6s ease',
'-o-transition' : 'background-color 0.6s ease',
'transition' : 'background-color 0.6s ease',
'-webkit-transition' : 'border-color 0.6s ease',
'-moz-transition' : 'border-color 0.6s ease',
'-o-transition' : 'border-color 0.6s ease',
'transition' : 'border-color 0.6s ease'
});
}
function setCSS(element, values) {
$(element).css(values);
}
}