【问题标题】:Wicket Drag and drop functionality for adding an image用于添加图像的 Wicket 拖放功能
【发布时间】:2013-11-15 19:49:35
【问题描述】:

我正在制作一个 wicket 应用程序,它可以管理 Cashdesk 应用程序的一些选项。其中一个选项是更改selected 产品的图像。

选择此选项时,用户(管理器)可以从数据库(SQL)中已经存在的图像中进行选择,或者如果不存在所需的图像,则可以添加新图像。 不要提及测试名称和很棒的图像(它仍在测试阶段)

我更喜欢看到通过拖放实现的图像添加 html5 demo [dnd-upload]
(从桌面进入浏览器)

我目前正在使用 Wicket-6.2.0wicket-dnd 0.5.0,但我似乎无法正常工作!我能找到的所有示例都来自 wicket 2.x 或更低版本。

在 Wicket-6.2 中可以使用拖放,但我该如何实现呢?

检票口中似乎有一些DraggableBehavior?欢迎任何帮助!

[更新]

升级到 wicket-dnd 0.6

【问题讨论】:

  • 不是邪恶的javascript吗?
  • @KevinEsche 不,但它使用 Javascript 来制作 ajax 行为。
  • 今天宣布了与 Wicket 6 配合使用的新的 wicket-dnd 快照版本。请尝试github.com/svenmeier/wicket-dnd
  • 我注意到 wicket-dnd 0.6 drag and drop between any Wicket components 有人知道是否可以在桌面和浏览器之间拖放吗?
  • 我自己的解决方案!明天我会添加答案,因为我还在忙着调整(已经很好用了)

标签: java drag-and-drop wicket


【解决方案1】:

根据您的代码,我编写了自定义 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);

}

【讨论】:

    【解决方案2】:

    所以这是承诺的答案! (只有代码,但如果您熟悉 wicket,则易于理解)

    该代码可以将文件拖到一个区域,并将其发送到检票口服务器(无论它获取什么文件)这并不总是您想要的(但只是我需要的)。

    如果您只想上传 1 种类型的文件,请在 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
    - 我的页面.html
    - DropZone.java
    - DropZone.html
    - DropZone.properties
    - DropAjaxBehavior
    - drop.js
    - drop.css

    使用的库:
    - jQuery.js
    - jQuery-ui.js
    - 检票口 6.2
    - slf4j-1.2.16
    - log4j-1.2.16
    - 番石榴-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));
        }
    }
    

    我的页面.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);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多