Update Panel .NET

Exploring Microsoft ASP.NET AJAX and jQuery

Posts Tagged ‘jQuery

Goodbye Microsoft AJAX Library

with 4 comments

Microsoft AJAX Library is no more… for me!

No more Sys.<Whatever>!

I’ve seen the light, I shall jQuery all the way… to scripting heaven!

P.S. I may still use one or two JavaScript extensions (e.g. String.format) from the Microsoft AJAX Library!

Written by tzkuei

April 19, 2009 at 10:52 pm

Posted in Microsoft AJAX Library, jQuery

Tagged with

Getting started with Sys.Binding – Part 3

leave a comment »

In part one, I demonstrated how Sys.Binding can be used to bind properties of DOM elements, and in part two, I used a simple JavaScript object to share properties across multiple DOM elements.  In this post, I will expand on the topic by adding components to the mix.  By components I mean objects derived from Sys.Component, that includes Sys.UI.Behavior and Sys.UI.Control.

Sys.Binding works with components by hooking up the propertyChanged event to track changes made to the bound properties, and gets or sets values by invoking the relevant getter and setter functions.

As for the example, I will expand on the one given in part two, and add a slider to allow the user to adjust the range by dragging on the handles, like this:

Screen capture of example

I know there is a slider control in the AJAX Control Toolkit, but it currently does not support multiple handles, and I need two for this example.  I also know there is a MultiHandleSlider control in development, but I need it now!

Well, jQuery UI has a nice slider control that already supports multiple handles, so I will be using it for my example.  Download the 1.5.2 stable build, unzip the archive and add the folder to your web site:

Web site project structure

There is a “slight” problem – the jQuery UI slider cannot be used directly with Sys.Binding, becuase it does not have the necessary property getter and setter functions, i.e. get_value() and set_value(), nor the “propertyChanged” event, required by Sys.Binding.  As a workaround, I wrapped the jQuery UI slider inside a Sys.UI.Control:

