Javascript 内容完全加载后测量元素的高度

Javascript 内容完全加载后测量元素的高度,javascript,jquery,Javascript,Jquery,一般来说,我对JavaScript/jQuery/编程是完全陌生的,所以如果我觉得自己非常幼稚,请原谅我 我写了一个脚本,将Tumblr博客上的脚注转换为“旁注”。在大多数情况下,它运行得非常好。你可以 为此,我将脚注的innerHTML附加到一个空div,然后用CSS隐藏原始脚注(display:none)。我根本不想改变帖子的标记。我的想法是,我可以删除脚本和旁注,恢复或“降级”回脚注 侧注相对于其容器绝对定位,它们的位置取决于几个因素:前面侧注的位置、文本中引用链接的位置以及容器的位置。理

一般来说,我对JavaScript/jQuery/编程是完全陌生的,所以如果我觉得自己非常幼稚,请原谅我

我写了一个脚本,将Tumblr博客上的脚注转换为“旁注”。在大多数情况下,它运行得非常好。你可以

为此,我将脚注的innerHTML附加到一个空div,然后用CSS隐藏原始脚注(
display:none
)。我根本不想改变帖子的标记。我的想法是,我可以删除脚本和旁注,恢复或“降级”回脚注

侧注相对于其容器绝对定位,它们的位置取决于几个因素:前面侧注的位置、文本中引用链接的位置以及容器的位置。理想情况下,侧注应该与文本中的参考链接出现在相同的垂直偏移处,但是如果前面的元素挡住了方向,它会向下移动以避免重叠

脚本非常简单。基本算术。为了避免元素重叠,我计算了从页面顶部到前一个元素底部的偏移量。如果其大于参考链接的偏移量(以及容器的偏移量),则元素向下移动

如您所见,如果脚注仅包含文本,则所有内容都可以完美地工作。但如果它们也包含图像,则旁注开始重叠。我相信这是因为我正在使用.outerHeight()获取元素的高度,但如果图像尚未加载,它将返回错误的值。你可以看到一个例子,我所说的

我想我已经将问题隔离到下面的函数

我认为如果我使用.load,它将在执行代码之前等待元素的内容加载。但这似乎没有发生

请告诉我我可能做错了什么。我很确定脚本的问题包含在下面的代码中,但如果您认为这看起来不错,我也可以发布脚本的其余部分。或者您可以在
http://resources.contentioninvain.com/scripts/FootnotesToSidenotes.js
(对不起,我是新用户,所以我只能发布两个链接,哈哈)

提前感谢您的建议。这是我第一次发布问题,但我发现这个网站在过去非常有用。除了修修补补之外,这是我第一次尝试从头开始写剧本(我有点自豪,我在没有帮助的情况下走了这么远,哈哈)


我认为有三个不相关的问题:

  • 我认为你也必须单独观看图像加载,并且只在加载所有内容时才进行计算
  • 如果等待事件首先发生,则无法从函数返回值,因为函数将在事件发生之前已返回。您需要使用回调
  • 在钩住
    load
    事件之前,必须考虑已加载的图像
  • 例如:

    function watchForBottomDimension(element, callback) {
        var $element, images, loaded;
    
        // Get a jQuery wrapper for `element`
        $element = $(element);
    
        // Find the images within it that aren't loaded yet
        images = $element.find("img").filter(function(index, img) {
            return !img.complete;
        });
    
        // Find any?
        if (images.length === 0) {
            // No, we're done -- call the callback asynchronously for
            // consistency with the case below where we have to wait
            setTimeout(done, 0);
        }
        else {
            // We're waiting for some images, do that
            loaded = 0;
            images.load(function() {
                // One of them loaded; was it the last one?
                if (++loaded === images.length) {
                    // Yup, we're done
                    done();
                }
            }); 
        }
    
        // Handle completion
        function done() {
            var top, height, bottom;
    
            top = $element.offset().top; // Vert offset of element
            height = $element.outerHeight(true); // Height of element
    
            // Offset to bottom of element
            bottom = top + height;
    
            // Call the callback with the value
            callback(element, bottom);
        }
    }
    
    关于这一点,请注意:

  • 这是离题的,但这可能是你在上面注意到的第一件事,所以:我改变了事物的名称。在JavaScript中,压倒性的惯例是除了构造函数(主要使用
    new
    调用的函数,如
    Date
    )之外的所有函数都使用首字母小写字母,这些函数的首字母大写,而伪常量有时在所有大写字母中都使用。所以
    element
    而不是
    element
    doSomething
    而不是
    doSomething
    ,等等
  • 我正在检查图像是否通过加载。不过,根据该规范,有一个竞争条件,因为
    completed
    可能会在我们检查它和钩住
    load
    事件之间发生变化(直到我去寻找引用时我才意识到这一点;令人惊讶),因此可能需要一种更稳健的方法
  • 原始代码的一部分假设
    元素
    是一个jQuery实例,其他部分则将其传递到
    $
    中,就好像它不是。在上面我假设它是一个原始DOM元素;如果它是jQuery实例,只需删除
    $element=$(element)
    位,并使用
    element
    而不是
    $element
  • 请注意,我的
    watchForBottomDimension
    接受一个名为
    callback
    的参数,该参数应该是一个函数。稍后,它使用维度调用该函数(也传回元素,必须用于引用)
  • 我卸下钻头,观察元素本身;它不应该是必需的(除非元素是图像)。但我增加了对其中图像的观察——特别是那些(尚未)
    加载的图像
  • 有两种终止条件:A)没有需要等待的图像,B)有。所以我们需要在两个位置执行
    done
    逻辑,所以我将它放在一个嵌套函数中(因为其中一个位置在
    load
    事件处理程序中)
  • 因为我们的一个终止条件是异步的,所以我将它们都设置为异步的,这样无论是否有图像要观看,调用方都可以看到相同的东西(异步结果),在不需要等待任何东西的情况下,通过
    setTimeout
    调用
    done
  • 上面没有注意图像加载错误(via),它可能应该这样做;如果映像加载失败,它将永远不会发出回调

  • 您可能会发现有关查看图像加载的信息非常有用。

    从哪一点开始计算元素

    我建议您等待整个页面加载bevor,然后再计算任何内容

    您可以使用Jquery函数ready:

    $(document).ready(function(){...}); 
    
    更多信息请点击此处:

    尝试以下方法

    $(选择器).height()


    首先,祝贺你有一个非常优雅的plugi
    $(document).ready(function(){...}); 
    
    var resize = function() {
      // within this handler, `this` will refer to the img tag.
      var container = $(this).closest('.sidenote');
    
      // ... resize calculation ...
    }
    
    // bind images in the sidenote to the resize handler
    $('img', sidenote).load(resize);