Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

How the jQuery UI uses the parts library


May 08, 2021 jQuery UI


Table of contents


How the jQuery UI uses the Widget Factory

In this section, we'll show you how the jQuery UI uses part libraries.

In the following example, we'll create a progress bar, which can be done by calling jQuery.widget() has two parameters: the name of the plug-in you want to create, and the object text that contains the functions that support the plug-in. W hen a plug-in is called, it creates a new plug-in instance in which all functions are executed. T his is different from the standard jQuery plug-in in two important ways. F irst, the context is an object, not a DOM element. Second, context is always a single object, not a collection.

$.widget( "custom.progressbar", {
    _create: function() {
        var progress = this.options.value + "%";
        this.element
            .addClass( "progressbar" )
            .text( progress );
    }
});

The name of the plug-in must contain a namespace, in which case we custom namespace. You can only create a deep namespace, so custom.progressbar is a valid plug-in name, while very.custom.progressbar not a valid plug-in name.

We see that the Widget Factory gives us two properties. this.element is a jQuery object that contains an element. I f our plug-in is called on a jQuery object that contains multiple elements, a separate plug-in instance is created for each element, and each this.element T he second property, this.options is a hash that contains key names/key value pairs for all plug-in options. These options can be passed on to the plug-in as follows:

$( "<div></div>" )
    .appendTo( "body" )
    .progressbar({ value: 20 });

When we jQuery.widget() it extends jQuery by adding functions to jQuery.fn (the system used to create the standard plug-in). T he added function name is based on the name you passed to jQuery.widget() without the namespace -"progressbar". T he option passed to the plug-in is to get the value of the setting in the plug-in instance. A s the following example shows, we can specify a default value for either option. When designing your API, you should be aware of the most common usage of your plug-ins so that you can set the appropriate default values and make sure that all options are truly optional.

$.widget( "custom.progressbar", {
 
    // Default options.
    options: {
        value: 0
    },
    _create: function() {
        var progress = this.options.value + "%";
        this.element
            .addClass( "progressbar" )
            .text( progress );
    }
});

Call the plug-in method

Now that we can initialize our progress bar, we'll execute the action by calling the method on the plug-in instance. T o define a plug-in method, we refer to jQuery.widget() We can also define the "private" method by underlining the function name.

$.widget( "custom.progressbar", {
 
    options: {
        value: 0
    },
 
    _create: function() {
        var progress = this.options.value + "%";
        this.element
            .addClass( "progressbar" )
            .text( progress );
    },
 
    // Create a public method.
    value: function( value ) {
 
        // No value passed, act as a getter.
        if ( value === undefined ) {
            return this.options.value;
        }
 
        // Value passed, act as a setter.
        this.options.value = this._constrain( value );
        var progress = this.options.value + "%";
        this.element.text( progress );
    },
 
    // Create a private method.
    _constrain: function( value ) {
        if ( value > 100 ) {
            value = 100;
        }
        if ( value < 0 ) {           
 value = 0;         }         
return value;   
  } 
}); 

In order to call a method on a plug-in instance, you can pass the name of the method to the jQuery plug-in. If you call a method that accepts parameters, you simply pass them after the method name.

Note: The method is executed by passing the method name to the same jQuery function used to initialize the plug-in. T his is done to prevent jQuery namespace contamination when the chain method is called. Later in this chapter, we'll see other uses that look more natural.

var bar = $( "<div></div>" )
    .appendTo( "body" )
    .progressbar({ value: 20 });
 
// Get the current value.
alert( bar.progressbar( "value" ) );
 
// Update the value.
bar.progressbar( "value", 50 );
 
// Get the current value again.
alert( bar.progressbar( "value" ) );

Use the option

option() automatically provided to the plug-in. option() method allows you to get and set options after initialization. T he method is like .css() and .attr() you can pass only one name to use as a value taker, you can pass a name and value to use as a seter, or you can pass a hash of a key name/key value pair to set multiple values. W hen used as a value taker, the plug-in returns the current value of the option that corresponds to the incoming name. W hen used as a seter, the _setOption method is called by each of the options set. W e can specify a method in our _setOption to react to option changes. For actions that change the options to perform independently, we can _setOptions

$.widget( "custom.progressbar", {
    options: {
        value: 0
    },
    _create: function() {
        this.options.value = this._constrain(this.options.value);
        this.element.addClass( "progressbar" );
        this.refresh();
    },
    _setOption: function( key, value ) {
        if ( key === "value" ) {
            value = this._constrain( value );
        }
        this._super( key, value );
    },
    _setOptions: function( options ) {
        this._super( options );
        this.refresh();
    },
    refresh: function() {
        var progress = this.options.value + "%";
        this.element.text( progress );
    },
    _constrain: function( value ) {
        if ( value > 100 ) {
            value = 100;
        }
        if ( value < 0 ) {          
   value = 0;   
      } 
        return value;    
 } 
}); 

Add a callback

The easiest way to extend an extension is to add callbacks so that users can react when the state of the plug-in changes. W e can see how the following example adds a callback to the progress bar when the progress reaches 100%. _trigger() has three parameters: a callback name, a jQuery event object that initiates the callback, and a data hash related to the event. C allback names are the only required parameters, but other parameters are useful for users who want to implement custom functionality on plug-ins. F or example, if we create a dragable plug-in, we can pass a mousemove event when a drag callback is triggered, which will allow the user to react to drag based on the x/y coordinates provided by the event object. Note that the original _trigger() must be a jQuery event, not a native browser event.

