一个文档类型声明是如何破坏我的JavaScript的?

4
我制作了一个菜单,刚刚我添加了一些内容。
<!DOCTYPE html>

将文档中的doctype删除后,JavaScript就无法正常工作。但代码仍然在运行,在鼠标悬停时仍会在控制台中打印等操作。我尝试了其他doctype,它们也会破坏它,它只会保持静态状态。

doctype有什么原因会导致JavaScript不能正常工作?

JS:

var total_width = "960";
var slide_width = "182";
var slide_margin = "10";
var expand_width = "374";
var icon_width = "32";
var icon_margin = "15";
var slide_number = "5";

function slideid(i) {
    var m = document.getElementById("slide"+i);
    var l = document.getElementById("slideimg"+i);
    var k = document.getElementById("slidetext"+i);
    var j = document.getElementById("slidediv"+i);
    return [m, l, k, j]
}

function compat() {
    if (window.opera) {
        for (var i=1;i<6;i++) {
            s = slideid(i);
            s[3].style.position="relative";
            s[3].style.bottom="46px";
        }
    }
    if (document.all && !(window.opera)) {
        for (var i=1;i<6;i++) {
            s = slideid(i);
            s[0].style.height="60px";
            s[1].style.display="none";
            var iecontents = s[2].innerHTML;
            s[0].innerHTML=iecontents;
            s[0].style.fontFamily="'astonishedregular',Impact,serif";
            s[0].style.fontSize="40px";
            s[0].style.color="#fff";
            s[0].style.textDecoration="none";
            s[0].style.padding="10px auto";
        }
    }
}

function expand(x) {
    if (document.all && !(window.opera)) {
        return
    }
    var shrink = new Array();
    for (var i=1;i<6;i++) {
        if (i === x) {
            var expander = i;
        }
        else {
            var d = shrink.length;
            shrink[d] = i;
        }
    }
    for (var i=0;i<4;i++) {
        s = slideid(shrink[i]);
        var slide_shrink = ((total_width-(5*slide_margin))-expand_width)/(slide_number-1);
        s[1].style.marginLeft=(slide_shrink-icon_width)/2;
        s[0].style.width=slide_shrink;
        s[2].style.display="none";
        s[3].style.width="0"
    }
    s = slideid(expander);
    s[1].style.marginLeft=icon_margin;
    s[0].style.width=expand_width;
    s[2].style.display="inline-block";
    s[3].style.width=expand_width-icon_width-icon_margin-7;
}

function shrink() {
    if (document.all && !(window.opera)) {
        return
    }
    for (var i=1;i<6;i++) {
        s = slideid(i);
        s[1].style.marginLeft=(slide_width-icon_width)/2;
        s[0].style.width=slide_width;
        s[2].style.display="none";
        s[3].style.width="0";
    }
}

还有HTML:

<!DOCTYPE html>
<head>
    <link rel="stylesheet" href="style.css" />
    <script src="menu.js"></script>
</head>
<body onload="compat()">

<div id="Menu" onMouseout="shrink()">
    <a href="#" class="slide" id="slide1" onMouseOver="expand(1)">
        <img id="slideimg1" src="home.png" />
        <div id="slidediv1">
            <h2 id="slidetext1">Home</h2>
        </div>
    </a>
    <a href="#" class="slide" id="slide2" onMouseOver="expand(2)">
        <img id="slideimg2" src="sound.png" />
        <div id="slidediv2">
            <h2 id="slidetext2">Music</h2>
        </div>
    </a>
    <a href="#" class="slide" id="slide3" onMouseOver="expand(3)">
        <img id="slideimg3" src="blog.png" />
        <div id="slidediv3">
            <h2 id="slidetext3">Blog</h2>
        </div>
    </a>
    <a href="#" class="slide" id="slide4" onMouseOver="expand(4)">
        <img id="slideimg4" src="note.png" />
        <div id="slidediv4">
            <h2 id="slidetext4">Bio</h2>
        </div>
    </a>
    <a href="#" class="slide" id="slide5" onMouseOver="expand(5)">
        <img id="slideimg5" src="way.png" />
        <div id="slidediv5">
            <h2 id="slidetext5">Links</h2>
        </div>
    </a>
</div>
</body>

这真是让人怀旧啊,一股过去的感觉。针对楼主:修复这个脚本之外,是否有可能选择其他写于21世纪的千万种菜单脚本呢? :) - Sergey
@Sergey 噢,抱歉我误解了。我知道这一点,我认为这是我在Javascript中做的第二件事情,学习新东西通常会采用非常糟糕的方法。当我准备修复它时,我不小心把它搞坏了。 - Liam Bigelow
@Sergey 出于好奇,您看到了哪些最糟糕的实践? - Liam Bigelow
啊,这个问题值得单独提出来讨论,可能要在http://codereview.stackexchange.com/上发帖。举几个例子:全局变量泄漏、缺少分号、不必要的浏览器检测、`new Array()`语法、整个冗长的onMouseOver事件... 作为一个学习练习,可以访问http://jslint.com并调整脚本,直到它没有错误为止——目前它因为太多错误而停在了第19行。 - Sergey
@Sergey 是的,我明白。这些都是我正在修复的问题。谢谢。 - Liam Bigelow
显示剩余2条评论
4个回答

