1

I need to observe events from a couple of jQuery UI dialogs. They all come standard with a few events that you can listen for. No problem so far.

I could use this to bind a function to the open event:

$(document).bind('dialogopen', function() {});

However I need to distinguish from which dialog the event origins. For example:

$('#dialog1').dialog();
$('#dialog2').dialog();

Opening either of them will trigger the same event. The function bound to document will fire for both dialogs when they are opened. This is not what I wish for. I found two possible solutions and neither feels great but would at least do the job.

Solution 1: Trigger a custom event by the callback function for the open event

// Trigger events
$('#dialog1').dialog({open: function() {
        $(this).trigger('dialog1open')
    }
});
$('#dialog2').dialog({open: function() {
        $(this).trigger('dialog2open')
    }
});

// Observe events
$(document).bind('dialog1open', function() {
    //actions specifik to dialog 1 open event
});
$(document).bind('dialog2open', function() {
    //actions specifik to dialog 2 open event
});

This way would require me to write custom functions for all events, on all dialogs when initiating them, just to forward it with an event name specific to each dialog.

Solution 2: Capture the target in the event parameter. It would look something like this:

$(document).bind('dialogopen', function(event) {
    el = event.target; // get the element triggering the event
    switch(el.id) { // Action depending on the triggers id
        case dialog1:
            //do something
            break;
        case dialog2:
            //do something else
            break
    }
});

This way on the other hand requires me to have a load of switch cases for each event I'm interested in capturing.

Would writing a wrapping plugin be a good idea here? A plugin that forces you to give an id to each dialog. It would then retrigger each event with the id as prefix or suffix. Opening #dialog1 would for example trigger the custom event dialog1open.

Ideas or concrete solutions would be appreciated here

Edit: A crucial thing I did not mention is that I have observers that the subject (Like #dialog1 and #dialog2) does not know of. This must be taken into consideration.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Anders
  • 499
  • 1
  • 5
  • 18

3 Answers3

1

I could be wrong, but it seems like you're overthinking the problem here.

If you want to bind to an individual dialog's open event, you were going down the correct path with Solution 1, but you don't want to trigger the event because, once you are in that function, the event has already been triggered...

// Trigger events
$('#dialog1').dialog({open: function() {
        // Don't do this.
        // $(this).trigger('dialog1open')

        // Just do what you want to do in response to this particular dialog opening.
    }
});
$('#dialog2').dialog({open: function() {
        // Again, don't do this.
        // $(this).trigger('dialog2open')

        // Just do what you want to do in response to this particular dialog opening.
    }
});

Now, if you want to get some code reuse (AKA, maybe the responses are almost identical), you can write a separate function AND pass in parameters to customize the response. So...something like this:

$('#dialog1').dialog({
    open: openAlert("dialog1");
});
$('#dialog2').dialog({
    open: openAlert("dialog2");
});

function openAlert(dialogName) {
    alert(dialogName + " just opened up!");
}

That way, you get some reuse, but avoid all the case statements, etc. (Of course, you can make this more complicated for your specific purposes.)

JasCav
  • 34,458
  • 20
  • 113
  • 170
  • I might have forgotten to mention one crucial thing about the problem. I'm using observers that #dialog1 and #dialog2 not necessarily know of. $(document) will delegate actions and events to the observers as described here: http://stackoverflow.com/questions/12590091/jquery-observer-pattern I will try to reflect this in the question – Anders Oct 10 '12 at 18:53
1

I'd wrap all the dialogues in a div, and attach a listener to it.

$("#dialog_wrapper").delegate(".dialog", "dialogopen", function(e){
    var open_dialog_id = $(this).attr("id"); //get id of child dialog

    /* do whatever */
});

But I agree with JasCav, you may be overthinking it.

MalSu
  • 541
  • 3
  • 11
0

MalSu led me in the right direction with .delegate. Upgrading jQuery UI and jQuery to latest versions I was able to use .on

Here is my test example

From body

<div id="dialog1">Dialog number one</div>
<div id="dialog2">Dialog number two</div>
<button id="d1Opener">Open Dialog One</button>
<button id="d2Opener">Open Dialog Two</button>

From <script>

$(document).ready(function() {
    $('#dialog1, #dialog2').dialog({
        modal: true,
        autoOpen: false
    });
    $('#d1Opener').click(function() {
        $('#dialog1').dialog('open');
    });
    $('#d2Opener').click(function() {
        $('#dialog2').dialog('open');
    });
    $(document).on('dialogopen', function() {
        console.log('A dialog was opened');
    });
    $(document).on('dialogopen', '#dialog1', function() {
        console.log('Dialog1 was opened');
    });
    $(document).on('dialogopen', '#dialog2', function() {
        console.log('Dialog2 was opened');
    });
});
Anders
  • 499
  • 1
  • 5
  • 18