Type.registerNamespace("UPDN.jQuery.UI");
UPDN.jQuery.UI.Slider = function(element) {
    UPDN.jQuery.UI.Slider.initializeBase(this, [element]);
    this._slider = $(element);
    this._animate = false;
    this._enabled = true;
    this._handles = [];
    this._max = 100;
    this._min = 0;
    this._orientation = "horizontal";
    this._range = false;
    this._stepping = 0;
    this._steps = 0;
}
UPDN.jQuery.UI.Slider.prototype = {
    initialize: function() {
        var options = {
            animate: this.get_animate(),
            axis: this.get_orientation(),
            handles: this.get_handles(),
            max: this.get_max(),
            min: this.get_min(),
            range: this.get_range(),
            steps: this.get_steps(),
            change: Function.createDelegate(this, this._raiseChangeEvent),
            slide: Function.createDelegate(this, this._raiseSlideEvent),
            start: Function.createDelegate(this, this._raiseStartEvent),
            stop: Function.createDelegate(this, this._raiseStopEvent)
        }
        this._slider.slider(options);
        // Dynamically add value property getter and setter for each handle
        // Property name is "value" + handle.id, as specified in the options.
        // If handle.id is "1" then property is get_value1() and set_value1(value).
        var handles = this.get_handles();
        for (var i = 0; i < handles.length; i++) {
            this._addValueProperty(i, handles[i]);
        }
    },
    dispose: function() {
        this._slider.slider("destroy");
    },
    _addValueProperty: function(i, handle) {
        var propertyName = "value" + handle.id;
        this["get_" + propertyName] = function(index) {
            return function() {
                return this.getValue(index);
            }
        } (i);
        this["set_" + propertyName] = function(index) {
            return function(value) {
                this.setValue(index, value);
            }
        } (i);
        this.add_slide(Function.createDelegate(this, function() {
            this.raisePropertyChanged(propertyName);
        }));
    },
    _raiseChangeEvent: function() {
        var handler = this.get_events().getHandler("change");
        if (handler) {
            handler(this, Sys.EventArgs.Empty);
        }
    },
    _raiseSlideEvent: function() {
        var handler = this.get_events().getHandler("slide");
        if (handler) {
            handler(this, Sys.EventArgs.Empty);
        }
    },
    _raiseStartEvent: function() {
        var handler = this.get_events().getHandler("start");
        if (handler) {
            handler(this, Sys.EventArgs.Empty);
        }
    },
    _raiseStopEvent: function() {
        var handler = this.get_events().getHandler("stop");
        if (handler) {
            handler(this, Sys.EventArgs.Empty);
        }
    },
    add_change: function(handler) {
        /// <summary>Adds a event handler for the change event.</summary>
        /// <param name="handler" type="Function">The handler to add to the event.</param>
        this.get_events().addHandler("change", handler);
    },
    remove_change: function(handler) {
        /// <summary>Removes a event handler for the change event.</summary>
        /// <param name="handler" type="Function">The handler to remove from the event.</param>
        this.get_events().removeHandler("change", handler);
    },
    add_slide: function(handler) {
        /// <summary>Adds a event handler for the slide event.</summary>
        /// <param name="handler" type="Function">The handler to add to the event.</param>
        this.get_events().addHandler("slide", handler);
    },
    remove_slide: function(handler) {
        /// <summary>Removes a event handler for the slide event.</summary>
        /// <param name="handler" type="Function">The handler to remove from the event.</param>
        this.get_events().removeHandler("slide", handler);
    },
    add_start: function(handler) {
        /// <summary>Adds a event handler for the start event.</summary>
        /// <param name="handler" type="Function">The handler to add to the event.</param>
        this.get_events().addHandler("start", handler);
    },
    remove_start: function(handler) {
        /// <summary>Removes a event handler for the start event.</summary>
        /// <param name="handler" type="Function">The handler to remove from the event.</param>
        this.get_events().removeHandler("start", handler);
    },
    add_stop: function(handler) {
        /// <summary>Adds a event handler for the stop event.</summary>
        /// <param name="handler" type="Function">The handler to add to the event.</param>
        this.get_events().addHandler("stop", handler);
    },
    remove_stop: function(handler) {
        /// <summary>Removes a event handler for the stop event.</summary>
        /// <param name="handler" type="Function">The handler to remove from the event.</param>
        this.get_events().removeHandler("stop", handler);
    },
    get_animate: function() {
        /// <value type="Boolean">True if slider handle animation is enabled, false if disabled.</value>
        return this._animate;
    },
    set_animate: function(value) {
        this._animate = value;
    },
    get_enabled: function() {
        /// <value type="Boolean">True if slider is enabled, false if disabled.</value>
        return this._enabled;
    },
    set_enabled: function(value) {
        if (this._enabled !== value) {
            this._enabled = value;
            if (value) {
                this._slider.slider("enable");
            } else {
                this._slider.slider("disable");
            }
            this.raisePropertyChanged("enabled");
        }
    },
    get_handles: function() {
        /// <value type="Object">Specify boundaries for one or more handles.</value>
        return this._handles;
    },
    set_handles: function(value) {
        this._handles = value;
    },
    get_max: function() {
        /// <value type="Number">The maximum value of the slider.</value>
        return this._max;
    },
    set_max: function(value) {
        this._max = value;
    },
    get_min: function() {
        /// <value type="Number">The minimum value of the slider.</value>
        return this._min;
    },
    set_min: function(value) {
        this._min = value;
    },
    get_orientation: function() {
        /// <value type="String">The orientation of the slider.</value>
        return this._orientation;
    },
    set_orientation: function(value) {
        this._orientation = value;
    },
    get_range: function() {
        /// <value type="Boolean">True if slider range is enabled, false if disabled.</value>
        return this._range;
    },
    set_range: function(value) {
        this._range = value;
    },
    get_stepping: function() {
        /// <value type="Number">The number to jump per slide.</value>
        return this._stepping;
    },
    set_stepping: function(value) {
        this._stepping = value;
    },
    get_steps: function() {
        /// <value type="Number">The number of steps the slider have.</value>
        return this._steps;
    },
    set_steps: function(value) {
        this._steps = value;
    },
    getValue: function(index) {
        /// <summary>Gets the current value of the specified handle.</summary>
        /// <param name="index" type="Number">The index/number of the handle, zero-based.</param>
        return this._slider.slider("value", index);
    },
    setValue: function(index, value) {
        /// <summary>Sets the value of the specified handle.</summary>
        /// <param name="index" type="Number">The index/number of the handle, zero-based.</param>
        /// <param name="value" type="Number">The value to be set.</param>
        this._slider.slider("moveTo", value, index);
    }
}
UPDN.jQuery.UI.Slider.registerClass("UPDN.jQuery.UI.Slider", Sys.UI.Control);

