【问题标题】:Vaadin - run client side javascript after image fully loadedVaadin - 图像完全加载后运行客户端javascript
【发布时间】:2017-04-25 14:43:31
【问题描述】:

我需要在客户端打印一张图片。我使用this 作为模板。我的 PrintUI 如下所示:

@Override
protected void init(VaadinRequest request) {
    Item item = ..get item ..

    StreamResource imageStream = ... build image dynamically ...
    Image image = new Image(item.getName(), imageStream);
    image.setWidth("100%");
    setContent(image);
    setWidth("100%");

    // Print automatically when the window opens
    JavaScript.getCurrent().execute("setTimeout(function() {print(); self.close();}, 0);");
}

到目前为止,这在 IE 中有效,但在 chrome 中,它会打开显示空白页面的打印预览。问题是图像以某种方式加载,chrome 不会等待它并立即开始打印预览。

为了验证这一点,我尝试了:(设置 5 秒超时)

JavaScript.getCurrent().execute("setTimeout(function() {print(); self.close();}, 0);");

然后它可以在 IE 和 Chrome 中运行,但它当然是一个丑陋的 hack,如果连接速度低于 5 秒,那么它会再次失败。

在纯 JS 中它会像 this 一样工作,但我不确定如何在 cient-side js 中引用来自 vaadin 的元素。有任何想法吗?

【问题讨论】:

    标签: spring-boot vaadin vaadin4spring


    【解决方案1】:

    您可以使用AbstractJavascriptExtension

    示例扩展类:

    @JavaScript({ "vaadin://scripts/connector/wait_for_image_load_connector.js" })
    public class WaitForImageLoadExtension extends AbstractJavaScriptExtension {
    
        private List<ImageLoadedListener> imageLoadedListeners = new ArrayList<>();
    
        public interface ImageLoadedListener {
            void onImageLoaded();
        }
    
        public void extend(Image image) {
            super.extend(image);
            addFunction("onImageLoaded", new JavaScriptFunction() {
    
                @Override
                public void call(JsonArray arguments) {
                    for (ImageLoadedListener imageLoadedListener : imageLoadedListeners) {
                        if (imageLoadedListener != null) {
                            imageLoadedListener.onImageLoaded();
                        }
                    }
                }
            });
        }
    
        public void addImageLoadedListener(ImageLoadedListener listener) {
            imageLoadedListeners.add(listener);
        }
    }
    

    和 javascript 连接器(放置在 wait_for_image_load_connector.js 中)与您拥有的等待方法 linked:

    window.your_package_WaitForImageLoadExtension = function() {
            var connectorId = this.getParentId();
            var img = this.getElement(connectorId);
    
            if (img.complete) {
                this.onImageLoaded();
            } else {
                img.addEventListener('load', this.onImageLoaded)
                img.addEventListener('error', function() {
                    alert('error');
                })
            }
    
        }
    

    然后你可以这样做:

    Image image = new Image(item.getName(), imageStream);
    
    WaitForImageLoadExtension ext = new WaitForImageLoadExtension();
    ext.extend(image);
    ext.addImageLoadedListener(new ImageLoadedListener() {
    
        @Override
        public void onImageLoaded() {
            JavaScript.eval("print()");
        }
    });
    

    在您的情况下,当调用 print() 是您在加载图像后唯一想做的事情时,您也可以在连接器中调用它而无需服务器端侦听器:

    if (img.complete) {
        print();
    } else {
        img.addEventListener('load', print)
        img.addEventListener('error', function() {
            alert('error');
        })
    }
    

    【讨论】:

    • 很好的答案! @JavaScript({ ..... 是做什么的?或者我可以在哪里了解更多信息?
    • @petey @JavaScript 是一个 vaadin 注释,它告诉框架在加载带注释的连接器之前加载特定的 JS 文件。在这个例子中,它告诉加载wait_for_image_load_connector.js,如果有任何组件被WaitForImageLoadExtension 扩展扩展。您可以在this tutorialofficial docs 中了解更多信息。
    猜你喜欢
    • 1970-01-01
    • 2016-10-11
    • 1970-01-01
    • 1970-01-01
    • 2020-08-27
    • 2010-11-18
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    相关资源
    最近更新 更多