11

您需要在marginLeftwidth中添加"px"。设置需要单位的CSS样式将无法正常工作。同时,您还缺少<html></html>标签。

function expand(x) {
    if (document.all && !(window.opera)) {
        return
    }
    var shrink = new Array();
    for (var i=1;i<6;i++){
        if (i === x) {
            var expander = i;
        }
        else {
            var d = shrink.length;
            shrink[d] = i;
        }
    }
    for (var i=0;i<4;i++){
        s = slideid(shrink[i]);
        var slide_shrink = ((total_width-(5*slide_margin)) - expand_width) / (slide_number-1);
        s[1].style.marginLeft=(slide_shrink-icon_width)/2 +"px";
        s[0].style.width=slide_shrink +"px";
        s[2].style.display="none";
        s[3].style.width="0"
    }
    s = slideid(expander);
    s[1].style.marginLeft=icon_margin +"px";
    s[0].style.width=expand_width + "px";
    s[2].style.display="inline-block";
    s[3].style.width= (expand_width-icon_width-icon_margin-7) +"px";
}

function shrink() {
    if (document.all && !(window.opera)) {
        return
    }
    for (var i=1;i<6;i++){
        s = slideid(i);
        s[1].style.marginLeft=(slide_width-icon_width)/2 +"px";
        s[0].style.width=slide_width + "px";
        s[2].style.display="none";
        s[3].style.width="0";
    }
}

这样就解决了,现在幻灯片可以很好地滑动了。有些东西已经偏离了轨道,但这是因为我没有从doctype开始。谢谢。 - Liam Bigelow
在HTML中,<html></html>标签是完全可选的。 - Nisse Engström

2
document.all是微软的东西,不受标准覆盖(更多信息请参见此其他问答)。请删除所有使用它的内容,并根据需要改用document.getElementById
我猜如果你查看JavaScript控制台,你会看到与不存在document.all相关的错误,因为无论你在哪个浏览器上测试,只要支持怪异模式,就会支持它,但当你将其切换为标准模式(通过添加文档类型)时,它就不再支持了。

我在控制台中没有看到来自document.all的错误,现在这只是我粗略检查它们是否在IE上并且如果是,则不执行动画的方式,我没有想到那会破坏其他代码。 - Liam Bigelow

1

添加HTML5 DOCTYPE(<!DOCTYPE html>)可以将浏览器置于“标准模式”。如果没有它,浏览器将处于“怪异模式”,这基本上是IE5 /遗留兼容模式。 MDN有更多关于此主题的信息, 以及Firefox行为差异列表

您的脚本最大的问题是使用了document.all,这是一个非标准的Microsoft东西。您需要使用标准DOM内容,例如document.getElementById


我没有使用document.all来获取元素,只是一种粗糙的浏览器检测方法,因为在IE中滑动效果不太好。 - Liam Bigelow

0

将您的计数脚本包含在关闭body标记之前,并不要忘记添加HTML的结束标记

<!DOCTYPE html>
<head>
<link rel="stylesheet" href="style.css" />
<script src="menu.js"></script>
</head>
<body onload="compat()">

<div id="Menu" onMouseout="shrink()">
<a href="#" class="slide" id="slide1" onMouseOver="expand(1)">
  <img id="slideimg1" src="home.png" />
<div id="slidediv1">
    <h2 id="slidetext1">Home</h2>
</div>
</a>
<a href="#" class="slide" id="slide2" onMouseOver="expand(2)">
<img id="slideimg2" src="sound.png" />
<div id="slidediv2">
    <h2 id="slidetext2">Music</h2>
</div>
</a>
<a href="#" class="slide" id="slide3" onMouseOver="expand(3)">
<img id="slideimg3" src="blog.png" />
<div id="slidediv3">
    <h2 id="slidetext3">Blog</h2>
</div>
</a>
<a href="#" class="slide" id="slide4" onMouseOver="expand(4)">
<img id="slideimg4" src="note.png" />
<div id="slidediv4">
    <h2 id="slidetext4">Bio</h2>
</div>
</a>
<a href="#" class="slide" id="slide5" onMouseOver="expand(5)">
<img id="slideimg5" src="way.png" />
<div id="slidediv5">
    <h2 id="slidetext5">Links</h2>
</div>
</a>
</div>
</body>
</html>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接