2

I'm developing a web app at the moment, and, being a perfectionist, I try to make it all shiny and compliant with all the standards. As far as I know, the <img> tag is to be deprecated in the upcoming standards for xHTML, and as nowadays even IE is able to handle <object> properly, I wanted to use the <object> tag for all the images on my site.

Now, I need to preload some of my images for standard onmouseover swapping. It was no problem with <img>:

var rateImagesURLs = new Array("images/mark0.png", "images/mark1.png");
var rateImages = new Array(rateImagesURLs.length);

for (var i=0;i<rateImagesURLs.length;++i) {
    rateImages[i] = new Image();
    rateImages[i].src = rateImagesURLs[i];
}

but I can't get it to work with <object>. I just can't find a way to connect JavaScript's Image object to actual <object> tag. I tried playing with <object>'s data, as well as archive attribute, but even the guys at W3C seem to be unsure as to how to use it, suggesting in their documents separating values with spaces in one place, and then commas a few paragraphs below... So my question is: how do I preload images in JavaScript using <object> tag?

P.S. Sorry for lengthy intro for rather simple question.


Here's my magic formula for doing this. Maybe there's a better way, but this one works and ensures the same 404 view renders whether you generate the 404 or grails does it internally (no controller found, for example).

First, create a View class that extends AbstractView:

class NotFoundView extends AbstractView {

@Override
    protected void renderMergedOutputModel(Map<String, Object> model,
      HttpServletRequest request, HttpServletResponse response) {
        response.sendError(HttpServletResponse.SC_NOT_FOUND)
    }
}

Next, create an error controller:

class ErrorController {

    def notFound = {
        return render(view: '/error/notFound')
    }
}

Now create your error view under views/error/notFound.gsp:

<g:applyLayout name="main">
<!doctype html>
<html>
<head>
    <title>Oops! Not found!</title>
</head>

<body>
    <h1>Not Found</h1>

    <section id="page-body">
        <p>Nothing was found at your URI!</p>
    </section>

</body>
</html>
</g:applyLayout>

It's crucial that you use the <g:applyLayout> tag. If you use your layout will render twice and nest itself.

Now for the URL mapping:

"404"(controller: 'error', action: 'notFound')

You're all set now to send that 404 from your controller:

def myAction = {
    Thing thing = Thing.get(params.id)
    if (!thing) {
         return new ModelAndView(new NotFoundView())
    }
}

This approach also lets you easily log the 404, try to resolve it and send a 301, or whatever you want to do.

4

2 回答 2

3

坦率地说,这很愚蠢。 <img> 不会去任何地方,当然也不会“失宠”。实际上,您引用的规范 (XHTML2)已被放弃

XHTML2 工作组的章程在完成本文档的工作之前就到期了。

您应该以标准为目标的是HTML5。尽管我不建议这样做,但如果您绝对坚持使用 XHTML,那么XHTML5是 HTML5 的子集;但是,唯一的区别实际上是您用于服务页面的 MIME 类型。由于所需的 MIME 类型(application/xhtml+xmlapplication/xml)与旧版浏览器的兼容性较差,因此没有理由在标准网站/网络应用程序中使用它。


关于整个<img>/<object>事情:

从实际的角度来看,使用<img>. 您尝试使用<object>.

<object>不可访问。 <img>具有alt可访问性的属性,屏幕阅读器知道如何处理它。屏幕阅读器可能不知道如何处理<object>. 此外,<object>它不是语义的,它是完全通用的。 <img>意味着它是一个图像。

再说一次,<img>不会很快消失或失宠。在可预见的未来,它仍将是在 HTML 文档中嵌入图像的推荐方式。


最后,关于您如何完成图像翻转的评论:您不应该在 JavaScript 中执行此操作;使用 CSS。

理想情况下,您会使用 sprite(需要对所有图像发出一个 HTTP 请求,从而大大提高性能),并调整background-positionin :hover.

于 2012-05-01T20:19:30.060 回答
1

我玩<object>了更长的时间,但是似乎没有任何干净的方法可以只预加载一次图像,然后将其<object>动态附加到不同的标签。这是最适合我的解决方案的示例代码,到目前为止,如果有人遇到同样的问题:

// Init
for (var i=0;i<imageCount;++i) {
    imagesUnset[i] = document.createElement("object");
    imagesUnset[i].setAttribute("type", "image/png");
    imagesUnset[i].setAttribute("data", imagesURLs[0]);
    imagesUnset[i].setAttribute("onmouseover", "switchImg(this);");

    imagesSet[i] = document.createElement("object");
    imagesSet[i].setAttribute("type", "image/png");
    imagesSet[i].setAttribute("data", imagesURLs[1]);
    imagesSet[i].setAttribute("onmouseover", "switchImg(this);");
}

function switchImg(caller) {
    // some code to identify caller's index in the array and the image to swap to
    caller.parentNode.replaceChild(newObject, caller);
}

我们必须为要交换的每个图像创建单独的对象对;如果我们尝试使用同一个对象,JS 会给我们一个无效指针异常。不知道这在内存使用或性能方面是如何工作的,但它确实有效。

有趣的是,在缓存/缓冲方面,新的 IE (v.9) 比 Firefox 管理得更好。即使没有特殊的 JS 来管理缓冲,它也能够在不闪烁的情况下呈现更改。也许我会停止不喜欢它,最后。

如果有人找到更好的解决方案,请分享。谢谢。

于 2012-05-01T19:02:28.250 回答