Javascript 在 class 中获取 class 失败

Javascript failing when getting a class within a class

我正在为我的摄影网站制作 "worksafe mode"(裸体 [NSFW] 默认隐藏)。

index.php 包含一系列包含:

<?php include 'images/20090820_9616/card.php';?>     
<?php include 'images/20110509_1509/card.php';?>
etc..

card.php 对于所有 SFW 图像都是相同的(figure.class 除外)

<figure id="<?php echo basename(__DIR__);?>" class="Horizontal Landscape FallColor">
    <a href="<?php echo 'images/'.basename(__DIR)__).'/';?>">
        <img src="<?php echo 'images/'.basename(__DIR__).'/thumbnail.jpg';?>">
    </a>
</figure>
NSFW 图片的

card.php 不同:

<figure id="<?php echo basename(__DIR__);?>" class="NSFW Horizontals">
    <a class="sfw_a" href="#">
        <img class="sfw_img_h" src="images/include/sfw_h.jpg">
    </a>
</figure>

无论如何,当有人单击 "Turn Worksafe Off" 按钮时,Javascript 应该将第二个 card.php 更改为与第一个基本相同。我大部分都在工作:

function worksafeOff() {
    var sfw = document.getElementsByClassName('NSFW');
    for (i = 0; i < sfw.length; i++) {
// I. Insert NSFW thumbnails and links
        sfw[i].getElementsByTagName('a')[0].href = '/images/' + sfw[i].id + '/';
        sfw[i].getElementsByTagName('img')[0].src = '/images/' + sfw[i].id + '/0x.jpg';
// II. Update Class of thumbnails and links to NSFW
        sfw[i].getElementsByClassName('sfw_a')[0].className = 'nsfw_a';
        sfw[i].getElementsByClassName('sfw_img_h')[0].className = 'nsfw_img_h';
        sfw[i].getElementsByClassName('sfw_img_v')[0].className = 'nsfw_img_v';
    }
    document.getElementById('NSFW_deactivateFilter').style.border = '1px solid red';
    document.getElementById('NSFW_deactivateFilter').innerHTML = 'Worksafe Mode: Off';
    document.getElementById('NSFW_deactivateFilter').setAttribute('onClick', 'worksafeOn()');
    document.getElementById('NSFW_deactivateFilter').id = 'NSFW_activateFilter';
}
function worksafeOn() {
    var nsfw = document.getElementsByClassName('NSFW');
    for (i = 0; i < nsfw.length; i++) {
// I. Remove NSFW thumbnails and links
        nsfw[i].getElementsByTagName('a')[0].href = '#';
        nsfw[i].getElementsByClassName('nsfw_img_h')[0].src = 'images/include/sfw_h.jpg';
        nsfw[i].getElementsByClassName('nsfw_img_v')[0].src = 'images/include/sfw_v.jpg';
// II. Update Class of thumbnails and links to SFW
        nsfw[i].getElementsByClassName('nsfw_a')[0].className = 'sfw_a';
        sfw[i].getElementsByClassName('nsfw_img_h')[0].className = 'sfw_img_h';
        sfw[i].getElementsByClassName('nsfw_img_v')[0].className = 'sfw_img_v';
    }
// III. Change "Worksafe Mode: Off" button to "Worksafe Mode: On" button
    document.getElementById('NSFW_activateFilter').style.border = '1px solid black';
    document.getElementById('NSFW_activateFilter').innerHTML = 'Worksafe Mode: On';
    document.getElementById('NSFW_activateFilter').setAttribute('onClick', 'worksafeOff()');
    document.getElementById('NSFW_activateFilter').id = 'NSFW_deactivateFilter';
}

这是the main jsfiddlegEBTN[0]('a')gEBTN[0]('img') 都可以正常工作。 gEBCN[0]('a.class') 也很完美。但是尝试 gEBCN[0]('img.class') 失败并挂起函数。在 jsfiddle 中,我注释掉了第 9、10、22、23、26、27 行,这样您就可以看到没有其他错误。

这里是 a simplified fork,您可以很容易地看到 gEBCN[0]('a.class') 在第 8 行工作,但 gEBCN[0]('img.class') 在第 9 行失败 and/or 10.

尝试使用 querySelector() 函数。这将允许您使用 element, class 或 id:

获取元素

sfw[i].querySelector('.sfw_img_h')[0].className = 'nsfw_img_h';

为什么不在 NSFW 图像中添加 data-nsfw-src 和 data-sfw-src?然后您可以使用该属性而不是 id,反之亦然。

如@pabs123 所建议,使用 querySelector 或 querySelectorAll:(未测试)

var nsfw_images = document.querySelectorAll('[data-nsfw-src]');
for(var i in nsfw_images) {
    nsfw_images[i].src = nsfw_images[i].getAttribute('data-sfw-src');
}

您还可以添加 NSFW 和 SFW 图像,更改全局容器 class(如 document.documentElement),并使用样式 show/hide 正确的图像。然后切换 img src.

更容易
.hide-nsfw img.nsfw, .show-nsfw img.sfw {display:none}

问题出在这两行:

    sfw[i].getElementsByClassName('sfw_img_h')[0].className = 'nsfw_img_h';
    sfw[i].getElementsByClassName('sfw_img_v')[0].className = 'nsfw_img_v';

有的元素只有sfw_img_h,有的只有sfw_img_v。当您尝试设置不存在的元素的 class 时,您会收到错误消息并且函数退出。您需要测试元素是否存在。

var imgs = sfw[i].getElementsByClassName('sfw_img_h');
if (imgs.length) {
    imgs[0].className = 'nsfw_img_h';
}
imgs = sfw[i].getElementsByClassName('sfw_img_v');
if (imgs.length) {
    imgs[0].className = 'nsfw_img_v';
}

如果您 运行 在控制台打开的情况下编写代码,您会看到错误提示您无法分配给 undefinedclassName 属性 .