I have been writing a jQuery widget for a couple of days now. Originally I needed this functionality for something I am writing at work, but I felt like I could abstract it a little more so here I am. I think it's about finished for now, I may add some features depending on how It gets used (if it does).This is my first jQuery widget and I have been programming in JavaScript for just over a month now, so I don't think the code will be particularly great, but I've tried my hardest.I have done some vague testing and it does seem to work in all browsers.My main gripes are validation of the options, of which I don't really know how to do, however, I am going to do some proper research on this and come back to it.There a few other problems with it but I think that this is not the right place to ask about those, so will leave it for now.I would just like some feedback on my coding, how to improve/do it better, now and in the future. It's quite a big chunk of code but I didn't see anything in the FAQ about length of code.I've also attached a jsFiddle so you can mess with it: http://jsfiddle.net/jCVzp/2/I've tried to comment as best as I can and have noted all the options in the file description, and more guidance needed, just ask.All the CSS is present in the jsFiddle, didn't think it was necessary to post it here.Any time and help is greatly appreciated.(function($) {            /*             *   Document   : list-widget-0.1            *   Created on : 06-Aug-2012, 20:53:49            *   Author     : aydin hassan            *   Description:            *       This widget is designed to be attatched to a div            *                   *       Using the options you can specify one of three list types:            *           1.) a normal list if items (normal)            *           2.) a list of items with a cross/tick img depending on its status (act-deact)            *               ---Clicking the image will toggle its status (change the img and class) and run a provided callback            *           3.) a list of items with a trash can icon (remove)            *               ---Click the image will run a supplied calback and then remove the item            *            *       Each of the lists has various callbacks:            *           1.) The global click callback (selectabble.clickCallBack), if passed, will launch on clicked an element for any list type            *           2.) The global click off callback (selectable.clickOffCallBack), if passed, will launch when an item is clicked off.            *               ---Works in conjuction with selectable.sticky - if this is set to true elements will stay higlighted until they are clicked off            *               ---NOTE: click off callback will not be processed if selectable.sticky is set to true            *           3.) The act-deact callback, if passed, will run after a user has clicked the img, or, if there is no global click callback (selectabble.clickCallBack) it will             *               run when the li element is clicked            *           4.) The remove callback, if passed, will run after the user clicks on the trash-can icon            *           5.) The add button callback, if passed, will run when a user clicks the add button            *            *       List data:            *           The list data must be an object of the following form:            *               act-deact:            *               var data = {            *                   0:{name:list item 1,activated:true},            *                   1:{name:list item 2,activated:true},            *                   2:{name:list item 3,activated:false}            *               };            *                           *               normal/remove:            *               var data = {            *                   0:{name:list item 1},            *                   1:{name:list item 2},            *                   2:{name:list item 3}            *               };            *                   *       Other options:            *           title:          ---The title of the list box            *           description:    ---Some description of the data            *           searchBar:      ---BOOL - To display a filter box            *           addButton:      ---BOOL - To display an add button            *           idStyle:        ---A string to prepend to the id of the item id in the data object to use as the li element id attribute            *                       */                $.widget( widgets.adminList, {            // These options will be used as defaults            options: {               list: null,              title: Title,              description: Some description,              searchBar: true,              addButton: false,              addCallBack: null,              listType: normal,              idStyle: li-id-,              removeCallBack: null,              toggleCallBack: null,              selectable: null                },            // Set up the widget            _create: function() {            },            _init: function() {                var options = this.options;                //Build the container elements                this._buildTableHead();                //switch type of list and run setup function for specified type                switch (options.listType) {                    case normal: this._setUpNormal();                        break;                    case act-deact: this._setUpActDeact();                        break;                    case remove: this._setUpRemove();                        break;                }                //If the selectable options are configured then we may want sticky elements (hover css stays until clciked again, or another elements is clicked)                //And there may also be click on and click off callbacks                if(options.selectable != null) {                    $(.list-widget-list-container .list-widget-list li a).live('click',(function(e) {                        //prevent the href() from being followed, href is needed for IE to display hover                        e.preventDefault();                        //If we want elements to stick                        if(options.selectable.stick) {                            //If this element is stuck already                            //unstick it and run click off call back if supplied                            if($(this).hasClass(selected)) {                                $(this).removeClass(selected);                                if(options.selectable.clickOffCallBack != null){                                    options.selectable.clickOffCallBack(this);                                }                            //Else unstick any other elements                            //Stick this element                            //and run click callback                            } else {                                $(.list-widget-list-container .list-widget-list).find(.selected).removeClass(selected);                                $(this).addClass(selected);                                if(options.selectable.clickCallBack != null){                                    options.selectable.clickCallBack(this);                                }                            }                        //If we don't want to stick just run click on callback if supplied                        } else {                            if(options.selectable.clickCallBack != null){                                options.selectable.clickCallBack(this);                            }                        }                    }));                }                //If add callback is supplied                //create click event                if(options.addButton && options.addCallBack != null) {                    $(.list-widget-head-div .header-table .add-but).click(function() {                        options.addCallBack(this);                    });                }                //create event for filter box                var that = this;                                    $(.list-widget-head-div .header-table .list-search-box).bind(keyup,function(){                    that._listFilter(this);                });                //Add the list elements                this.add(options.list);            },            _listFilter:function(e){                var filter = $(e).val(); // get the value of the input, which we filter on                var list = $(.list-widget-list-container .list-widget-list);                //only filter if value exists                if(!filter || filter.length < 1 ){                    list.find(li).show();                }                else{                    list.find(li).each(function(){                        //if a element text contains the filter value, hide it                        if($(a, this).text().toLowerCase().indexOf(filter.toLowerCase()) == -1  ){                            $(this).hide();                        }                        else{                            //else show it                            $(this).show();                        }                    });                }            },            _buildTableHead:function(){                //get the current options                var options = this.options;                //get the div the widget has been attatched to                var self = this.element;                //build table header                var headCells = $(<tr />)                        .append($('<td  />')                            .attr(width,33%)                            .attr(height,45px)                            .append($('<p />')                                .addClass(title)                                .text(options.title)                            )                        );                //depending on the options;                //add a search bar and add button                //if we want searchbar and add button..                if(options.searchBar && options.addButton) {                    headCells.append($('<td  />')                        .attr(width,33%)                        .attr(height,45px)                        .attr(text-align,center)                        .append($('<img />')                            .addClass(add-but)                            .attr(src,add-image.png)                        )                    )                    .append($('<td  />')                        .attr(width,33%)                        .attr(height,45px)                        .append($('<input />')                            .attr(type,text)                            .addClass(list-search-box)                        )                    );                //if we only want add button                } else if (!options.searchBar && options.addButton) {                    headCells.append($('<td  />')                        .attr(width,50%)                        .attr(align,center)                        .append($('<img />')                            .addClass(add-but)                            .attr(src,add-image.png)                        )                    );                //if we only want search bar                } else if (options.searchBar && !options.addButton) {                    headCells.append($('<td  />')                        .attr(width,50%)                        .append($('<input />')                            .attr(type,text)                            .addClass(list-search-box)                        )                    );                }                //Build the tables and append the cells                self.append($('<div />')                        .addClass(list-widget-head-div)                        .addClass(ui-corner-top)                        .append($('<table />')                            .addClass(header-table)                            .append(headCells)                        )                        //Add the description if present                        .append($(<p />)                            .addClass(descript)                            .text(options.description)                    )                );                //Add the actual list element                self.append($(<div />)                    .addClass(list-widget-list-container)                    .addClass(ui-corner-bottom)                        .append($(<ul />)                        .addClass(list-widget-list)                    )                );            },            _setUpNormal:function(){                //get the current options                var options = this.options;            },            _setUpActDeact:function(){                //get the current options                var options = this.options;                //click event upon clicking the item image                //Changes the status and can be provided with a call back                //which has access to the clicked element                //If there is no clickCallBack supplied, we apply the toggle action to the whole li element                if(options.selectable.clickCallBack == null) {                    $(.list-widget-list-container .list-widget-list li).live('click',function(e){                        //get the clicked element                        var imgElem = $(this).find(img.list-img);                        //var to store status                        var active;                        //get status of item                        //and remove the class                        if(imgElem.hasClass(deactivated)) {                            active = false;                            imgElem.removeClass(deactivated);                        } else {                            active = true;                            imgElem.removeClass(activated);                        }                        //add the loading class                        imgElem.addClass(loading);                        imgElem.attr(src,ajax-loader.gif)                        //if callback has been provided, run it                        if(options.toggleCallBack != null) {                            options.toggleCallBack(this)                        }                        //remove loading class                        imgElem.removeClass(loading);                        //add the oposite class(item has been toggled)                        if(active) {                            imgElem.addClass(deactivated);                            imgElem.attr(src,cross.png)                        } else {                            imgElem.addClass(activated);                            imgElem.attr(src,tick.png)                        }                    });                //if there is a clickCallBack then we just apply the toggle event to the image                } else {                    $(.list-widget-list-container .list-widget-list li img.list-img).live('click',function(e){                        //get the clicked element                        var imgElem = $(this);                        //var to stored status                        var active;                        //get status of item                        //and remove the class                        if(imgElem.hasClass(deactivated)) {                            active = false;                            imgElem.removeClass(deactivated);                        } else {                            active = true;                            imgElem.removeClass(activated);                        }                        //add the loading class                        imgElem.addClass(loading);                        imgElem.attr(src,ajax-loader.gif)                        //if callback has been provided, run it                        if(options.toggleCallBack != null) {                            options.toggleCallBack(this)                        }                        //remove loading class                        imgElem.removeClass(loading);                        //add the oposite class(item has been toggled                        if(active) {                            imgElem.addClass(deactivated);                            imgElem.attr(src,cross.png)                        } else {                            imgElem.addClass(activated);                            imgElem.attr(src,tick.png)                        }                    });                }            },            _setUpRemove:function(){                //get the current options                var options = this.options;                //click event upon clicking the delete image                //runs a provided callback and the removes item                $(.list-widget-list-container .list-widget-list li img.list-img).live('click',function(e){                    //if callback has been provided, run it                    if(options.removeCallBack != null) {                        options.removeCallBack(this)                    }                    //remove element                    $(this).parent().remove();                });            },            // Use the _setOption method to respond to changes to options            _setOption: function( key, value ) {              switch( key ) {                case clear:                  // handle changes to clear option                  break;              }              // In $ UI 1.8, you have to manually invoke the _setOption method from the base widget              $.Widget.prototype._setOption.apply( this, arguments );              // In $ UI 1.9 and above, you use the _super method instead              this._super( _setOption, key, value );            },            // Use the destroy method to clean up any modifications your widget has made to the DOM            destroy: function() {              // In $ UI 1.8, you must invoke the destroy method from the base widget              $.Widget.prototype.destroy.call( this );              // In $ UI 1.9 and above, you would define _destroy instead of destroy and not call the base method            },            /* This fuction when presented with an object in the following format             * var data = {             *      0:{name:list item 1,activated:true},             *      1:{name:list item 2,activated:true},             *      2:{name:list item 3,activated:false}             *  };             * Will append the items to the bottom of the list             */             add: function(list) {                //Pick add function depending on listType                switch(this.options.listType) {                    case normal:this._addNormal(list);                        break;                    case act-deact:this._addActDeact(list);                        break;                    case remove:this._addRemove(list);                        break;                }            },            _addNormal: function(list) {                var options = this.options;                //Get the list elemenent                var ulElem = $(.list-widget-list-container .list-widget-list);                //For each list item                $.each(list, function(key,val){                    //Append the item to the list                    ulElem.append($(<li />)                        .attr(id,options.idStyle + key)                            .append($(<a />)                            .text(val.name)                        )                    );                });            },            _addActDeact: function(list) {                var options = this.options;                //Get the list elemenent                var ulElem = $(.list-widget-list-container .list-widget-list);                //For each list item                $.each(list, function(key,val){                    //creat li element                    var li = $(<li />)                        .attr(id,options.idStyle + key)                            .append($(<img />)                                .addClass(list-img)                            )                            .append($(<a />)                                .text(val.name)                                .attr(href,)                                .addClass(actdeact)                        );                    //add activated/deactivated class                    //depending on item status                     if(val.activated === true) {                        li.find(img).addClass(activated);                        li.find(img).attr(src,tick.png);                    } else {                        li.find(img).addClass(deactivated);                        li.find(img).attr(src,cross.png);                    }                    //Append the list item to the list                    ulElem.append(li);                });            },            _addRemove: function(list) {                var options = this.options;                //Get the list elemenent                var ulElem = $(.list-widget-list-container .list-widget-list);                //For each list item                $.each(list, function(key,val){                    //Append the item to the list                    ulElem.append($(<li />)                        .append($(<img />)                                .addClass(list-img)                                .attr(src,trash_can.png)                            )                        .attr(id,options.idStyle + key)                            .append($(<a />)                                .text(val.name)                                .addClass(remove)                        )                    );                });            },            //Function to empty the list            empty: function() {                $(.list-widget-list-container .list-widget-list).empty();            }        });
jQuery list widget
javascript;jquery