How to “pin” a jQuery UI Dialog in place

Recently, I wanted to “pin” a jQ UI Dialog in place for an application I was designing – the idea being that the user could open the Dialog (non-modal), drag it to the location on the screen they wanted, then scroll up & down the page and interact with content while having the Dialog pinned in its position, say just inside the top-right corner of the viewport.

Surprisingly, I found very little info on doing so (sorry, no documented jQ UI method) but I didn’t let that stop me. Conceptually, I knew I needed first to add a “pin” button to the Dialog itself – I thought the top-left corner of the title bar would be best – then I needed to combine some jQ that would handle my click events for pinning & unpinning. And before long, I had it…

Click to pin (state is currently unpinned):

Click to Unpin (state is currently pinned):

Here’s what I did to achieve this result…

  1. Initialize your jQ UI Dialog; in this example, mine has an ID of ‘MyJqUiDialog’. As part of creating the Dialog, I’m prepending a button to the Title bar that has stock jQ UI styling plus a custom class called ‘PinDialog’.
        autoOpen: false,
        modal: false,
        create: function () {
            $('#MyJqUiDialog').parent().children('.ui-dialog-titlebar').prepend('<button class="ui-button ui-widget ui-state-default ui-corner-all ui-button-icon-only PinDialog" role="button" aria-disabled="false" title="Pin down"><span class="ui-button-icon-primary ui-icon ui-icon-pin-w"></span></button>');
  2. Add a click handler binding to the ‘PinDialog’ class; upon click, this will toggle the Pin class to ‘DialogPinned’ (which also re-styles the icon as seen in the screenshots above), calculate the current position of an unpinned Dialog, change its CSS position to “fixed” and set its CSS top & left to the current position. In other words, it calculates where in the viewport the Dialog currently is & fixes it there.
    $('.PinDialog').click(function () {
        var CurrentDialogPosition = $(this).closest('.ui-dialog').offset();
        var DialogLeft = CurrentDialogPosition.left - $(window).scrollLeft();
        var DialogTop = - $(window).scrollTop();
        $(this).toggleClass('PinDialog DialogPinned').toggleClass('ui-state-highlight ui-state-default').children().toggleClass('ui-icon-pin-w ui-icon-pin-s').closest('.ui-dialog').css({ 'position': 'fixed', 'top': DialogTop, 'left': DialogLeft });


  3. Add a click handler binding to the ‘DialogPinned’ class; upon click, revert to the previous icon and set the CSS position to absolute while also setting its top & left to its absolution position in the window. This is key as it keeps the Dialog from jumping back to the top of the window if say you had scrolled down the page before unpinning it.
    $('.DialogPinned').click(function () {
        $(this).toggleClass('PinDialog DialogPinned').toggleClass('ui-state-highlight ui-state-default').children().toggleClass('ui-icon-pin-s ui-icon-pin-w').closest('.ui-dialog').css({ 'position': 'absolute', 'top': $(this).closest('.ui-dialog').offset().top, 'left': $(this).closest('.ui-dialog').offset().left });
  4. Finally, I have a little CSS to ensure the Pin/Unpin icon displays as expected within the Dialog title bar
    .ui-dialog-titlebar .PinDialog, .ui-dialog-titlebar .DialogPinned {
        float: left;
        height: 20px;
        margin: 0 5px 0 -10px;
        padding: 1px;
        top: 50%;
        width: 20px;

And there you have it – everything you need to create your own jQuery UI Dialog customization to enable the pinning & unpinning of the Dialog on the screen.

Comments are closed.