metro4
Version:
The front-end framework for Build responsive, mobile-first projects on the web with the first front-end component library in Metro Style
336 lines (258 loc) • 9.48 kB
JavaScript
var Treeview = {
init: function( options, elem ) {
this.options = $.extend( {}, this.options, options );
this.elem = elem;
this.element = $(elem);
this._setOptionsFromDOM();
this._create();
return this;
},
options: {
effect: "slide",
duration: 100,
onNodeClick: Metro.noop,
onNodeDblClick: Metro.noop,
onNodeDelete: Metro.noop,
onNodeInsert: Metro.noop,
onNodeClean: Metro.noop,
onCheckClick: Metro.noop,
onRadioClick: Metro.noop,
onExpandNode: Metro.noop,
onCollapseNode: Metro.noop,
onTreeviewCreate: Metro.noop
},
_setOptionsFromDOM: function(){
var that = this, element = this.element, o = this.options;
$.each(element.data(), function(key, value){
if (key in o) {
try {
o[key] = JSON.parse(value);
} catch (e) {
o[key] = value;
}
}
});
},
_create: function(){
var that = this, element = this.element, o = this.options;
this._createTree();
this._createEvents();
$.each(element.find("input"), function(){
if (!$(this).is(":checked")) return;
that._recheck(this);
});
Utils.exec(o.onTreeviewCreate, [element], element[0]);
},
_createIcon: function(data){
var icon, src;
src = Utils.isTag(data) ? $(data) : $("<img>").attr("src", data);
icon = $("<span>").addClass("icon");
icon.html(src);
return icon;
},
_createCaption: function(data){
return $("<span>").addClass("caption").html(data);
},
_createToggle: function(){
return $("<span>").addClass("node-toggle");
},
_createNode: function(data){
var node;
node = $("<li>");
if (data.caption !== undefined) {
node.prepend(this._createCaption(data.caption));
}
if (data.icon !== undefined) {
node.prepend(this._createIcon(data.icon));
}
if (data.html !== undefined) {
node.append(data.html);
}
return node;
},
_createTree: function(){
var that = this, element = this.element, o = this.options;
var nodes = element.find("li");
element.addClass("treeview");
$.each(nodes, function(){
var node = $(this);
if (node.data("caption") !== undefined) {
node.prepend(that._createCaption(node.data("caption")));
}
if (node.data("icon") !== undefined) {
node.prepend(that._createIcon(node.data("icon")));
}
if (node.children("ul").length > 0) {
node.append(that._createToggle());
if (node.data("collapsed") !== true) {
node.addClass("expanded");
} else {
node.children("ul").hide();
}
}
});
},
_createEvents: function(){
var that = this, element = this.element, o = this.options;
element.on(Metro.events.click, ".node-toggle", function(e){
var toggle = $(this);
var node = toggle.parent();
that.toggleNode(node);
e.preventDefault();
});
element.on(Metro.events.click, "li > .caption", function(e){
var node = $(this).parent();
that.current(node);
Utils.exec(o.onNodeClick, [node, element], node[0]);
e.preventDefault();
});
element.on(Metro.events.dblclick, "li > .caption", function(e){
var node = $(this).closest("li");
var toggle = node.children(".node-toggle");
var subtree = node.children("ul");
if (toggle.length > 0 || subtree.length > 0) {
that.toggleNode(node);
}
Utils.exec(o.onNodeDblClick, [node, element], node[0]);
e.preventDefault();
});
element.on(Metro.events.click, "input[type=radio]", function(e){
var check = $(this);
var checked = check.is(":checked");
var node = check.closest("li");
that.current(node);
Utils.exec(o.onRadioClick, [checked, check, node, element], this);
});
element.on(Metro.events.click, "input[type=checkbox]", function(e){
var check = $(this);
var checked = check.is(":checked");
var node = check.closest("li");
that._recheck(check);
Utils.exec(o.onCheckClick, [checked, check, node, element], this);
});
},
_recheck: function(check){
var element = this.element;
var checked, node, checks;
if (!Utils.isJQueryObject(check)) {
check = $(check);
}
checked = check.is(":checked");
node = check.closest("li");
this.current(node);
// down
checks = check.closest("li").find("ul input[type=checkbox]");
checks.attr("data-indeterminate", false);
checks.prop("checked", checked);
checks = [];
$.each(element.find(":checkbox"), function(){
checks.push(this);
});
$.each(checks.reverse(), function(){
var ch = $(this);
var children = ch.closest("li").children("ul").find(":checkbox").length;
var children_checked = ch.closest("li").children("ul").find(":checkbox:checked").length;
if (children > 0 && children_checked === 0) {
ch.attr("data-indeterminate", false);
ch.prop("checked", false);
}
if (children_checked === 0) {
ch.attr("data-indeterminate", false);
} else {
if (children_checked > 0 && children > children_checked) {
ch.attr("data-indeterminate", true);
} else if (children === children_checked) {
ch.attr("data-indeterminate", false);
ch.prop("checked", true);
}
}
});
},
current: function(node){
var element = this.element, o = this.options;
if (node === undefined) {
return element.find("li.current")
}
element.find("li").removeClass("current");
node.addClass("current");
},
toggleNode: function(node){
var element = this.element, o = this.options;
var func;
var toBeExpanded = !node.data("collapsed");//!node.hasClass("expanded");
console.log(toBeExpanded);
node.toggleClass("expanded");
node.data("collapsed", toBeExpanded);
if (o.effect === "slide") {
func = toBeExpanded === true ? "slideUp" : "slideDown";
} else {
func = toBeExpanded === true ? "fadeOut" : "fadeIn";
}
if (toBeExpanded) {
Utils.exec(o.onExpandNode, [node, element]);
} else {
Utils.exec(o.onCollapseNode, [node, element]);
}
node.children("ul")[func](o.duration);
},
addTo: function(node, data){
var that = this, element = this.element, o = this.options;
var target;
var new_node;
var toggle;
if (node === null) {
target = element;
} else {
target = node.children("ul");
if (target.length === 0) {
target = $("<ul>").appendTo(node);
toggle = this._createToggle();
toggle.appendTo(node);
node.addClass("expanded");
}
}
new_node = this._createNode(data);
new_node.appendTo(target);
Utils.exec(o.onNodeInsert, [new_node, element], new_node[0]);
return new_node;
},
insertBefore: function(node, data){
var element = this.element, o = this.options;
var new_node = this._createNode(data);
new_node.insertBefore(node);
Utils.exec(o.onNodeInsert, [new_node, element], new_node[0]);
return new_node;
},
insertAfter: function(node, data){
var element = this.element, o = this.options;
var new_node = this._createNode(data);
new_node.insertAfter(node);
Utils.exec(o.onNodeInsert, [new_node, element], new_node[0]);
return new_node;
},
del: function(node){
var element = this.element, o = this.options;
var parent_list = node.closest("ul");
var parent_node = parent_list.closest("li");
node.remove();
if (parent_list.children().length === 0 && !parent_list.is(element)) {
parent_list.remove();
parent_node.removeClass("expanded");
parent_node.children(".node-toggle").remove();
}
Utils.exec(o.onNodeDelete, [element], element[0]);
},
clean: function(node){
var element = this.element, o = this.options;
node.children("ul").remove();
node.removeClass("expanded");
node.children(".node-toggle").remove();
Utils.exec(o.onNodeClean, [node, element], node[0]);
},
changeAttribute: function(attributeName){
switch (attributeName) {
default: ;
}
}
};
Metro.plugin('treeview', Treeview);