$.widget( "custom.progressbar", {
    options: {
        value: 0
    },
    _create: function() {
        this.options.value = this._constrain(this.options.value);
        this.element.addClass( "progressbar" );
        this.refresh();
    },
    _setOption: function( key, value ) {
        if ( key === "value" ) {
            value = this._constrain( value );
        }
        this._super( key, value );
    },
    _setOptions: function( options ) {
        this._super( options );
        this.refresh();
    },
    refresh: function() {
        var progress = this.options.value + "%";
        this.element.text( progress );
        if ( this.options.value == 100 ) {
            this._trigger( "complete", null, { value: 100 } );
        }
    },
    _constrain: function( value ) {
        if ( value > 100 ) {
            value = 100;
        }
        if ( value < 0 ) {  
           value = 0;       
  }  
       return value;  
   }
 }); 

Callback functions are essentially just additional options, so you can get and set them just like any other option. W henever a callback is executed, a corresponding event is triggered. T he event type is determined by connecting the name of the plug-in and the name of the callback function. B oth callbacks and events accept two identical parameters: an event object and a data hash related to the event, as shown in the following example. Y our plug-in may need to include features that prevent users from using it, and the best way to do this is to create a callback that you can undo. U sers can undo callbacks or related events, as they do with any native event, event.preventDefault() false If the user undoes the _trigger() false that you can implement the appropriate functionality within the plug-in.

var bar = $( "<div></div>" )
    .appendTo( "body" )
    .progressbar({
        complete: function( event, data ) {
            alert( "Callbacks are great!" );
        }
    })
    .bind( "progressbarcomplete", function( event, data ) {
        alert( "Events bubble and support many handlers for extreme flexibility." );
        alert( "The progress bar value is " + data.value );
    });
 
bar.progressbar( "option", "value", 100 );

Essence

Now that we've seen how to create a plug-in using the Widget Factory, let's see how it actually works. W hen you jQuery.widget() creates a constructor for the plug-in and sets the object that you pass in as a prototype for the plug-in instance. A ll features that are automatically added to the plug-in come from a basic jQuery.Widget.prototype When a plug-in instance is created, it is stored on the original DOM element using jQuery.data with the plug-in name as the key name.

Because plug-in instances are linked directly to DOM elements, you can access plug-in instances directly without having to traverse plug-in methods. This will allow you to call methods directly on the plug-in instance without having to pass the method name in string form, and you can also access the plug-in's properties directly.

var bar = $( "<div></div>" )
    .appendTo( "body" )
    .progressbar()
    .data( "progressbar" );
 
// Call a method directly on the plugin instance.
bar.option( "value", 50 );
 
// Access properties on the plugin instance.
alert( bar.options.value );
您也可以在不遍历插件方法的情况下创建一个实例,通过选项和元素直接调用构造函数即可:
var bar = $.custom.progressbar( {}, $( "<div></div>" ).appendTo( "body") );
 
// Same result as before.
alert( bar.options.value );

Prototype of the extension

The biggest benefit of plug-ins having constructors and prototypes is that they are easy to extend. B y adding or modifying the methods on the plug-in prototype, we can modify the behavior of all instances of the plug-in. For example, if we want to add a method to the progress bar to reset the progress to 0%, we can add this method to the prototype, which will be callable on all plug-in instances.

$.custom.progressbar.prototype.reset = function() {
    this._setOption( "value", 0 );
};

For more details on extension widgets and how to create a brand new widget on an existing widget, check out Widget extension widgets with widgets.

Clean

In some cases, users are allowed to apply the plug-in and then cancel the app. Y ou _destroy() the () method. W ithin _destroy() you should undo all actions made by the plug-in during initialization and later use. _destroy() .destroy() method, which is .destroy() called when the plug-in instance-bound element is removed from the DOM, so this can be used for garbage collection. The basic .destroy() common cleanup operations, such as removing instance references from the DOM element of a widget, unbinding all events in the widget namespace from the element, and _bind()

$.widget( "custom.progressbar", {
    options: {
        value: 0
    },
    _create: function() {
        this.options.value = this._constrain(this.options.value);
        this.element.addClass( "progressbar" );
        this.refresh();
    },
    _setOption: function( key, value ) {
        if ( key === "value" ) {
            value = this._constrain( value );
        }
        this._super( key, value );
    },
    _setOptions: function( options ) {
        this._super( options );
        this.refresh();
    },
    refresh: function() {
        var progress = this.options.value + "%";
        this.element.text( progress );
        if ( this.options.value == 100 ) {
            this._trigger( "complete", null, { value: 100 } );
        }
    },
    _constrain: function( value ) {
        if ( value > 100 ) {
            value = 100;
        }
        if ( value < 0 ) {     
        value = 0;     
    }
          return value;  
   },  
   _destroy: function() { 
        this.element          
   .removeClass( "progressbar" )         
    .text( "" );   
  }
 }); 

Close the comment

Widget Factory is just one way to create a stated plug-in. T here are a number of other different models available here, each with its own strengths and weaknesses. Widget Factory solves a number of common problems and greatly improves efficiency, while also greatly improving the re-use of code, making it suitable for jQuery UI and other stated plug-ins.

Note that in this section we used the custom namespace. ui namespace is reserved for the official jQuery UI plug-in. W hen you create your own plug-ins, you should create your own namespace. This makes it clearer where the plug-in comes from and what scope it belongs to.