I'm getting started with my first official jQuery plugin, and I'm just turning now looking for input. I want to know what I'm doing wrong or right so far and if everything is being developed in a manner that won't cause issue down the road. With no further adieu:$.fn.heftyBox = function(args) {    if ($(this).length) {    //Set up defaults    var a    =  $.extend({        type   :  checkbox,        width  :  auto,        height :  ($(this).innerHeight() > 150) ? $(this).innerHeight() : 150    }, args);    //Gather original attributes, convert DOM, then reassgign attributes    var attributes = $(this)[0].attributes;    var optionsHTML = $(this).html();    $(this).after('<ul id=tmpul>' + optionsHTML + '</ul>');    $(this).remove();    var ul = $('#tmpul')[0];    for (var i = 0; i < attributes.length; i++) {        $(ul).attr(attributes[i].name, attributes[i].value);    }    //Convert options to checkbox or radios    var options = $(ul).children('option');    var name = $(ul).attr('name');    $(ul).removeAttr('name');    var f = 0;    $.each(options, function(key, option) {        var itemAttributes = $(this)[0].attributes;        var value = $(this).attr('value');        var label = $(this).text();        var selected = $(this).attr('selected') ? checked : ''        selected += $(this).attr('disabled') ?  disabled : ''        var newLi;        $(this).replaceWith(newLi = $('<li ' + selected + '><input type=' + a.type + ' id=option_' + name + '_' + f + ' name=' + name + ' value=' + value + ' ' + selected + '/><label for=option_' + name + '_' + f + '>' + label + '</label></li>') )        for (var i = 0; i < itemAttributes.length; i++) {            $(newLi).children('input').attr(itemAttributes[i].name, itemAttributes[i].value);        }        f++;    })    //Add Filter Box    $(ul).before('<input id=' + name + '_filter class=list_filter />');    var list = $(ul).children('li');    var filter = $('#' + name + '_filter');    filterBox($(filter), list);    //Contain it all    $(filter).before('<div class=heftyBox id=' + name + '_container></div>');    var container = $('#' + name + '_container');    $(filter).appendTo($(container));    $(ul).appendTo($(container));    //Select all box for checkboxes    if (a.type == checkbox) {        $(filter).after($('<a href=#>Select All</a>').bind('click', function() {            var checkboxes = $(this).next('ul').find('input:not([disabled])');            if ($(checkboxes).length > $(checkboxes + ':checked').length) {                $(checkboxes).attr('checked', 'checked').closest('li').attr('checked', 'checked');            } else {                $(checkboxes).removeAttr('checked', 'checked').closest('li').removeAttr('checked');            }            ($(this).text() == Select All) ? $(this).text(Select None) : $(this).text(Select All)            $(this).next('ul').trigger('change')            return false;        }))    }    //Write the Data to the DOM    $(ul).data({        heftyBox: a    })    //Apply DOM data    updateheftyBox($(ul));    //Handle Value Change    $(this).bind('change', function() {updateheftyBox($(this));})    }    //scroll to first selected DOM    if ($(ul).find('li[checked]:first').length) {        var itemTop = $(ul).find('li[checked]:first').offset().top || $(ul).offset().top;        var ulTop = $(ul).offset().top;        $(ul).scrollTop(itemTop - ulTop);    }}updateheftyBox = function(target) {    var a = $(target).data().heftyBox;    var container = $(target).parent('.heftyBox');    var filter = $(target).siblings('.list_filter');    var ul = $(target);    //Gather created data    a.value = [];    $(ul).find('input:checked').each(function() {        a.value.push($(this).val())    })    $(container).css({        width: a.width,        height: a.height,        min-width: $(filter).outerWidth()    });    $(ul).css({        height: a.height - $(filter).outerHeight(),        margin-top: $(filter).outerHeight()    })    $(ul).val(a.value);}filterBox = function(target, blocks) {    $(target).unbind('keyup change');    $(target).bind('keyup change', function() {        var inText = $(this).val().trim(); //remove trailing whitespace        $.each(blocks, function() {            var title = $(this).children('label').text(); //the title in the block            if (matchAll(title, inText)) {                $(this).show();            } else {                $(this).hide();            }        })    })}matchAll = function(string, args) { //string= string to match, args= search input    var die = 0; //return switch    var checks = args.split(' '); //break input into array    $.each(checks, function() {        var myReg = new RegExp(this, 'i'); //search term to regex        if (!string.match(myReg)) { //if it doesn't match, kill the function            die = 1;        }     })    if (die == 1) {        return false;    } else {        return true;    }}$('.heftyBox li:has(input:checkbox)').live('click', function() {    ($(this).has(':checked').length) ? $(this).attr('checked', 'checked') : $(this).removeAttr('checked')})The concepts of thus plugin: The HeftyBox should be dynamic and not affect any attributes or user input that coould be collected by the original Select boxThe HeftyBox should accept many options to match styling and uniqueness of the application it is being used forThe HeftyBox should be able to be modified and customized with calls to the object after it is initiatedThe HefyBox should be easy to implement, attractive, and functional with defualt settingSource github/kmacey1249/heftyboxImplemented like so: Initial HTML<select name=test id=test multiple=multiple bar=baz>  <option value=1>One</option>  <option value=2>Two</option>  <option value=3 foo=bar>Three</option></select>jQuery Call$('#test').heftyBox(); //{type: checkbox/radio, width: auto, height: 150}Result: <div class=heftyBox id=test_container style=width: auto; height: 178px; min-width: 155px; >  <input id=test_filter class=list_filter />  <a href=#>Select All</a>  <ul id=test multiple=multiple bar=baz style=height: 155px; margin-top: 23px; >    <li>      <input type=checkbox id=option_test_0 name=test value=1>      <label for=option_test_0>One</label>    </li>    <li>      <input type=checkbox id=option_test_1 name=test value=2>      <label for=option_test_1>Two</label>    </li>    <li>      <input type=checkbox id=option_test_2 name=test value=3 foo=bar>      <label for=option_test_2>Three</label>    </li>             </ul></div>Code in action at JSFiddle http://jsfiddle.net/kmacey1249/vXGke/
My first jQuery plugin -- Heftybox
javascript;jquery;plugin
I'm sorry, it's late for me, i'll just tell you what i did. I also put comments in the code to explain why i did some things Here is my refactoring :putting it in a self-executing function. Your three helpers functions doesn't have to be in the global scope.caching almost all elements, you made too much call to $adding a lot of semilicons, you forgot it all the timeprevented the use of jQuery function when they are not needed ( attr(), val() ... )prevent to rely on ids. You were inserting elements then using dom, with id, to retrieve them. I just created elements, then inserted them.edit : i just added another closure function because the first wasn't taking $.fb.heftyBox into it closure.ps: setting attributes that doesn't exist for a tag is not a good solution. Use 'data-' attributes instead of putting non-existant attributes to a tag.    (function($) {    $.fn.heftyBox = (function() {    // usefull functions    // declared in a self-executing function to not charge the global scope    var updateheftyBox = function($target) {        // $target is already a jQuery object, don't need to $() it again        var box         = $target.data().heftyBox,            $container  = $target.parent('.heftyBox'),            $filter     = $target.siblings('.list_filter'); // caching $(filter)        //Gather created data        box.value = [];        $target.find('input:checked').each(function() {            // using this.value instead of .val(), jQuery tools is not needed            box.value.push(this.value);         });        $container.css({            width: box.width,            height: box.height,            min-width: $filter.outerWidth()        });        $target.css({            height: box.height - $filter.outerHeight(),            margin-top: $filter.outerHeight()        })        $target.val(box.value);    };    var filterBox = function($target, blocks) {        // $target is already a jQuery object, don't need to $() it again        // use chaining        $target.unbind('keyup change')            .bind('keyup change', function() {                // input, don't need to use $(this).val(), just this.value                var inText = this.value.trim(); //remove trailing whitespace                $.each(blocks, function() {                    var $that = $(this);                    var title = $that.children('label').text(); //the title in the block                    if (matchAll(title, inText)) {                        $that.show();                    } else {                        $that.hide();                    }                });            });    };    var matchAll = function(string, args) { //string= string to match, args= search input        var checks = args.split(' '); //break input into array        for(var i = checks.length; i--; ) {            if (!string.match(new RegExp(checks[i], 'i'))) { // test if args[i] match the string                // return false if one don't match, don't need to get threw all                return false;             }        }        return true;    };    return function(args) {        var $that = $(this);        if ($that.length) {            //Set up defaults            var opt = $.extend({                        type   :  checkbox,                        width  :  auto,                        height :  ($that.innerHeight() > 150) ? $that.innerHeight() : 150                    }, args                ),                attributes = $that[0].attributes, //Gather original attributes, convert DOM, then reassgign attributes                optionsHTML = $that.html();                $ul = $('<ul id=tmpul>' + optionsHTML + '</ul>'); // build ul, then use it | maybe use a random id instead of hardcoding one            for (var i = attributes.length; i--; ) {                $ul.attr(attributes[i].name, attributes[i].value);            }            //Convert options to checkbox or radios            var options = $ul.children('option'),                name = $ul.attr('name'),                f = 0;            $ul.removeAttr('name'),            $.each(options, function(key, option) {                var $that           = $(this),                    itemAttributes  = $that[0].attributes,                    value           = $that.value,                    label           = $that.text(),                    selected        = itemAttributes.selected ? checked : '';                selected += itemAttributes.disabled ?  disabled : '';                var $newLi = $('<li ' + selected + '></li>'),                     $input = $('<input type=' + opt.type + ' id=option_' + name + '_' + f + ' name=' + name + ' value=' + value + ' ' + selected + '/><label for=option_' + name + '_' + f + '>' + label + '</label>');                $newLi.append($input);                $that.replaceWith($newLi);                for (var i = attributes.length; i--; ) {                    $input[0][attributes[i].name] = attributes[i].value;                }                f++;            });            //Add Filter Box            var $filter = $('<input id=' + name + '_filter class=list_filter />');            var list = $ul.children('li');            filterBox($filter, list);            // add filter and ul to new container            var $container = $('<div class=heftyBox id=' + name + '_container></div>').append($filter, $ul);            // replace existing element by new container            $that.after($container).remove();            //Select all box for checkboxes            if (opt.type == checkbox) {                var $link = $('<a href=#>Select All</a>')                        .bind('click', function() {                            var $that = $(this);                            //@todo get checked                            // directly using $ul not using specific dom manipulation                            var $checkboxes = $ul.find('input:not([disabled])');                            // btw... adding 'checked' attribute to an li is weird... maybe using a data-checked will be better                            if ($checkboxes.length > $checkboxes.filter(':checked').length) {                                $checkboxes.attr('checked', 'checked').closest('li').attr('checked', 'checked');                            } else {                                $checkboxes.removeAttr('checked').closest('li').removeAttr('checked');                            }                            $that.text( ($that.text() == Select All) ? Select None : Select All);                            $ul.trigger('change');                            return false;                        }                    );                // divided creating and appending. just take one more line and is more readable                $filter.after($link);            }            //Write the Data to the DOM            $ul.data({ heftyBox: opt });            //Apply DOM data            updateheftyBox($ul);            //Handle Value Change            $ul.bind('change', function() { updateheftyBox($(this)); }) // change event when clickin                .delegate('input:checkbox', 'click', function() { // delegate click event on checkbox                    var li = $(this).parent();                    (this.checked) ? li.attr('checked', 'checked') : li.removeAttr('checked');                    // trigger change                    $ul.trigger('change');                });            //scroll to first selected DOM            if ($ul.find('li[checked]:first').length) {                var itemTop = $ul.find('li[checked]:first').offset().top || $ul.offset().top,                    ulTop = $ul.offset().top;                $ul.scrollTop(itemTop - ulTop);            }        }    };    })(); })(jQuery);