javascripthtmlbrowsermcustomscrollbar

Why does my js execute differently with improper html?


I have a webpage using jQuery, bootstrap, and 2 different jQuery plugins. One is called Turn.js and the other is called mCustomScrollbar. Before today I had server side code that would prepend a script tag, before the <!DOCTYPE html> tag, to every request. I noticed on a different page that this was causing an issue with jQuery returning an improper height when using $(window).height(), so I modified the code and figured out a way to put the script tag just before the closing </body> tag. This has however broken the functionality of the mCustomScrollBar library that I am using

For some reason the scroll bar doesn't show up, the mouse wheel functionality is disabled, and scrolling is disabled on mobile/touch devices. The plugin is definitely firing as I can see the html gets modified by the plugin.

So my question is: Why does my javascript work correctly, or at least how I want it to, when I have improper html, but it does not work correctly when my markup is corrected (No text before the <!DOCTYPE html> tag)?

Relevant Code:

The html structure I'm applying the mCustomScrollbar plugin to. The parent of the #flip-indes div a bootstrap .container-fluid which is the pages main container. I'm using C# with razor syntax on my views. I can post the generated html of a page if needed.

<div id="flip-index">
    <div class="customScrollbar">
        @for (var i = 0; i < Model.Pages.Count; ++i)
        {
            <div class="index-item" onclick="$('#flipbook').turn('page', @(i + 1));">
                <img src="@Config.Get("FlipbookImgURL")@Model.Pages[i].Replace('\\', '/')" alt="Flipbook index preview" onerror="replaceWithText(event);"/>
                <a class="btn btn-primary full-size-img" href="/FlipBook/FullSizeImage?img=@Config.Get("FlipbookImgURL")@Model.Pages[i].Replace('\\', '/')" target="_blank" title="View Image Full Size">
                    <span class="glyphicon glyphicon-eye-open"></span>
                </a>
                <div class="index-number">@(i + 1)</div>
            </div>
        }
        <div class="index-pad">&nbsp;</div>
    </div>
</div>

My $(document).ready()

try
{
    $('.index-item:first-child').addClass('active');
    var turnOptions = {};
    var width = screenWidth();
    $('.main-content').css('padding-top', $('nav.navbar').outerHeight())
    $('#flipbook').turn(turnOptions);
    var firstImage = $('#flipbook img')[0];
    if (firstImage.complete || firstImage.naturalHeight > 0) {
        sizeElements();
    } else {
        firstImage.onload = sizeElements;
    }
    $('.customScrollbar').mCustomScrollbar({
        theme: 'minimal-light',
        axis: 'y',
        mouseWheel: {
            scrollAmount: ($('#flip-index').outerHeight() * (1 / $('.index-item').length)) * 2
        }
    });

    $('#flip-index').css({
        left: parseInt($('.main-content').css('padding-left'))
    });

    // Keep the sidebar and the flipper in sync.
    $('#flipbook').on('turning', pageTurning);
    window.addEventListener('resize', windowResize);

    $('#otherInserts .active, #otherInserts .disabled').on('click', function (e) {
        e.preventDefault();
        e.stopImmediatePropagation();
    });
}
catch(ex)
{
    alert('There was an error loading this page!');
    throw ex;
}
finally
{
    // remove loading overlay
    $('.loading-overlay').fadeOut(function () {
        $('.loading-overlay').remove();
    });
}

There is a whole lot more js I have on this page but none of it references the mCustomScrollbar plugin so I didn't think it was relevant, and I don't want to overload anyone with unnecessary info. If anyone would like more code posted I would be glad to do it, just ask.

I really think the answer is going to lie somewhere within how the browser is interpreting my js or html markup based on whether or not the browser is able to validate the html.


Solution

  • Welcome to: QUIRKS MODE

    Depending on the doctype, or lack thereof, the browser can use either standards mode or quirks mode. Quirks mode duplicates functionality of ancient browsers and its best avoided.

    Since you are rendering content before the doctype tag, the browser assumes quirks.

    There are a LOT of differences between the two modes, but this might get you started:

    https://developer.mozilla.org/en-US/docs/Quirks_Mode_and_Standards_Mode

    As well as this friendly chart:

    http://www.quirksmode.org/css/quirksmode.html

    Recommendation: Avoid quirks mode at all costs. Fix whatever broken code is giving you bad HTML.