Skip to content

Instantly share code, notes, and snippets.

@jdickey
Last active December 13, 2015 22:19
Show Gist options
  • Save jdickey/4983769 to your computer and use it in GitHub Desktop.
Save jdickey/4983769 to your computer and use it in GitHub Desktop.
Discussion of changes in Bootstrap's `modal` (dialog) plugin between version 2.0 and the (now-)current 2.3.

Introduction

Bootstrap's modal-dialog behaviour has changed significantly since Version 2.0.x.

What interests me here is the behaviour I had previously been testing in Jasmine specs to detect whether the dialog was being shown or not. In earlier versions, Bootstrap would add the CSS class modal-open to the HTML body to indicate that there was a modal open somewhere on the page. You can make any of several arguments why that's a poor mechanism, including the fact that you can't look at the currently active DOM and easily tell which of several possible dialogs on a page is active.

Now, the markup for the outermost containing div of the dialog has changed significantly. I used this jsFiddle to explore how Bootstrap modifies that div in the DOM as of Bootstrap version 2.3.0.

Dialog markup as written

Attachment 01-as-written.html shows the markup of a sample dialog, as copied from their example of a "live demo" dialog. Note the outermost div markup:

<div id="myModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">

Dialog markup while dialog is being shown

Attachment 02-as-shown.html shows the markup active in the DOM while the dialog is being shown. Again, note the outermost div markup:

<div id="myModal" class="modal hide fade in" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="false" style="display: block;">

What's changed?

  1. The CSS class in has been added to the div. (No change was made to any containing block's markup).
  2. The value of the attribute aria-hidden has changed from true to false.
  3. A new style attribute was added, with the value display: block, so that the entire div is shown as one contiguous block in the rendered page.

Dialog markup after dialog no longer shown

Finally, attachment 03-after-close.html shows the markup active in the DOM after the dialog has been "closed" (hidden). The outermost div now reads:

<div id="myModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="display: none;">
  1. The CSS class in has been removed.
  2. The aria-hidden attribute has been restored to true.
  3. The CSS style attribute has been changed to display: none, rather than being removed to match the initial markup.

Observations

  1. Markup is now significantly more complex, with more fully-fledged ARIA role information being specified.
  2. Markup changes as dialog state changes are now localised to the dialog markup, rather than polluting the page body.
  3. Whereas earlier Bootstrap versions could tell if a dialog was being shown, now we can inspect the DOM to see which dialog is being shown.
  4. Inspecting the DOM now indicates if a dialog has not yet been shown, is currently being shown, or has been hidden after being shown one or more times.

All this explains why my dialog specs broke after upgrading to the latest version of the bootstrap-sass Gem, which includes Bootstrap 2.3.0 (the now-current version). I've written this up as a warning and an explanation to myself and others using Bootstrap modals as to why we're suddenly chasing our tails on things that "should Just Work". The accompanying jsFiddle is an easy way to explore changes in future Bootstrap versions; copy the amended sample modal-dialog code over and have a look.

<div id="myModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Modal header</h3>
</div>
<div class="modal-body">
<p>One fine body…</p>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
<button class="btn btn-primary">Save changes</button>
</div> <!-- modal-footer ->
</div> <!-- modal -->
</div>
<div id="myModal" class="modal hide fade in" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="false" style="display: block;">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Modal header</h3>
</div>
<div class="modal-body">
<p>One fine body…</p>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
<button class="btn btn-primary">Save changes</button>
</div> <!-- modal-footer ->
</div> <!-- modal -->
</div>
<div id="myModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="display: none;">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Modal header</h3>
</div>
<div class="modal-body">
<p>One fine body…</p>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
<button class="btn btn-primary">Save changes</button>
</div> <!-- modal-footer ->
</div> <!-- modal -->
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment