Vaadin - 运行 客户端 javascript 图像完全加载后

Vaadin - run client side javascript after image fully loaded

我需要在客户端打印图片。我使用 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 的元素。有任何想法吗?

您可以使用 AbstractJavascriptExtension.

示例扩展 class:

@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');
    })
}