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 collapsible blocks (https://web.archive.org/web/20120501053458/http://jquerymobile.com/demos/1.1.0/docs/content/content-collapsible.html) (e.g. <div data-role="collapsible">) in a collapsible set collapsible set (https://web.archive.org/web/20120501053458/http://jquerymobile.com/demos/1.1.0/docs/content/content-collapsible-set.html) (e.g. <div data-role="collapsible-set">) the collapsible blocks’ “collapse collapse” (https://web.archive.org/web/20120501053458/http://jquerymobile.com/demos/1.1.0/docs/content/content-collapsible-events.html) 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>

Monday, December 28, 2009

Programmatically Create a ClickOnce Application Shortcut

A common approach for programmatically creating a shortcut to a ClickOnce application is to copy the “Application Reference” (*.appref-ms) file that was created in the user’s start menu when the application was installed.

The following function will create a ClickOnce Application Shortcut (*.appref-ms) file for the currently running ClickOnce application without coping the file that exists in the user’s start menu:

''' <summary>
''' Creates a ClickOnce application reference (*.appref-ms) file for the
''' currently running ClickOnce application.
'''
</summary>
''' <param name="location">
''' Path, including file name, of the new ClickOnce application reference
''' file to create. File should have an ".appref-ms" extension.
'''
</param>
Public Sub CreateClickOnceShortcut( _
   
ByVal location As String)

   
Dim updateLocation As Uri = _
        Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation
   
Dim AppSecurityInfo As New Security.Policy.ApplicationSecurityInfo( _
        AppDomain.CurrentDomain.ActivationContext)
   
Dim DeploymentInfo As ApplicationId = AppSecurityInfo.DeploymentId
   
Dim PublicKey As Byte() = DeploymentInfo.PublicKeyToken

   
Using ShortcutFile As New IO.StreamWriter( _
        location,
False, System.Text.Encoding.Unicode)

        ShortcutFile.Write(updateLocation.ToString().Replace(
" ", "%20"))
        ShortcutFile.Write(
"#"c)
        ShortcutFile.Write(DeploymentInfo.Name)
        ShortcutFile.Write(
", Culture=neutral, PublicKeyToken=")

       
For i As Integer = 0 To (PublicKey.Length - 1)
            ShortcutFile.Write(
"{0:x}", PublicKey(i))
       
Next i

        ShortcutFile.Write(
", processorArchitecture=")
        ShortcutFile.Write(DeploymentInfo.ProcessorArchitecture)

        ShortcutFile.Close()

   
End Using

End
Sub

It appears that the ClickOnce application’s manifest must be signed for the shortcut’s application specific icon to appear. If it is not signed, the default application icon appears.

Monday, December 21, 2009

ASP.NET AJAX Control Toolkit Hidden ComboBox Issue

The AJAX ComboBox control that is included in the September 2009 Release of the ASP.NET AJAX Control Toolkit has a problem whenever the control is hidden when the page is initially rendered. The button for the ComboBox control appears as a 1x1 pixel button and the DropDown list is only 1 or 2 pixels high.

The following is a javascript function I wrote that will correct these issues if it is called right after the ComboBox is made visible.

// Resets the ComboBox indicated by the id argument

// that was hidden when the
// page was initially rendered. This method should

// be called right after the
// hidden ComboBox is made visible. This function

// will correct control sizing
// issues that occur when a ComboBox is not visible

// when the page is initially
// rendered.
//
// Parameters:
// id: Name of the ComboBox control to reset.
// --------------------------------------------------

function ResetComboBox(id) { 

    // Get ComboBox 
    var Combo = Sys.Application.findComponent(id);  

    // Get Button Style 
    var ButtonStyle = Combo.get_buttonControl().style;  

    // Reset Button Image 
    ButtonStyle.height = Combo.get_textBoxControl().offsetHeight + 'px'
    ButtonStyle.width = ButtonStyle.height;

    // Reset Options List 
    var OptionListStyle = Combo.get_optionListControl().style; 
    Combo._optionListHeight = null
    Combo._optionListWidth = null
    OptionListStyle.display = 'block';
}

NOTE: I have only tested this with the September 2009 Release of the ASP.NET AJAX Control Toolkit.