【问题标题】:getElementById() within $(document).ready() returns null$(document).ready() 中的 getElementById() 返回 null
【发布时间】:2015-09-17 11:53:46
【问题描述】:

我是 JavaScript 的“新手”,正在为网站制作我的第一个图像和媒体滑块。 我已经在网上和 SO 中搜索了答案,但它们对我不起作用。

我的最后一个重大变化是将我的脚本分成两部分。一个在$(document).ready() 外面,一个在里面。我希望用户能够通过 HTML 中的按钮调用函数。为了使这成为可能,这个函数必须是全局的,并且不能位于$(document).ready() 内。我对吗? 在我划分我的脚本之前,一切都在$(document).ready() 区域内并且它工作正常。但由于我无法通过按钮调用该函数。

但是现在我的$(document).ready() 中的部分,它必须在页面加载时构建滑块,而不是等待它。我所有的getElementById() 都在产生错误:“无法设置属性‘样式’为空。”所以滑块不会被构建。 这告诉我 getElementById() 返回“null”,即使它在 $(document).ready() 内。

HTML:

  <!-- very content -->

  <link href="...css" />
  <script src="...js" />
  <div id="slider"></div>

  <!-- more content -->

  <div id="changeContent"></div>

  <!-- more content -->

</body>
</html>

JavaScript:

    // Configuration
var slidersParentId = 'imslider';
var slideShowTitle = '';
var thumbnailWidth = 20;
var slidesWidth = 281.25;
var slidesHeight = 144.5625;
var currentSlideWidth = 500;
var currentSlideHeight = 257;
var nextSlideWidth = 375;
var nextSlideHeight = 192.75;
var prevSlideWidth = nextSlideWidth;
var prevSlideHeight = nextSlideHeight;
var resizeDifference = currentSlideWidth - nextSlideWidth;
var slidesMargin = 20;
var animationDistance = slidesWidth + slidesMargin;
var animationSpeed = 2000;
var intervalSpeed = 7000;
var contentDiv = "descriptif_site_spip";

// Variables from slides.json
var numberOfSlides;
var jsonSlides = {};
var bgImgUrl;

// Cache the DOM
var $slideShow = $('#'+slidersParentId);
var $slideInner;
var $slides;
var $slideNav;
var $navThumb;
var $thumb;
var $hovers;
var $content = document.getElementById(contentDiv);

// Other global Variables
var interval;
var currentSlide = 1;
var nextSlide = currentSlide + 1;
var prevSlide = currentSlide - 1;
var lastSlide = currentSlide;
var lastCurrentDif;
var lastNextSlide = lastSlide + 1;
var lastPrevSlide = lastSlide - 1;
var thumbImgs = [];
var navTo;
var interval;
var i;

// Global Variables for dragging
var dragStartPosition;
var dragStopPosition;
var draggedDistance;
var slidesDragged;
var posSlidesDragged;
var negSlidesDragged;

// IRIS-MEDIA-MODUS ?!
var iris_mode = 1;

//global functions...
//global warming...


$(document).ready(function(){

  $.ajax({}

    //getting some json...

  });

  // Building the slideshow windows
  if (slideShowTitle !== 0) {
    $slideShow.append('<h2 class="slideShowTitle">'+slideShowTitle+'</h2>');
  }

  $slideShow.append('<div id="outerWindow"><div id="innerWindowPositioner"<div id="innerWindow"></div></div</div>');
  $slideInner = $slideShow.find('#innerWindow');
  $slideInner.css({'width': numberOfSlides*slidesWidth+numberOfSlides*slidesMargin*currentSlideWidth*3});


// Building the slides & hovers
for (i=1; i<=numberOfSlides; i++) {

    var idSlides = "slide_Nr"+i;
    alert(idSlides);
    var idHover = "hover_Nr"+i;
    var j = i-1;
        bgImgUrl = "url('" +jsonSlides[j].mediaUrl+ "')";
    var title = jsonSlides[j].title;
    var artUrl = jsonSlides[j].articleUrl;
    var subtitle = jsonSlides[j].subtitle;
    var text = jsonSlides[j].text;
    var date = jsonSlides[j].date;

    $slideInner.append('<div class="slide" id="'+idSlides+'"><div class="hover" id="'+idHover+'"></div></div>');
    $('#'+idSlides).css('top', '56.21875px');
    document.getElementById(idSlides).style.backgroundImage = bgImgUrl;

    $('#'+idHover).append('<div class="hover-title"><h3><a href="'+artUrl+'">'+title+'</a></h3><span class="hover-subtitle">'+subtitle+'</span></div><span class="hover-date">'+date+'</span><br clear="all" /><p class="hover-text">'+text+'</p>');
}

$slides = $slideInner.find('.slide');
$hovers = $slides.find('.hover');


// Building the thumbnail navigation
$slideShow.append('<div id="slideShowNavigation"><ul id="navigationThumbnails"></ul></div>');
$slideNav = $slideShow.find('#slideShowNavigation');
$navThumb = $slideNav.find('#navigationThumbnails');

for (i=0; i<numberOfSlides; i++) {
    thumbImgs[i] = jsonSlides[i].mediaUrl;
//  alert(thumbImgs);
}

for (i=1; i<=numberOfSlides; i++) {

        j = i-1;
    var idThumbs = "thumb_Nr"+i;
        bgImgUrl = "url('" +jsonSlides[j].mediaUrl+ "')";

    $navThumb.append('<li class="thumb" id="'+idThumbs+'"></li>');
    document.getElementById(idThumbs).style.backgroundImage = bgImgUrl;
    }

$thumb = $navThumb.find('.thumb');
$( '<li class="year">&nbsp;>&nbsp;2000&nbsp;>&nbsp;</li>' ).insertBefore( "#thumb_Nr62" );
$navThumb.prepend('<li class="year">1980&nbsp;>>&nbsp;</li>');
$navThumb.append('<li class="year">&nbsp;&nbsp;2020&nbsp>></li>');
$navThumb.append('<br clear="both" />');

// ...some
// ...more
// ...functions

});

使用这种 HTML 结构是行不通的。 当我将脚本包含在 HTML 的末尾时,它可以正常工作,并且将构建滑块。

那么为什么我的$(document).ready() 触发得太早了? 我也试过$(window).load(),但没有效果。

或者有什么理由让$(document).ready() 中的函数全局可用而不从$(document).ready() 中删除?

【问题讨论】:

  • 我怀疑,您的脚本依赖于ajax的响应,因此,您需要在回调函数中移动依赖代码。
  • 您是否验证了$slideShow 存在于DOM 中?我们缺少一些相关信息。
  • 老兄,不知道你去了哪里,但很可能你正在创建并添加到 DOM 的元素实际上并没有被添加,因为你试图将它们添加到不存在的元素中. jQuery 有点糟糕,当它应该给出错误时它会悄悄地失败。因此,使用 jQuery 选择器找不到要添加新内容的元素,然后您的 .append() 调用什么也不做,因此不会找到新元素。所以只要确保所有 需要.ready() 中的东西都放回那里。这包括 DOM 选择。
  • 对不起,我忘了给你看我的 DOM 变量。我现在将更新我的 JavaScript。
  • 是的,您对 $slideShow$content 变量的 DOM 选择现在发生在元素存在之前。要么将你的脚本移到页面底部&lt;/body&gt; 标记之前,要么在.ready() 处理程序中执行这些DOM 选择,以便在加载DOM 之前不会发生。这就是.ready() 处理程序的全部意义所在。它确保文档在运行之前完全加载,以便初始元素存在以供选择。

标签: javascript jquery html dom scope


【解决方案1】:

可能是因为您的脚本在页面的其余部分加载之前运行。尝试使用$(window).ready()

编辑:

有错误的函数.load() 我的意思是 .ready()...哎呀!

【讨论】:

  • 我认为您不了解 .ready() 的作用以及它与 .load() 的不同之处。
  • 当然可以,前几天我不得不使用它。
  • 太棒了,那为什么.load()会比.ready()更好呢?
  • OP 已经在使用.ready()。他在问题中提到了十几次。通过 window 而不是 document 没有区别。不知道为什么有人会给这个+1。停止同情投票的人。
  • 好的,从现在开始,我将把答案留给你。
【解决方案2】:

我的最后一个重大变化是将我的脚本分成两部分。一个在$(document).ready() 外面,一个在里面。我希望用户能够通过 HTML 中的按钮调用函数。为了使这成为可能,这个函数必须是全局的,并且不能位于$(document).ready() 内。

其实it can:

所有全局 JavaScript 对象、函数和变量都自动成为窗口对象的成员。

我想你需要这样的东西:

window.addEventListener('DOMContentLoaded', function () {
    window.my_magic_function = function (/* my magic params */) {
        /* doing my magic */
    };
});
<button onclick="my_magic_function(/* my magic params */)">Do magic</button>

window.addEventListener('DOMContentLoaded', ...) 等同于$(document).ready(...)

【讨论】:

  • 'DOMContentLoaded' 基本等价于.ready()。而且您无需等待 DOM 准备好创建全局函数。
  • @squint,我知道。那么,如果它不能以不同的方式解决 TC 的问题,你为什么要这么说呢?
  • 我告诉你,这无助于解决 OP 的问题。他在某处有一些故障代码,已从问题中排除。我猜他已经从.ready() 处理程序中删除了一些实际上需要在那里的东西。我不知道你想用这个答案说什么。
  • @squint > 在我分割我的脚本之前,一切都在 $(document).ready() 区域内并且它工作正常。
  • @Nils 我在上面的帖子中提供了工作示例和证明链接。不是很相关,但是github.com/pyinstaller/pyinstaller/wiki/…可以回答如何发帖的问题。
猜你喜欢
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-20
  • 2011-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多