在内容完全加载后测量元素的高度
Measure height of element after content is fully loaded
我对JavaScript/jQuery/编程完全陌生,所以如果我给人的印象是天真的,请耐心等待。
我写了一个脚本,将汤博乐博客上的脚注转换为"旁注"。在大多数情况下,它运行得很好。你可以在我的博客上看到例子。
为此,我将脚注的innerHTML附加到一个空div中,然后用CSS(display: none
)隐藏原始脚注。我根本不想更改帖子的标记。我的想法是,我可以删除脚本和旁注,恢复或"降级"回脚注。
旁注相对于其容器是绝对定位的,它们的位置取决于几个因素:前一个旁注的位置、引用链接在文本中的位置以及容器的位置。理想情况下,旁注应该与文本中的引用链接出现在相同的垂直偏移处,但如果前面的元素挡住了去路,它会向下移动以避免重叠。
剧本很简单。基本算术。为了避免元素重叠,我计算了从页面顶部到前一个元素底部的偏移量。如果它大于引用链接的偏移量(和容器的偏移量),则元素向下移动。
正如你所看到的,如果脚注只包含文本,一切都会完美地进行。但是,如果它们也包含图像,侧注就会开始重叠。我相信这是因为我使用.outerHeight()来获取元素的高度,但如果图像还没有加载,它会返回错误的值。你可以在我的一个测试页面上看到我所说的一个例子。
我想我已经将问题隔离到下面的函数中了。
我想如果我使用.load,它会等待元素的内容加载后再执行代码。但这似乎并没有发生。
请告诉我我可能做错了什么。我很确定脚本的问题包含在下面的代码中,但如果你认为这看起来不错,我也可以发布脚本的其余部分。或者你可以在http://resources.contentioninvain.com/scripts/FootnotesToSidenotes.js
上查看(对不起,我是新用户,所以我不能发布两个以上的链接,哈哈)。
提前感谢您的任何建议。这是我第一次发布问题,但我发现这个网站在过去真的很有用。除了修修补补,这是我第一次尝试从头开始写剧本(我有点自豪,我在没有帮助的情况下走到了这一步,哈哈)。
// GetBottomOffset gets the vertical offset to the bottom of an element
// It adds the element's vertical offset and its height:
function GetBottomOffset(Element) {
$(Element).load(function() {
var ElementTop = Element.offset().top; // Vert offset of element
var ElementHeight = Element.outerHeight(true); // Height of element
// Offset to bottom of element
var ElementBottom = ElementTop + ElementHeight;
// Returns ElementBottom
return ElementBottom;
});
}
我认为有三个不相关的问题:
- 我认为你也必须单独观察要加载的图像,并且只有在所有内容都加载时才进行计算
- 如果等待事件首先发生,则不能从函数返回值,因为函数在事件发生之前已经返回。您需要使用回调
- 在挂接
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
)和伪常量(有时用ALL CAPS完成)之外,所有函数都使用小写字母。所以element
而不是Element
,doSomething
而不是DoSomething
等等 - 我正在检查图像是否通过
HTMLImageElement#complete
加载。然而,根据该规范,存在竞争条件,因为completed
可能在我们检查它和挂接load
事件之间发生变化(直到我去寻找参考,我才意识到这一点;令人惊讶),因此可能需要一种更稳健的方法 - 原始代码的一部分假设
Element
是一个jQuery实例,其他部分则将其传递到$
中,就好像它不是一样。在上面的文章中,我假设它是一个原始DOM元素;如果它是一个jQuery实例,只需删除$element = $(element)
位并使用element
而不是$element
- 请注意,我的
watchForBottomDimension
接受一个名为callback
的参数,它应该是一个函数。稍后,它用维度调用该函数(同时传递回元素,必须用于引用) - 我去掉了观察元素本身的部分;应该没有必要(除非元素是图像)。但我添加了观看其中的图像—特别是还不是
loaded
的图像 - 有两种终止条件:A)没有我们需要等待的图像,B)有。所以我们需要在两个地方执行
done
逻辑,所以我把它放在一个嵌套函数中(因为其中一个地方在load
事件处理程序中) - 由于我们的终止条件之一是异步,因此我使它们都异步,因此无论是否有图像要观看,调用者都会看到相同的东西(异步结果),在我们不必等待任何东西的情况下,通过
setTimeout
调用done
- 上面没有注意到图像加载错误(通过
error
),这可能是应该的;如果图像加载失败,它将永远不会发出回调
你可能会发现另一个关于观看图像负载的SO答案很有帮助。
您从哪一点开始计算元素?
我建议等待完整的页面加载,然后再计算任何内容。
您可以使用Jquery函数ready:
$(document).ready(function(){...});
更多信息请点击此处:
http://api.jquery.com/ready/
首先,祝贺您获得了一个非常优雅的插件!
不幸的是,onload
只在上启动
<body>
<link>
和<script>
<frame>
、<frameset>
和<iframe>
<img>
如果你能提前预测图像的尺寸,那将是理想的。由于您的用例不允许这样做,您可以根据脚注的内容绑定到onload
事件:
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);
尝试以下
$(选择器).height();
- CKEditor Widget-阻止编辑可编辑元素本身
- 如何设置html元素填充的动画
- 如何将HTML id分配给元素,以及如何将JavaScript应用于元素
- 使用 jQuery 的 .on 函数如何获取事件的原始元素
- 使用clickToggle并在单击另一个元素时关闭元素
- 单击时将焦点更改为元素
- 表追加而不附加最后一个元素
- 如何在jQuery中获取元素的形式
- 我可以获得相对于被点击元素的确切点击位置吗
- 在函数中添加数组元素的数值
- 在单击任何位置时隐藏元素,而不检查每次DOM单击
- 将视口底部滚动到元素底部
- 测量元素和窗口边距之间的长度
- 测量 HTML 5 画布元素上的角度
- 使用CTRL+SHIFT+R与F5重新加载时,元素测量的宽度不同
- 如何测量HTML元素的宽度
- 测量子模板中的目标元素并传递给全局函数
- 如何使用jQuery测量元素宽度
- 隐藏了溢出的DOM元素及其子元素,DOM可以测量高度/宽度
- 在内容完全加载后测量元素的高度