Save this script as UPDN.jQuery.UI.Slider.js and add it the web site project.

By wrapping the jQuery UI slider inside a Sys.UI.Control, I have exposed the necessary property getters and setters and hooked up the “slide” event to raise the propertyChanged event whenever the user moves the slider handle(s).

Include a few stylesheets to the page, between the <head> tags:

<link href="jquery.ui-1.5.2/themes/flora/flora.css" rel="stylesheet" type="text/css" />
<link href="jquery.ui-1.5.2/themes/flora/flora.slider.css" rel="stylesheet" type="text/css" />
<style type="text/css" media="all">
#Slider1 { margin-top: 1.5em; }
.label-1 { position: absolute; left: 0; top: -1.1em; }
.label-2 { position: absolute; right: 0; top: -1.1em; }
</style>

Add the <asp:ScriptManager> control and include the necessary scripts:

<asp:ScriptManager ID="ScriptManager1" runat="server">
    <Scripts>
        <asp:ScriptReference Path="~/MicrosoftAjaxTemplates.js" ScriptMode="Auto" />
        <asp:ScriptReference Path="~/jquery.ui-1.5.2/jquery-1.2.6.js" ScriptMode="Auto" />
        <asp:ScriptReference Path="~/jquery.ui-1.5.2/ui/ui.core.js" ScriptMode="Auto" />
        <asp:ScriptReference Path="~/jquery.ui-1.5.2/ui/ui.slider.js" ScriptMode="Auto" />
        <asp:ScriptReference Path="~/UPDN.jQuery.UI.Slider.js" ScriptMode="Auto" />
    </Scripts>
</asp:ScriptManager>

Add the mark-up for the slider to the page:

<asp:CheckBox ID="CheckBox1" runat="server" Text="Use slider" Checked="true" />
<div id="Slider1" class="ui-slider-2">
    <span class="label-1">0</span>
    <span class="label-2">100</span>
</div>

Add the following blocks of JavaScript to the pageLoad() function:

var slider = $create(UPDN.jQuery.UI.Slider, {
    handles: [ { start: 0, min: 0, max: 100, id: "1" },
               { start: 100, min: 0, max: 100, id: "2" } ],
    range: true
}, null, null, $get("Slider1"));

This block creates the slider component, and assigns it the the slider variable for later usage.

$create(Sys.Binding, {
    target: slider,
    targetProperty: "enabled",
    source: $get("CheckBox1"),
    path: "checked",
    mode: Sys.BindingMode.oneWay
});

This block creates the binding between the check box element and the “enabled” property of the slider component, so the user can enable or disable the slider by selecting the check box.

$create(Sys.Binding, {
    target: slider,
    targetProperty: "value1",
    source: range,
    path: "min",
    mode: Sys.BindingMode.twoWay
});
$create(Sys.Binding, {
    target: slider,
    targetProperty: "value2",
    source: range,
    path: "max",
    mode: Sys.BindingMode.twoWay
});

This blocks binds the slider handles to the range JavaScript object.

Start the web site and you should be able to change the min and max values by entering a value into the text boxes or moving the handles on the slider, and watch the changes reflected in all the bound elements.

Written by tzkuei

November 16, 2008 at 10:58 pm

Posted in Microsoft AJAX Library

Tagged with ,