Search code examples
jquery-uipublish-subscribeobserver-pattern

Why does my jQuery UI range slider not respond to pubsub events?


I am creating a calculator based on the jQuery UI range slider and have a setup that works. I have a bindEvents function in my application that binds the slider to the slide event:

    // this is where I bind all slide events
    bindEvents: function() {
        // hold on to the value of this
        var self = CloudCalc;

        // bind the slider's slide event to a data event
        self.sl.on('slide', this.setSliderOutputValue);             
    }

and then here is the handler that faithfully executes my event:

setSliderOutputValue: function (event, ui) {
        // hold on to the value of this
        var self = CloudCalc;

        // show the ui output value on slide event
        self.output.html( ui.value + " INSTANCE");  
}

Now I want to trigger multiple events when the user slides the slider. So I would like to use the observer pattern in this setup like so (using addyosmani's pubsub plugin):

bindEvents: function() {
    // hold on to the value of this
    var self = CloudCalc;

    // bind the slider's slide event and publish it
    self.sl.on('slide', $.publish('slider/moved'));             
}

Here's the subscription:

subscriptions: function () {
    $.subscribe('slider/moved', this.setSliderOutputValue);     
}

So when this subscription calls the setSliderOutputValue event, I get a console error saying:

Uncaught TypeError: Cannot read property 'value' of undefined

That means the reference to ui property is not getting passed to the setSliderOutputValue event.

How do I pass the ui property? Please correct me if I am doing this wrong.


Solution

  • So here is what I got working with a pubsub pattern. I added the $.publish call to the setSliderOutputValue method like this:

    setSliderOutputValue: function (event, ui) {
            // hold on to the value of this
            var self = CloudCalc;
    
            // show the ui output value on slide event
            self.output.html( ui.value + " INSTANCE");
            $.publish('slider/moved')   
    },
    

    And then added to my subscription like so:

    subscriptions: function () {
            $.subscribe( 'plan/results', this.parseJSON );      
            $.subscribe( 'slider/moved', this.setVMval );
            $.subscribe( 'slider/moved', this.setRAMval );
            $.subscribe( 'slider/moved', this.setHDval );           
    },
    

    And voila! I can now listen to and trigger multiple events based on a single event with my jQuery range slider.

    Any suggestions to improve this code by refactoring the multiple subscribe calls into one single call are welcome.