Monday, April 16, 2012

jQuery Mobile: Finding the “Real” Collapse Event

I have found that if you have a group of jQuery Mobile (Version 1.1.0) collapsible blocks (e.g. <div data-role="collapsible">) in a collapsible set (e.g. <div data-role="collapsible-set">) the collapsible blocks’ “collapse” event seems to fire more often than it should.

For example, if a page contains a collapsible set containing five collapsible blocks that are currently collapsed and one of the blocks is expand, a “collapse” event will be raised for the other four blocks in the set, even though they were already collapsed. I would not have expected to see any “collapse” events in that situation.

Then, if one of the other collapsed blocks is expanded, I would expect to only see a “collapse” event raised for the one block that was expanded, but a “collapse” event is raised for all of the blocks in the collapsible set (except for the one that was just expanded).

For my purposes I, only want to know about the “collapse” events that occur when a collapsible block is truly collapsed (i.e. the collapsible block went from an expanded state to a collapsed state). To accomplish this, I add a new attribute to the collapsible block, called data-previous-state. On the “expand” event for the collapsible block, I set this attribute to “expanded”. On the “collapse” event, I check to see if the data-previous-state attribute is set to “expanded”. If it is, I perform my collapse logic and set the data-previous-state attribute to “collapsed”. If the data-previous-state attribute is set to “collapsed”, I ignore it.

The following is the code for a page that demonstrates this issue. The collapse events highlighted in yellow are the “real” collapse events.

<!DOCTYPE html>

<html>

<head>

    <title>jQuery Mobile Collapsible Content Events</title>

    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css" />

    <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>

    <script type="text/javascript" src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"></script>

    <style>

        #EventOutput

        {

            border-top: 1px dotted Grey;

        }

        #EventOutput div

        {

            border-bottom: 1px dotted Grey;

        }

        .highlight

        {

            background-color: Yellow;

        }

    </style>

</head>

<body>

    <div id="CollapsibleContentEventsPage" data-role="page">

    <div data-role="header" data-position="fixed">

        <h1>

            Collapsible Content Events

        </h1>

    </div>

    <div data-role="content">

      <div data-role="collapsible-set">

        <div class="section" data-section="1" data-role="collapsible" data-content-theme="d">

          <h3>

            Section 1

          </h3>

          <p>

            I'm the collapsible set content for section 1.

          </p>

        </div>

        <div class="section" data-section="2" data-role="collapsible" data-content-theme="d">

          <h3>

            Section 2

          </h3>

          <p>

            I'm the collapsible set content for section 2.

          </p>

        </div>

        <div class="section" data-section="3" data-role="collapsible" data-content-theme="d">

          <h3>

            Section 3

          </h3>

          <p>

            I'm the collapsible set content for section 3.

          </p>

        </div>

        <div class="section" data-section="4" data-role="collapsible" data-content-theme="d">

          <h3>

            Section 4

          </h3>

          <p>

            I'm the collapsible set content for section 4.

          </p>

        </div>

        <div class="section" data-section="5" data-role="collapsible" data-content-theme="d">

          <h3>

            Section 5

          </h3>

          <p>

            I'm the collapsible set content for section 5.

          </p>

        </div>

      </div>

    </div>

    <div data-role="content" data-theme="d">

      <h3>

        Event Details

      </h3>

      <div id="EventOutput">

      </div>

    </div>

    </div>

 

<script type="text/javascript">

 

    $("#CollapsibleContentEventsPage").live("pageinit", function (event) {

 

        $("#EventOutput").prepend("<div>" + (new Date()).getTime() + ": pageinit</div>");

 

        $("div.section").on("expand", function () {

            $(this).data("previous-state", "expanded");

        });

 

        $("div.section").on("collapse", function () {

 

            var eventInfo;

 

            if ($(this).data("previous-state") == "expanded") {

                eventInfo = "<div class='highlight'>"

            }

            else {

                eventInfo = "<div>"

            }

 

            eventInfo += (new Date()).getTime()

                + ": collapse - Section "

                + $(this).data("section")

                + "</div>";

 

            $("#EventOutput").prepend(eventInfo);

 

            $(this).data("previous-state", "collapsed");

        });

    });

</script>

</body>

</html>

No comments: