Edit: Hoping to bump this a little as I never got any feedback.
Edit: Hoping to bump this a little as I never got any feedback.
Edit: Hoping to bump this a little as I never got any feedback.
Edit: Hoping to bump this a little as I never got any feedback.
Jquery jQuery list widget code review
this is my first post here, so Hello :)
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 javascriptJavaScript for just over a month now, so I don't think the code will be particularly great, but I've tried my hardest.
I would just like some feedback on my coding, how to improve/ dodo 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 attatchedattached a jsFiddle so you can mess with it. : http://jsfiddle.net/jCVzp/2/ I've
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.
Any time and help is greatly appreciated, thanks!.
(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 code review
this is my first post here, so Hello :)
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 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 attatched 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.
Any time and help is greatly appreciated, thanks!
(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
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 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.
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();
}
});