TFS_ANTIGUO/SInCathay/ULA.Cathay.Credito/Scripts/jquery.bonsai.js

271 lines
No EOL
7.5 KiB
JavaScript

(function($){
$.fn.bonsai = function( options ) {
return this.each(function() {
var bonsai = new Bonsai(this, options);
$(this).data('bonsai', bonsai);
});
};
$.bonsai = {};
$.bonsai.defaults = {
expandAll: false, // boolean expands all items
expand: null, // function to expand an item
collapse: null, // function to collapse an item
checkboxes: false, // requires jquery.qubit
// createCheckboxes: creates checkboxes for each list item.
//
// The name and value for the checkboxes can be declared in the
// markup using `data-name` and `data-value`.
//
// The name is inherited from parent items if not specified.
//
// Checked state can be indicated using `data-checked`.
createCheckboxes: false,
// handleDuplicateCheckboxes: adds onChange bindings to update
// any other checkboxes that have the same value.
handleDuplicateCheckboxes: false,
selectAllExclude: null
};
var Bonsai = function( el, options ) {
var self = this,
options = $.extend({}, $.bonsai.defaults, options),
checkboxes, isRootNode;
this.el = el = $(el);
// store the scope in the options for child nodes
if( !options.scope ) {
options.scope = el;
isRootNode = true;
}
this.options = options;
el.addClass('bonsai');
if( options.checkboxes ) {
checkboxes = true;
// handle checkboxes once at the root of the tree, not on each element
options.checkboxes = false;
}
// look for a nested list (if any)
el.children().each(function() {
var item = $(this),
// insert a thumb
thumb = $('<div class="thumb" />');
if( options.createCheckboxes ) {
// insert a checkbox after the thumb
self.insertCheckbox(item);
}
item.prepend(thumb);
// if there is a child list
$(this).children().filter('ol, ul').last().each(function() {
// that is not empty
if( $('li', this).length == 0 ) {
return;
}
// then this el has children
item.addClass('has-children')
// attach the sub-list to the item
.data('subList', this);
thumb.on('click', function() {
self.toggle(item);
});
// collapse the nested list
if( options.expandAll || item.hasClass('expanded') ) {
self.expand(item);
}
else {
self.collapse(item);
}
// handle any deeper nested lists
$(this).bonsai(options)
});
});
// if this is root node of the tree
if( isRootNode ) {
if( checkboxes )
el.qubit(options);
if( this.options.addExpandAll )
this.addExpandAll();
if( this.options.addSelectAll )
this.addSelectAll();
}
this.expand = options.expand || this.expand;
this.collapse = options.collapse || this.collapse;
this.el.data('bonsai', this);
this.initialised = true;
};
Bonsai.prototype = {
initialised: false,
toggle: function( listItem ) {
if( !$(listItem).hasClass('expanded') ) {
this.expand(listItem);
}
else {
this.collapse(listItem);
}
},
expand: function( listItem ) {
this.setExpanded(listItem, true);
},
collapse: function( listItem ) {
this.setExpanded(listItem, false);
},
setExpanded: function( listItem, expanded ) {
listItem = $(listItem);
if( listItem.length > 1 ) {
var self = this;
listItem.each(function() {
self.setExpanded(this, expanded);
});
return;
}
if( expanded ) {
if( !listItem.data('subList') )
return;
listItem = $(listItem).addClass('expanded')
.removeClass('collapsed');
$(listItem.data('subList')).css('height', 'auto');
}
else {
listItem = $(listItem).addClass('collapsed')
.removeClass('expanded');
$(listItem.data('subList')).height(0);
}
},
expandAll: function() {
this.expand($('li', this.el));
},
collapseAll: function() {
this.collapse($('li', this.el));
},
insertCheckbox: function( listItem ) {
var id = this.generateId(listItem),
checkbox = $('<input type="checkbox" name="'
+ this.getCheckboxName(listItem)
+ '" id="' + id + '" /> '
),
children = listItem.children(),
// get the first text node for the label
text = listItem.contents().filter(function() {
return this.nodeType == 3;
}).first(),
self = this;
checkbox.val(listItem.data('value'));
checkbox.prop('checked', listItem.data('checked'))
children.remove();
listItem.append(checkbox)
.append($('<label for="' + id + '">')
.append(text ? text : children.first())
)
.append(text ? children : children.slice(1));
if( this.options.handleDuplicateCheckboxes ) {
this.handleDuplicates(checkbox);
}
},
handleDuplicates: function( checkbox ) {
var self = this,
checkbox = $(checkbox);
checkbox.bind('change', function(e) {
var isChecked = checkbox.prop('checked');
if( this.value ) {
var id = this.id;
e.duplicateIds = e.duplicateIds || [];
e.duplicateIds.push(id);
// select all duplicate checkboxes within the same scope
self.options.scope
.find('input[type=checkbox]')
.filter('[value="' + $(checkbox).attr('value') + '"][name="' + $(checkbox).attr('name') + '"]'
+ (isChecked ? ':not(:checked)' : ':checked'))
.filter(function() {
return e.duplicateIds.indexOf(this.id) == -1;
})
.each(function() {
// copy checked and indeterminate to the duplicate
$(this).prop({
checked: isChecked,
indeterminate: $(this).prop('indeterminate')
})
.trigger({
type: 'change',
duplicateIds: e.duplicateIds,
doneIds: e.doneIds
});
});
}
return true;
});
},
idPrefix: 'checkbox-',
generateId: function( listItem ) {
do {
var id = this.idPrefix + Bonsai.uniqueId++;
}
while( $('#' + id).length > 0 );
return id;
},
getCheckboxName: function( listItem ) {
return listItem.data('name')
|| listItem.parents().filter('[data-name]').data('name');
},
addExpandAll: function() {
var self = this,
scope = this.options.scope;
$('<div class="expand-all">')
.append($('<a class="all">Expand all</a>')
.css('cursor', 'pointer')
.bind('click', function() {
self.expandAll();
})
)
.append('<i class="separator"></i>')
.append($('<a class="none">Collapse all</a>')
.css('cursor', 'pointer')
.bind('click', function() {
self.collapseAll();
})
)
.insertBefore(this.el);
},
addSelectAll: function() {
var scope = this.options.scope,
self = this;
function getCheckboxes() {
// return all checkboxes that are not in hidden list items
return scope.find('li')
.filter(self.options.selectAllExclude || function() {
return $(this).css('display') != 'none';
})
.find('> input[type=checkbox]');
}
$('<div class="check-all">')
.append($('<a class="all">Select all</a>')
.css('cursor', 'pointer')
.bind('click', function() {
getCheckboxes().prop({
checked: true,
indeterminate: false
});
})
)
.append('<i class="separator"></i>')
.append($('<a class="none">Select none</a>')
.css('cursor', 'pointer')
.bind('click', function() {
getCheckboxes().prop({
checked: false,
indeterminate: false
});
})
)
.insertAfter(this.el);
},
setCheckedValues: function( values ) {
var all = this.options.scope.find('input[type=checkbox]');
$.each(values, function(key, value) {
all.filter('[value="' + value + '"]')
.prop('checked', true)
.trigger('change');
});
}
};
$.extend(Bonsai, {
uniqueId: 0
});
}(jQuery));