Files
aportil/themes/sources/dhtmlxTreeView/codebase/dhtmlxtreeview.js

1775 lines
51 KiB
JavaScript

/*
Product Name: dhtmlxSuite
Version: 5.2.0
Edition: Professional
License: content of this file is covered by DHTMLX Commercial or Enterprise license. Usage without proper license is prohibited. To obtain it contact sales@dhtmlx.com
Copyright UAB Dinamenta http://www.dhtmlx.com
*/
function dhtmlXTreeView(conf) {
// console.log("add cache for kids for removeItem");
// console.log("add unload");
var that = this;
if (typeof(conf) == "object" && conf.tagName == null) {
// api-init
} else {
conf = {parent: conf, clear: true};
}
this.base = (typeof(conf.parent)=="string"?document.getElementById(conf.parent):conf.parent);
if (this.base != document.body) {
while (this.base.childNodes.length > 0) this.base.removeChild(this.base.lastChild);
}
this.conf = {
skin: (conf.skin||window.dhx4.skin||(typeof(dhtmlx)!="undefined"?dhtmlx.skin:null)||window.dhx4.skinDetect("dhxtreeview")||"material"),
tree_id: window.dhx4.newId(), // register tree in common pull
ofs: {w: 1, h: 0}, // skyblue only
adjust_base: false,
icons: this.icons[(typeof(conf.iconset) == "string" && this.icons[conf.iconset] != null && this.icons[conf.iconset].r == true ? conf.iconset : "tree_native")],
autoload: {
url: null, // will set automaticaly from 1st loadStruct
mode: "id" // user function allowed here
},
selected: {},
ud: {}, // usersdata
idx: {sign:0,icon:1,text:2}, // icons index
silent: false, // do not callEvent if true
// macos related for selection
is_mac: (navigator.platform.match(/^mac/i) != null && typeof(window.addEventListener) == "function"),
mac_cmd_key: false
};
this.setSkin(this.conf.skin);
this.cont = document.createElement("DIV");
this.cont.className = "dhxtreeview_cont";
this.base.appendChild(this.cont);
this.area = document.createElement("DIV");
this.area.className = "dhxtreeview_area";
this.cont.appendChild(this.area);
this.cont.onclick = function(e) {
e = e||event;
that.callEvent("_onTreeClick", [e, {stop:false}]);
}
this.cont.ondblclick = function(e) {
e = e||event;
var t = (e.target||e.srcElement);
if (t.className.match(/dhxtreeview_item_label/) != null) {
that._openCloseItem(t.parentNode.parentNode._itemId, true);
}
}
this.items = {};
this._addItem = function(id, pId, data, index) {
var level = (pId!=null?this.items[pId].level+1:1);
var t = document.createElement("DIV");
t.className = "dhxtreeview_item";
t.innerHTML = "<div class='dhxtreeview_item_text'></div>";
if (index != null && index < 0) data.index = 0;
if (pId == null) {
var node = this.area;
} else {
var k = this.items[pId].kids;
if (k == false) this._initKidsNode(pId);
this.items[pId].kids_request = false; // do not use dyn load if at least 1 child is present
var node = this.items[pId].item.lastChild.firstChild;
}
if (index != null && node.childNodes[index] != null) {
node.insertBefore(t, node.childNodes[index]);
} else {
node.appendChild(t);
}
node = null;
t._itemId = id;
t._treeId = this.conf.tree_id;
if (window.dhx4.isIE == true) {
t.onselectstart = function(e){
e = e||event;
if (e.preventDefault) e.preventDefault(); else e.returnValue = false;
}
}
this.items[id] = {
id: id,
pId: pId,
treeId: this.conf.tree_id,
text: data.text,
item: t,
level: level,
kids: false, // true/false if any kid
opened: window.dhx4.s2b(data.open),
userdata: window.dhx4._copyObj(data.userdata||{}),
half_opened: false // true/false to change sign only, used for dyn.load
};
this.callEvent("_onItemRendered", [id, data]);
t.firstChild.innerHTML = this._getItemHtml(id);
t = null;
// pre-select
if (window.dhx4.s2b(data.select) == true) this._setSelected(id, true);
this.callEvent("_onItemInited", [id, data]);
}
this.addItem = function(id, text, parentId, index) {
if (this.items[id] != null) return;
if (parentId != null && this.items[parentId] == null) parentId = null;
this._addItem(id, parentId, {text: text}, index);
this._callPublicEvent("onAddItem", [id, text, parentId, index]);
}
this._removeSingleItem = function(id) {
if (window.dhx4.isIE == true) this.items[id].item.onselectstart = null;
this.items[id].item.parentNode.removeChild(this.items[id].item);
for (var a in this.items[id]) {
this.items[id][a] = null;
delete this.items[id][a];
}
delete this.items[id];
// clear selection if any
if (this.conf.selected[id] == true) delete this.conf.selected[id];
}
this._removeItem = function(id) {
var pid = id ? this.items[id].pId : -1;
var count = -1;
// remove nested
for (var a in this.items) {
if (this.items[a].pId == pid) count++;
if (this.items[a].pId == id) this._removeItem(a);
}
if (id != null) this._removeSingleItem(id);
if (pid && !count)
this._clearKidsNode(pid);
}
this.deleteItem = function(id) {
if (this.items[id] == null) return;
if (!this._callPublicEvent("onBeforeDeleteItem", [id])) return;
this._removeItem(id);
this._callPublicEvent("onDeleteItem", [id]);
}
this.deleteChildItems = function(id) {
id = id || 0;
for (var a in this.items) {
if (this.items[a].pId == id)
this._removeItem(a);
}
this._clearKidsNode(id);
}
this.clearAll = function() {
this._removeItem(null);
if (this.conf.unloading != true) this._fixAreaWidth();
}
this._initKidsNode = function(id) {
var p;
if (this.items[id].item.lastChild.className.match(/dhxtreeview_kids_cont/) == null) {
p = document.createElement("DIV");
p.className = "dhxtreeview_kids_cont";
p.innerHTML = "<div style='position:relative;'></div>";
p.style.opacity = "1";
if (this.items[id].opened != true) {
if (this.conf.transProp != false) {
p.style.height = "0px";
p.style.opacity = "0";
p.firstChild.style.display = "none";
} else {
p.style.display = "none";
}
}
this.items[id].item.appendChild(p);
}
this.items[id].kids = true;
this._iconUpdate(id);
this._signUpdate(id);
p = null;
}
this._clearKidsNode = function(id) {
if (this.items[id].item.lastChild.className.match(/dhxtreeview_kids_cont/) != null) {
this.items[id].item.removeChild(this.items[id].item.lastChild);
}
this.items[id].kids = false;
this._iconUpdate(id);
this._signUpdate(id);
}
// open/colse
this.openItem = function(id, anim) {
if (this.items[id].opened != true) {
if (typeof(anim) == "undefined") anim = true;
this._openCloseItem(id, anim);
}
}
this.closeItem = function(id, anim) {
if (this.items[id].opened == true) {
if (typeof(anim) == "undefined") anim = true;
this._openCloseItem(id, anim);
}
}
this._openCloseItem = function(id, anim) {
if (this.callEvent("_onBeforeOpen", [id]) !== true) return;
if (!(this.items[id].kids == true || this.items[id].kids_request == true)) return false;
if (this.items[id].half_opened == true) {
this.items[id].half_opened = false;
this._signUpdate(id);
return;
}
if (anim && this.conf.transProp != false) {
if (!this.items[id].transEv) {
this.items[id].item.lastChild.addEventListener(this.conf.transEv, this._doOnTrEnd);
this.items[id].transEv = true;
}
if (this.items[id].opened == true) {
// close
this.items[id].transMode = "close";
this.items[id].item.lastChild.style.overflow = "hidden";
this.items[id].item.lastChild.style.height = this.items[id].item.lastChild.childNodes[0].offsetHeight+"px";
window.setTimeout(function(){
that.items[id].item.lastChild.style[that.conf.transProp] = that.conf.transValueHeight;
that.items[id].item.lastChild.style.height = "0px";
that.items[id].item.lastChild.style.opacity = "0";
that.items[id].opened = false;
that._iconUpdate(id);
that._signUpdate(id);
},50);
} else {
// open
this.items[id].transMode = "open";
this.items[id].item.lastChild.style[this.conf.transProp] = this.conf.transValueHeight;
this.items[id].item.lastChild.childNodes[0].style.display = "";
this.items[id].item.lastChild.style.overflow = "hidden";
this.items[id].item.lastChild.style.height = this.items[id].item.lastChild.childNodes[0].offsetHeight+"px";
this.items[id].item.lastChild.style.opacity = "1";
this.items[id].opened = true;
this._iconUpdate(id);
this._signUpdate(id);
}
} else {
// open/close
this.items[id].opened = !this.items[id].opened;
this.items[id].item.lastChild.style.display = (this.items[id].opened==true ? "" : "none");
// add for dnd
this.items[id].item.lastChild.childNodes[0].style.display = this.items[id].item.lastChild.style.display;
this.items[id].item.lastChild.style.height = (this.items[id].opened==true?"":"0px");
this.items[id].item.lastChild.style.opacity = (this.items[id].opened==true?1:0);
// end for dnd
this._iconUpdate(id);
this._signUpdate(id);
this._fixAreaWidth();
}
}
this._doOnTrEnd = function() {
var id = this.parentNode._itemId;
that.items[id].item.lastChild.style[that.conf.transProp] = "";
if (that.items[id].transMode == "close") {
that.items[id].item.lastChild.childNodes[0].style.display = "none";
//that._iconUpdate(id);
} else {
that.items[id].item.lastChild.style.height = "";
that.items[id].item.lastChild.style.overflow = "";
}
that._fixAreaWidth();
}
// dimension
this.setSizes = function() {
// adjust top-parent, used in window when tree has border
if (this.conf.adjust_base == true) {
this.base.style.width = this.base.parentNode.clientWidth-2+"px";
this.base.style.height = this.base.parentNode.clientHeight-2+"px";
}
//
this.cont.style.left = this.conf.ofs.w+"px";
this.cont.style.top = this.conf.ofs.h+"px";
this.cont.style.width = this.base.clientWidth-this.conf.ofs.w*2+"px";
this.cont.style.height = this.base.clientHeight-this.conf.ofs.h*2+"px";
//
this._fixAreaWidth();
}
this._fixAreaWidth = function(r) {
this.area.style.width = "100%";
if (this.cont.scrollWidth != this.cont.clientWidth) {
this.area.style.width = this.cont.scrollWidth+1+"px";
}
if (window.dhx4.isIE7 == true && r !== false) { // extra loop for ie7 to fix scroll artefacts
window.setTimeout(function(){that._fixAreaWidth(false);},1);
}
}
this.setSizes();
dhx4._eventable(this);
// transition
var k = window.dhx4.transDetect();
this.conf.transProp = k.transProp;
this.conf.transEv = k.transEv;
this.conf.transValueHeight = "height 0.15s";
k = null;
// macos multiselect
if (this.conf.is_mac == true) {
this._macOnKey = function(e) {
if (((window.dhx4.isKHTML || window.dhx4.isChrome || window.dhx4.isOpera) && (e.keyCode == 91 || e.keyCode == 93)) || (window.dhx4.isFF && e.keyCode == 224)) {
that.conf.mac_cmd_key = (e.type == "keydown");
}
}
window.addEventListener("keydown", this._macOnKey, false);
window.addEventListener("keyup", this._macOnKey, false);
}
// extra modules to init if any
for (var a in this.modules) {
if (this.modules[a].init != null) this[this.modules[a].init](conf);
}
this.unload = function() {
this.conf.unloading = true;
this.cont.onclick = null;
this.cont.ondblclick = null;
this.clearAll();
if (this.conf.is_mac == true) {
window.removeEventListener("keydown", this._macOnKey, false);
window.removeEventListener("keyup", this._macOnKey, false);
}
// extra modules to unload if any
for (var a in this.modules) {
if (this.modules[a].unload != null) this[this.modules[a].unload]();
}
this.area.parentNode.removeChild(this.area);
this.area = null;
this.cont.parentNode.removeChild(this.cont);
this.cont = null;
this.base.className = String(this.base.className).replace(new RegExp("\s{0,}dhxtreeview_"+(this.conf.skin||"")), "");
window.dhx4._eventable(this, "clear");
for (var a in this) this[a] = null;
that = null;
}
// autoload/etc
if (conf.items != null || conf.json != null || conf.xml != null) {
this.loadStruct(conf.items||conf.json||conf.xml, conf.onload);
}
return this;
};
dhtmlXTreeView.prototype.modules = {};
// misc
dhtmlXTreeView.prototype.setSkin = function(skin) {
this.base.className = String(this.base.className).replace(new RegExp("\s{0,}dhxtreeview_"+(this.conf.skin||"")), "") + " dhxtreeview_"+skin;
this.conf.skin = skin;
this.conf.icon_width = dhx4.readFromCss("dhxtreeview_"+this.conf.skin+" dhxtreeview_icon_width");
this.conf.ofs = (this.conf.skin == "dhx_skyblue" ? {w:1, h:0} : {w:0, h:0});
};
dhtmlXTreeView.prototype.setItemText = function(id, text) {
if (this.items[id] != null) {
this.items[id].text = text;
this.items[id].item.firstChild.childNodes[this.conf.idx.text].innerHTML = text;
this._callPublicEvent("onTextChange", [id, text]);
}
};
dhtmlXTreeView.prototype.getItemText = function(id) {
return this.items[id].text;
};
dhtmlXTreeView.prototype.showItem = function(id) {
var top = 0;
var sub = false;
while (id){
var node = this.items[id];
if (node){
top += node.item.offsetTop + (sub?node.item.firstChild.offsetHeight:0);
id = node.pId;
sub = true;
} else
break;
}
this.cont.scrollTop = top;
};
//
dhtmlXTreeView.prototype.getParentId = function(id) {
return this.items[id].pId;
};
dhtmlXTreeView.prototype.getSubItems = function(parentId) {
var rt = this.items[parentId];
rt = rt ? rt.item.lastChild.firstChild : this.area;
var t = [];
for (var i = 0; i < rt.childNodes.length; i++)
t[i] = rt.childNodes[i]._itemId;
return t;
};
// render item html
dhtmlXTreeView.prototype._refreshItemHtml = function(id, updSign, updIcon) {
this.items[id].item.firstChild.innerHTML = this._getItemHtml(id);
if (updSign == true) this._signUpdate(id);
if (updIcon == true) this._iconUpdate(id);
};
dhtmlXTreeView.prototype._getItemHtml = function(id) {
var html = [];
var nodeIndex = 0;
for (var a in this.conf.idx) {
var data = this["_itemHtml_"+a](id, nodeIndex);
if (data.nodeText !== false) {
html.push(data.nodeText);
nodeIndex += data.nodeIndex;
}
}
return html.join("");
};
dhtmlXTreeView.prototype._getIconOfs = function(id, index) {
return ((this.items[id].level-1+index)*this.conf.icon_width);
};
dhtmlXTreeView.prototype._itemHtml_text = function(id, nodeIndex) {
return {
nodeIndex: 1,
nodeText: "<div class='dhxtreeview_item_label' style='left:"+this._getIconOfs(id, nodeIndex)+"px;'>"+this.items[id].text+"</div>"
};
};
// userdata
dhtmlXTreeView.prototype.setUserData = function(id, name, value) {
var item = this.items[id];
if (item) item.userdata[name] = value;
};
dhtmlXTreeView.prototype.getUserData = function(id, name) {
var item = this.items[id];
if (item && !name) return item.userdata;
return item ? (item.userdata[name]||null) : null;
};
// events extension
dhtmlXTreeView.prototype.silent = function(f) {
this.conf.silent = true;
if (typeof(f) == "function") f.apply(window, [this]);
this.conf.silent = false;
};
dhtmlXTreeView.prototype._callPublicEvent = function() {
return (this.conf.silent == false ? this.callEvent.apply(this, arguments) : true);
};
dhtmlXTreeView.prototype.refreshItem = function(id){
id = id || 0;
this.deleteChildItems(id);
this._dynLoadRequest(id);
}
dhtmlXTreeView.prototype.getLevel = function(id){
var top = this.items[id];
var level = 0;
while (top){
level++;
top = this.items[top.pId];
}
return level;
}
if (typeof(window.dhtmlXCellObject) == "function") {
dhtmlXCellObject.prototype.attachTreeView = function(conf) {
this.callEvent("_onBeforeContentAttach", ["treeview"]);
var obj = document.createElement("DIV");
obj.style.position = "relative";
obj.style.overflow = "hidden";
obj.style.width = "100%";
obj.style.height = "100%";
this._attachObject(obj);
var treeConf = {parent: obj, skin: this.conf.skin};
if (conf != null && typeof(conf) == "object") {
for (var a in conf) { if (typeof(treeConf[a]) == "undefined") treeConf[a] = conf[a]; }
}
this.dataType = "treeview";
this.dataObj = new dhtmlXTreeView(treeConf);
// draw border if attached to window
if (typeof(window.dhtmlXWindowsCell) == "function" && this instanceof window.dhtmlXWindowsCell) {
obj.className += " dhxtreeview_with_border";
this.dataObj.conf.adjust_base = true;
this.dataObj.setSizes();
}
treeConf.parent = null;
treeConf = obj = conf = null;
this.callEvent("_onContentAttach", []);
return this.dataObj;
};
}
// register checkboxes module
dhtmlXTreeView.prototype.modules.chbx = {
init: "_chbxInit"
};
// public
dhtmlXTreeView.prototype.enableCheckboxes = function(mode) {
mode = (mode==true);
if (this.conf.enable_chbx != mode) {
this.conf.enable_chbx = mode;
this._chbxUpdIndex();
for (var a in this.items) this._refreshItemHtml(a, true, true);
}
};
dhtmlXTreeView.prototype.getAllChecked = function(parentId) {
return this._chbxGetCheckedBranch(parentId, true);
};
dhtmlXTreeView.prototype.getAllUnchecked = function(parentId) {
return this._chbxGetCheckedBranch(parentId, false);
};
dhtmlXTreeView.prototype.checkItem = function(id) {
this._chbxSetChecked(id, true, true);
};
dhtmlXTreeView.prototype.uncheckItem = function(id) {
this._chbxSetChecked(id, false, true);
};
dhtmlXTreeView.prototype.isItemChecked = function(id) {
if (this.items[id] == null) return null;
return (this.items[id].checked == true);
};
dhtmlXTreeView.prototype.enableCheckbox = function(id) {
this._chbxSetEnabled(id, true);
};
dhtmlXTreeView.prototype.disableCheckbox = function(id) {
this._chbxSetEnabled(id, false);
};
dhtmlXTreeView.prototype.isCheckboxEnabled = function(id) {
return (this.items[id].chbx_enabled == true);
};
dhtmlXTreeView.prototype.showCheckbox = function(id) {
this._chbxSetVisible(id, true);
};
dhtmlXTreeView.prototype.hideCheckbox = function(id) {
this._chbxSetVisible(id, false);
};
dhtmlXTreeView.prototype.isCheckboxVisible = function(id) {
return (this.items[id].chbx_visible == true);
};
// private
dhtmlXTreeView.prototype._chbxInit = function(conf) { // init
this.enableCheckboxes(conf.checkboxes);
this.attachEvent("_onItemRendered", function(id, data){
this.items[id].checked = window.dhx4.s2b(data.checked);
var conf = (data.checkbox||"enabled,visible");
this.items[id].chbx_enabled = (conf.match(/disabled/)==null);
this.items[id].chbx_visible = (conf.match(/hidden/)==null);
});
this.attachEvent("_onTreeClick", function(e, flow){
if (this.conf.enable_chbx != true) return;
var t = (e.target||e.srcElement);
if (t.tagName.toLowerCase() == "i") t = t.parentNode; // check if icon
if ((t.parentNode.className||"").match(/dhxtreeview_item_text/) != null && t == t.parentNode.childNodes[this.conf.idx.chbx]) { // check if checkbox
var id = t.parentNode.parentNode._itemId;
if (this.items[id].chbx_enabled == true) this._chbxSetChecked(id, !this.items[id].checked, true);
flow.stop = true;
}
});
conf = null;
};
dhtmlXTreeView.prototype._itemHtml_chbx = function(id, nodeIndex) {
var r = {nodeIndex: 0, nodeText: false};
if (this.conf.enable_chbx == true) {
if (this.items[id].chbx_visible == true) r.nodeIndex = 1;
r.nodeText = "<div class='dhxtreeview_item_icon' style='left:"+this._getIconOfs(id, nodeIndex)+"px;"+(r.nodeIndex>0?"":"display:none;")+"'>"+this._chbxGenIcon(id)+"</div>";
}
return r;
};
dhtmlXTreeView.prototype._chbxSetChecked = function(id, state) {
if (this.conf.enable_chbx != true) return;
state = (state==true);
if (this.items[id].checked != state) {
if (this._callPublicEvent("onBeforeCheck", [id, (this.items[id].checked==true)]) !== true) return;
this.items[id].checked = state;
this.items[id].item.childNodes[0].childNodes[this.conf.idx.chbx].innerHTML = this._chbxGenIcon(id);
this._callPublicEvent("onCheck", [id, state]);
}
};
dhtmlXTreeView.prototype._chbxSetEnabled = function(id, mode) {
if (this.items[id].chbx_enabled != mode) {
this.items[id].chbx_enabled = mode;
this.items[id].item.firstChild.childNodes[this.conf.idx.chbx].innerHTML = this._chbxGenIcon(id);
}
};
dhtmlXTreeView.prototype._chbxSetVisible = function(id, mode) {
if (this.items[id].chbx_visible != mode) {
this.items[id].chbx_visible = mode;
this._refreshItemHtml(id, true, true);
}
};
dhtmlXTreeView.prototype._chbxGenIcon = function(id) {
var icon = this.conf.icons["chbx_"+(this.items[id].chbx_enabled?"":"dis_")+(this.items[id].checked?"1":"0")];
return '<i class="'+this.conf.icons.prefix+' '+icon+'"></i>';
};
dhtmlXTreeView.prototype._chbxUpdIndex = function() {
if (this.conf.enable_chbx == true) {
this.conf.idx = {sign: 0, chbx: 1, icon: 2, text: 3};
} else {
this.conf.idx = {sign: 0, icon: 1, text: 2};
}
};
dhtmlXTreeView.prototype._chbxGetCheckedBranch = function(pId, mode) {
var k = [];
for (var a in this.items) {
if (this.items[a].pId == pId) {
if (this.items[a].checked == mode) k.push(a);
if (this.items[a].kids == true) k = k.concat(this._chbxGetCheckedBranch(a, mode));
}
}
return k;
};
// register selection module
dhtmlXTreeView.prototype.modules.sign = {
init: "_signInit"
};
// private
dhtmlXTreeView.prototype._signInit = function() {
this.attachEvent("_onTreeClick", function(e, flow){
if (flow.stop == true) return; // check if cancelled by prev attached function
var t = (e.target||e.srcElement);
if (t.tagName.toLowerCase() == "i") t = t.parentNode; // check if icon
if ((t.parentNode.className||"").match(/dhxtreeview_item_text/) != null && t == t.parentNode.childNodes[this.conf.idx.sign]) {
this._openCloseItem(t.parentNode.parentNode._itemId, true);
flow.stop = true;
}
});
};
dhtmlXTreeView.prototype._signUpdate = function(id) {
var t = this.items[id];
var img = t.item.childNodes[0].childNodes[this.conf.idx.sign];
if (t.kids == true || t.kids_request == true) {
img.innerHTML = '<i class="'+this.conf.icons.prefix+" "+this.conf.icons[(t.opened||t.half_opened?"minus":"plus")]+'"></i>';
} else {
img.innerHTML = "";
}
t = img = null;
}
dhtmlXTreeView.prototype._itemHtml_sign = function(id, nodeIndex) { // item html renderer
return {
nodeIndex: 1,
nodeText: "<div class='dhxtreeview_item_icon' style='left:"+this._getIconOfs(id, nodeIndex)+"px;'></div>"
};
};
// register selection module
dhtmlXTreeView.prototype.modules.selection = {
init: "_selectionInit"
};
// public
dhtmlXTreeView.prototype.selectItem = function(id) {
if (this.conf.msel == true) {
var t = {};
if (!(id instanceof Array)) id = [id];
for (var q=0; q<id.length; q++) t[id[q]] = true;
for (var a in this.conf.selected) {
if (t[a] == true) {
delete t[a]; // already selected
} else {
this._setSelected(a, false); // clear selection if not preserve
}
}
for (var a in t) this._setSelected(a, true); // select the rest
} else if (id != null && this.conf.selected[id] != true && !(id instanceof Array)) {
if (this._clearSelection(id) == false) this._setSelected(id, true);
}
};
dhtmlXTreeView.prototype.unselectItem = function(id) {
if (this.conf.msel == true) {
if (!(id instanceof Array)) id = [id];
for (var q=0; q<id.length; q++) {
if (this.conf.selected[id[q]] == true) this._setSelected(id[q], false);
}
} else if (id != null) {
this._setSelected(id, false);
}
};
dhtmlXTreeView.prototype.getSelectedId = function() {
var ids = [];
for (var a in this.conf.selected) ids.push(a);
return (this.conf.msel?ids:(ids[0]||null));
};
dhtmlXTreeView.prototype.enableMultiselect = function(mode) {
mode = (mode==true);
if (this.conf.msel != mode) {
this._clearSelection();
this.conf.msel = mode;
}
};
// private
dhtmlXTreeView.prototype._selectionInit = function(conf) { // init
this.conf.msel = window.dhx4.s2b(conf.multiselect);
this.attachEvent("_onTreeClick", function(e, flow){
if (flow.stop == true) return; // check if cancelled by prev attached function
var t = (e.target||e.srcElement);
if (t.tagName.toLowerCase() == "i") t = t.parentNode; // check if icon
var selectId = null;
if (t.className.match(/dhxtreeview_item_label/) != null) {
selectId = t.parentNode.parentNode._itemId;
} else if (t.className.match(/^dhxtreeview_item_text/) != null) {
selectId = t.parentNode._itemId;
} else if (t.className.match(/^dhxtreeview_item_icon/) != null) {
selectId = t.parentNode.parentNode._itemId;
}
if (selectId != null) {
if (!this._callPublicEvent("onBeforeSelect", [selectId]))
return;
var now = new Date();
if (this._click_item !== selectId || (now - (this._click_timer||0)) > 300){
this._callPublicEvent("onClick", [selectId]);
this._click_timer = now;
this._click_item = selectId;
} else {
this._callPublicEvent("onDblClick", [selectId]);
this._click_item = null;
}
if (this.conf.msel == true) {
if ((e.ctrlKey == true || this.conf.mac_cmd_key == true) && e.shiftKey == false && e.altKey == false) { // ctrl pressed
this._setSelected(selectId, !this._isSelected(selectId));
} else if (e.ctrlKey == false && e.shiftKey == false && e.altKey == false && this.conf.mac_cmd_key == false) { // nothing pressed
if (this._clearSelection(selectId) == false) this._setSelected(selectId, true);
}
} else {
if (this._clearSelection(selectId) == false) this._setSelected(selectId, true);
}
}
});
};
dhtmlXTreeView.prototype._setSelected = function(id, mode) {
if (mode == true) {
if (this.conf.selected[id] != true) {
this.items[id].item.childNodes[0].className += " dhxtreeview_item_text_selected";
this.conf.selected[id] = true;
this._callPublicEvent("onSelect", [id, true]);
}
} else {
if (this.conf.selected[id] == true) {
this.items[id].item.childNodes[0].className = String(this.items[id].item.childNodes[0].className).replace(/\s*dhxtreeview_item_text_selected/gi, "");
delete this.conf.selected[id];
this._callPublicEvent("onSelect", [id, false]);
}
}
};
dhtmlXTreeView.prototype._clearSelection = function(exceptId) {
var r = false;
for (var a in this.conf.selected) {
if (exceptId != null && a == exceptId) r = true; else this._setSelected(a, false);
}
return r; // true if item stay selected
};
dhtmlXTreeView.prototype._isSelected = function(id) {
return (this.conf.selected[id]==true);
};
// register icons module
dhtmlXTreeView.prototype.modules.icons = {
init: "_iconModuleInit"
};
// public
dhtmlXTreeView.prototype.setItemIcons = function(id, icons) {
if (icons == null && this.items[id].icons != null) {
delete this.items[id].icons; // clear all custom for certain item
} else if (icons != null) {
if (this.items[id].icons == null) this.items[id].icons = {};
for (var a in icons) {
if (icons[a] != null) {
this.items[id].icons[a] = icons[a];
} else if (icons[a] == null && this.items[id].icons[a] != null) {
delete this.items[id].icons[a]; // clear only specified icon
}
}
}
this._iconUpdate(id);
};
dhtmlXTreeView.prototype.setIconColor = function(id, color) {
var icon = this.items[id].item.firstChild.childNodes[this.conf.idx.icon].firstChild;
if (color == null) {
if (this.items[id].icon_color != null) {
delete this.items[id].icon_color;
icon.style.color = "inherit";
}
} else {
if (this.items[id].icon_color != color) {
this.items[id].icon_color = color;
icon.style.color = color;
}
}
icon = null;
};
dhtmlXTreeView.prototype.setIconset = function(name) {
if (this.icons[name] != null && this.icons[name].r == true) {
this.conf.icons = this.icons[name];
}
};
// private
dhtmlXTreeView.prototype._iconModuleInit = function() { // init
this.attachEvent("_onItemRendered", function(id, data){
if (data.icons != null) this.items[id].icons = data.icons;
if (data.icon_color != null) this.items[id].icon_color = data.icon_color;
});
};
dhtmlXTreeView.prototype._iconConf = function(id) { // return array with icons
var icons = this.items[id].icons||{};
for (var a in {folder_opened:1, folder_closed:1, file:1}) {
if (typeof(icons[a]) == "undefined") icons[a] = this.conf.icons[a]; // if item has own icons missing will updated here
}
return icons;
};
dhtmlXTreeView.prototype._iconHtml = function(id, css) { // generate <i> for icon
var attrs = ['class="'+this.conf.icons.prefix+" "+css+'"'];
if (this.items[id].icon_color != null) attrs.push('style="color:'+this.items[id].icon_color+';"');
return "<i "+attrs.join(" ")+"></i>";
};
dhtmlXTreeView.prototype._itemHtml_icon = function(id, nodeIndex) { // item html renderer
return {
nodeIndex: 1,
nodeText: "<div class='dhxtreeview_item_icon' style='left:"+this._getIconOfs(id, nodeIndex)+"px;'>"+this._iconHtml(id, this._iconConf(id).file)+"</div>"
};
};
dhtmlXTreeView.prototype._iconUpdate = function(id) { // update icon inner call
var t = this.items[id];
var icons = this._iconConf(id);
var css = (t.kids == true || t.kids_request == true ? icons[t.opened?"folder_opened":"folder_closed"] : icons.file);
t.item.childNodes[0].childNodes[this.conf.idx.icon].innerHTML = this._iconHtml(id, css);
t = null;
};
// config
dhtmlXTreeView.prototype.icons = {
tree_native: {
r: true, // allow rendering depending on browser
prefix: "dhxtreeview_icon", // common prefix for all icons/arrows/checkboxes/etc
plus: "dhxtreeview_icon_plus",
minus: "dhxtreeview_icon_minus",
file: "dhxtreeview_icon_file",
folder_opened: "dhxtreeview_icon_folder_opened",
folder_closed: "dhxtreeview_icon_folder_closed",
loading: "dhxtreeview_icon_loading",
chbx_0: "dhxtreeview_icon_chbx_0",
chbx_1: "dhxtreeview_icon_chbx_1",
chbx_dis_0: "dhxtreeview_icon_chbx_dis_0",
chbx_dis_1: "dhxtreeview_icon_chbx_dis_1"
},
font_awesome: {
r: (!(window.dhx4.isIE6 == true || window.dhx4.isIE7 == true)),
prefix: "fa",
plus: "fa-caret-right",
minus: "fa-caret-down",
file: "fa-file-o",
folder_opened: "fa-folder-open-o",
folder_closed: "fa-folder-o",
loading: "fa-refresh fa-spin",
chbx_0: "fa-square-o",
chbx_1: "fa-check-square-o",
chbx_dis_0: "fa-square-o dhx-disabled",
chbx_dis_1: "fa-check-square-o dhx-disabled"
}
};
// register loading module
dhtmlXTreeView.prototype.modules.loading = {
init: "_loadingInit",
unload: "_loadingUnload"
};
dhtmlXTreeView.prototype._loadingInit = function(conf) {
window.dhx4._enableDataLoading(this, "_initObj", "_xmlToObj", "tree", {struct:true});
this.conf.root_id = (typeof(conf.root_id)=="undefined" || conf.root_id==null ? "0" : conf.root_id); // top-level item
this._dhxdataload.onBeforeXLS = function(url) { // add tree_id for 1st load if any
if (this.conf.autoload.url == null) this.conf.autoload.url = url;
return {url:url.replace(/\{id\}/gi, this.conf.root_id)};
}
};
dhtmlXTreeView.prototype._loadingUnload = function() {
window.dhx4._enableDataLoading(this, null, null, null, "clear");
};
dhtmlXTreeView.prototype._initObj = function(data, url, pId, fixArea) {
for (var q=0; q<data.length; q++) {
var id = data[q].id;
if (id == null) id = "dhxtreeview_id_"+window.dhx4.newId();
// add item if not exists, if already exists - refresh?
if (this.items[id] == null) this._addItem(id, pId, data[q]);
// nested
if (data[q].items != null) this._initObj(data[q].items, null, id, true);
}
// done
if (fixArea != true) {
this._fixAreaWidth();
}
};
dhtmlXTreeView.prototype._xmlToObj = function(root, nested) {
if (nested != true) root = root.getElementsByTagName("tree")[0];
var data = [];
for (var q=0; q<root.childNodes.length; q++) {
var node = root.childNodes[q];
if ((node.tagName||"").toLowerCase() == "item") {
// main item attrs
var item = {};
for (var w=0; w<node.attributes.length; w++) {
item[node.attributes[w].name] = node.attributes[w].value;
}
if (node.childNodes.length > 0) {
// nested items
var nested = this._xmlToObj(node, true);
if (nested.length > 0) item.items = nested;
// icons and userdata
for (var w=0; w<node.childNodes.length; w++) {
var tag = (node.childNodes[w].tagName||"").toLowerCase();
if ({icons:1, userdata:1}[tag] == 1) {
if (item[tag] == null) item[tag] = {};
for (var e=0; e<node.childNodes[w].attributes.length; e++) {
var name = node.childNodes[w].attributes[e].name;
if (item[tag][name] == null) item[tag][name] = node.childNodes[w].attributes[e].value;
}
}
n2 = null;
}
}
data.push(item);
}
node = null;
}
return data;
};
// register dnd module
dhtmlXTreeView.prototype.modules.dnd = {
init: "_dndInit",
unload: "_dndUnload"
};
dhtmlXTreeView.prototype.enableDragAndDrop = function(mode) {
this.conf.enable_dnd = window.dhx4.s2b(mode);
};
dhtmlXTreeView.prototype._dndInit = function(conf) { // init
var that = this;
this.enableDragAndDrop(conf.dnd);
this.conf.dnd = null;
this._dndOnMouseDown = function(e) {
if (that.conf.enable_dnd != true) return;
e = e||event;
if (typeof(e.button) != "undefined" && e.button >= 2) return false;
var id = null;
var treeId = null;
var t = e.target||e.srcElement;
var ofs_x = window.dhx4.absLeft(t)+(typeof(e.offsetX)=="undefined"?e.layerX:e.offsetX) - e.clientX;
var ofs_y = window.dhx4.absTop(t)+(typeof(e.offsetY)=="undefined"?e.layerY:e.offsetY) - e.clientY;
while (t != null && t != that.cont) {
if ((t.className||"").match(/dhxtreeview_item/) != null && t._itemId != null) {
id = t._itemId;
treeId = t._treeId;
t = null;
} else {
t = t.parentNode;
}
}
t = null;
if (id == null) return; // check if empty click and abort
that.conf.dnd = {
inited: false,
id: id,
treeId: treeId,
selected: (that.conf.selected[id]==true),
tid: null,
drop: {},
x: e.clientX,
y: e.clientY,
ofs_x: ofs_x,
ofs_y: ofs_y,
zi: window.dhx4.newId(),
scroll: false,
scroll_ofs: 5, // offset for single loop
scroll_time: 30, // timeout
scroll_tm: null,
kids: {}, // all kids of dragged to prevent dnd in advance
idx: {}
};
that._dndInitEvents();
}
this._dndOnMouseMove = function(e) {
e = e||event;
if (that.conf.dnd.inited != true) {
if (Math.abs(that.conf.dnd.x - e.clientX) >= 15 || Math.abs(that.conf.dnd.y - e.clientY) >= 15) {
if (that._callPublicEvent("onBeforeDrag", [that.conf.dnd.id]) !== true) return;
that.conf.dnd.inited = true;
that.cont.className += " dhxtreeview_dnd_mode";
that._dndInitDraggedObj();
that._dndCollectKids(that.conf.dnd.id);
that._dndCollectIndexes(that.area);
// rearrange selection
if (that._clearSelection(that.conf.dnd.id) == false) that._setSelected(that.conf.dnd.id, true);
// update item css
that.items[that.conf.dnd.id].item.className += " dhxtreeview_item_dragged";
document.body.className += " dhxtreeview_dnd_mode";
// tree area to check if scroll should be performed
that.conf.dnd.cont = {
x1: window.dhx4.absLeft(that.base),
y1: window.dhx4.absTop(that.base)
};
that.conf.dnd.cont.x2 = that.conf.dnd.cont.x1 + that.base.offsetWidth;
that.conf.dnd.cont.y2 = that.conf.dnd.cont.y1 + that.base.offsetHeight;
} else {
return;
}
}
that.conf.dnd.x = e.clientX;
that.conf.dnd.y = e.clientY;
that._dndAdjustDraggedObj();
// check tree area edges and scroll content if any
var stopScroll = true;
if (that.cont.scrollHeight > that.cont.clientHeight) {
if (that.conf.dnd.x >= that.conf.dnd.cont.x1 && that.conf.dnd.x <= that.conf.dnd.cont.x2) {
if (that.cont.scrollTop > 0 && that.conf.dnd.y >= that.conf.dnd.cont.y1 && that.conf.dnd.y <= that.conf.dnd.cont.y1 + 10) { // top edge
that._dndScroll("up");
stopScroll = false;
} else if (that.cont.scrollTop+that.cont.clientHeight < that.cont.scrollHeight && that.conf.dnd.y <= that.conf.dnd.cont.y2 && that.conf.dnd.y >= that.conf.dnd.cont.y2 - 10) { // bottom edge
that._dndScroll("down");
stopScroll = false;
}
}
}
if (stopScroll == true && that.conf.dnd.scroll == true) {
that._dndScroll("stop");
}
// detect node by target
var t = (e.target||e.srcElement);
// remove blink artefact if any
if (t.parentNode != null && (t.parentNode.className||"").match(/dhxtreeview_kids_cont/) != null) {
t = null;
return;
}
var upd = false;
var tid = null;
var treeId = null;
if (t.className != null) {
if (t.className.match(/dhxtreeview_item_[li]/) != null) { // label/icon
tid = t.parentNode.parentNode._itemId;
treeId = t.parentNode.parentNode._treeId;
} else if (t.className.match(/dhxtreeview_item_[t]/) != null) { // text
tid = t.parentNode._itemId;
treeId = t.parentNode._treeId;
}
}
// check if the same tree
if (tid != null && treeId != that.conf.dnd.treeId) {
return;
}
// check if target is the same or if target is child
if (that.conf.dnd.id == tid || that.conf.dnd.kids[tid] == true) {
tid = null;
}
if (tid != null) {
var h = that.items[tid].item.firstChild.offsetHeight;
var ofs = Math.max(Math.floor(Math.min(e.offsetY, h) * 3 / h), 0);
// depending on item type and offset - allow/block some offsets
if (ofs == 0) { // drop as sibling above target
if (that.items[tid].item.previousSibling == that.items[that.conf.dnd.id].item) { // do not allow if prev sibling is dragged
ofs = null;
}
} else if (ofs == 1) { // drop as child of target
if (that.items[that.conf.dnd.id].pId == tid) { // if already child of selected parent
ofs = null;
} else if (that.items[tid].kids == true && that.items[tid].item.lastChild.firstChild.firstChild == that.items[that.conf.dnd.id].item) { // do not allo if dragged already 1st child
ofs = null;
} else if (that.items[tid].opened == false) { // open node
//that._openCloseItem(tid, true);
}
} else if (ofs == 2) { // drop as sibling below target
if (that.items[tid].opened == true) { // do not allow for opened item
ofs = null;
} else if (that.items[tid].item.nextSibling == that.items[that.conf.dnd.id].item) { // do not allow if next sibling is dragged
ofs = null;
}
}
//
if (ofs != that.conf.dnd.ofs) {
that.conf.dnd.ofs = ofs;
upd = true;
}
}
if (tid != that.conf.dnd.tid) {
// clear old one
if (that.conf.dnd.tid != null) {
that._dndUpdateTargetCss(that.conf.dnd.tid, false);
}
// update new
if (tid != null) {
upd = true;
}
that.conf.dnd.tid = tid;
}
if (upd == true) {
var mode = false;
if (ofs != null) {
var drop = {
id: that.conf.dnd.id,
pId: that.items[tid].pId||null,
index: null,
idxOfs: (that.items[that.conf.dnd.id].pId == that.items[tid].pId && that.conf.dnd.idx[that.conf.dnd.id] < that.conf.dnd.idx[tid] ? -1 : 0)
};
if (ofs == 0 || ofs == 2) {
drop.index = that.conf.dnd.idx[tid]+(ofs==2?1:0)+drop.idxOfs;
} else if (ofs == 1) {
drop.pId = tid;
drop.index = (that.items[tid].item.lastChild.className.match(/dhxtreeview_kids_cont/)==null?0:that.items[tid].item.lastChild.firstChild.childNodes.length);
}
if (that.conf.dnd.drop.id != drop.id || that.conf.dnd.drop.pId != drop.pId || that.conf.dnd.drop.index != drop.index) {
that.conf.dnd.drop = drop;
if (that._callPublicEvent("onDragOver", [that.conf.dnd.drop.id, that.conf.dnd.drop.pId, that.conf.dnd.drop.index]) === true) mode = true;
}
}
if (mode != true) that.conf.dnd.ofs = ofs = null;
that._dndUpdateTargetCss(tid, mode);
}
}
this._dndOnMouseUp = function(e) {
e = e||event;
if (typeof(e.button) != "undefined" && e.button >= 2) return;
that._dndUnloadEvents();
that._dndUnloadDraggedObj();
if (that.conf.dnd.scroll == true) {
that._dndScroll("stop");
}
if (that.cont.className.match(/dhxtreeview_dnd_mode/gi) != null) {
that.cont.className = String(that.cont.className).replace(/\s*dhxtreeview_dnd_mode/gi, "");
}
if (that.conf.dnd.tid != null) {
that._dndUpdateTargetCss(that.conf.dnd.tid, false);
}
if (that.conf.dnd.inited == true) {
that.items[that.conf.dnd.id].item.className = String(that.items[that.conf.dnd.id].item.className).replace(/\s*dhxtreeview_item_dragged/gi, "");
document.body.className = String(document.body.className).replace(/\s*dhxtreeview_dnd_mode/, "");
if (that.conf.dnd.tid != null && that.conf.dnd.ofs != null) {
if (that._callPublicEvent("onBeforeDrop", [that.conf.dnd.drop.id, that.conf.dnd.drop.pId, that.conf.dnd.drop.index]) === true) {
var obj = that.items[that.conf.dnd.id];
var tobj = that.items[that.conf.dnd.tid];
var pobj = (obj.pId != null ? that.items[obj.pId] : null); // prev_parent id
var levelOfs;
// 1) dom
if (that.conf.dnd.ofs == 1) {
var open = false;
if (tobj.kids == false) {
that._initKidsNode(tobj.id);
open = true;
}
tobj.item.lastChild.firstChild.appendChild(obj.item);
//
if (open == true) {
that._openCloseItem(tobj.id, false);
}
obj.pId = tobj.id;
levelOfs = tobj.level+1-obj.level;
} else if (that.conf.dnd.ofs == 0 || that.conf.dnd.ofs == 2) { // sibling before/after
if (that.conf.dnd.ofs == 0) { // before
tobj.item.parentNode.insertBefore(obj.item, tobj.item);
} else if (tobj.item.nextSibling != null) { // after
tobj.item.parentNode.insertBefore(obj.item, tobj.item.nextSibling);
} else { // after
tobj.item.parentNode.appendChild(obj.item);
}
obj.pId = tobj.pId;
levelOfs = tobj.level-obj.level;
}
// update nested if level changed
if (levelOfs != 0) {
that.conf.dnd.kids[obj.id] = true;
for (var a in that.conf.dnd.kids) {
that.items[a].level += levelOfs;
that._refreshItemHtml(a, (that.items[a].kids == true), true);
}
}
// 4) check parent's kids area and remove if empty
if (pobj != null && pobj.kids == true && pobj.item.lastChild.firstChild.childNodes.length == 0) {
that._clearKidsNode(pobj.id)
pobj.opened = false;
}
obj = tobj = pobj = null;
that._fixAreaWidth();
that._callPublicEvent("onDrop", [that.conf.dnd.drop.id, that.conf.dnd.drop.pId, that.conf.dnd.drop.index]);
}
}
}
window.dhx4.zim.clear(that.conf.dnd.zi);
that.conf.dnd = null;
}
this._dndOnContextMenu = function(e) {
if (that.conf.dnd.inited == true) {
e = e||event;
e.cancelBubble = true;
if (e.preventDefault) e.preventDefault();
e.returnValue = false;
return false;
}
}
// events
this._dndInitEvents = function() {
if (typeof(window.addEventListener) == "function") {
window.addEventListener("mousemove", this._dndOnMouseMove, false);
window.addEventListener("mouseup", this._dndOnMouseUp, false);
window.addEventListener("contextmenu", this._dndOnContextMenu, false);
} else {
document.body.attachEvent("onmousemove", this._dndOnMouseMove);
document.body.attachEvent("onmouseup", this._dndOnMouseUp);
document.body.attachEvent("oncontextmenu", this._dndOnContextMenu);
}
}
this._dndUnloadEvents = function() {
if (typeof(window.addEventListener) == "function") {
window.removeEventListener("mousemove", this._dndOnMouseMove, false);
window.removeEventListener("mouseup", this._dndOnMouseUp, false);
window.removeEventListener("contextmenu", this._dndOnContextMenu, false);
} else {
document.body.detachEvent("onmousemove", this._dndOnMouseMove);
document.body.detachEvent("onmouseup", this._dndOnMouseUp);
document.body.detachEvent("oncontextmenu", this._dndOnContextMenu);
}
}
// dragged object
this._dndInitDraggedObj = function() {
this.conf.dnd.dragged = document.createElement("DIV");
this.conf.dnd.dragged.className = "dhxtreeview_dragged_obj_"+this.conf.skin;
this.conf.dnd.dragged.style.zIndex = window.dhx4.zim.reserve(this.conf.dnd.zi);
document.body.appendChild(this.conf.dnd.dragged);
//
this.conf.dnd.dragged.innerHTML = this.getItemText(this.conf.dnd.id);
}
this._dndAdjustDraggedObj = function() {
this.conf.dnd.dragged.style.left = this.conf.dnd.x + this.conf.dnd.ofs_x + 12 + "px";
this.conf.dnd.dragged.style.top = this.conf.dnd.y + this.conf.dnd.ofs_y + 18 + "px";
}
this._dndUnloadDraggedObj = function() {
if (this.conf.dnd.dragged != null) {
document.body.removeChild(this.conf.dnd.dragged);
this.conf.dnd.dragged = null;
}
}
// target node ui
this._dndUpdateTargetCss = function(id, mode) {
var t = this.items[id].item.childNodes[0];
if (this.conf.dnd.ofs == null) {
mode = false;
}
if (mode == true) {
t.className = String(t.className).replace(/(\s*dhxtreeview_drop_\d)?$/i, " dhxtreeview_drop_"+this.conf.dnd.ofs);
//
if (t.nextSibling == null || t.nextSibling.className.match(/dhxtreeview_drop_preview/) == null) {
var k = document.createElement("DIV");
k.className = "dhxtreeview_drop_preview";
k.style.left = t.lastChild.previousSibling.style.left;
if (t.nextSibling == null) {
t.parentNode.appendChild(k);
} else {
t.parentNode.insertBefore(k, t.nextSibling);
}
k = null;
}
t.nextSibling.className = String(t.nextSibling.className).replace(/(\s*dhxtreeview_drop_\d)?$/i, " dhxtreeview_drop_"+this.conf.dnd.ofs);
} else if (t.className.match(/dhxtreeview_drop_\d/) != null) {
t.className = String(t.className).replace(/\s*dhxtreeview_drop_\d/gi, "");
//
if (t.nextSibling != null && t.nextSibling.className.match(/dhxtreeview_drop_preview/) != null) {
t.parentNode.removeChild(t.nextSibling);
}
}
t = null;
}
// cache for kids items, dnd can't be performed
this._dndCollectKids = function(pId) {
for (var a in this.items) {
if (this.items[a].pId == pId) {
this.conf.dnd.kids[a] = true;
if (this.items[a].kids == true) this._dndCollectKids(a);
}
}
}
this._dndCollectIndexes = function(node) {
for (var q=0; q<node.childNodes.length; q++) {
this.conf.dnd.idx[node.childNodes[q]._itemId] = q;
if (node.childNodes[q].lastChild.className.match(/dhxtreeview_kids_cont/) != null) {
this._dndCollectIndexes(node.childNodes[q].lastChild.firstChild);
}
}
}
// scroll content area
this._dndScroll = function(mode, force) {
if (mode == "stop") {
if (that.conf.dnd.scroll == true) {
if (that.conf.dnd.scroll_tm) window.clearTimeout(that.conf.dnd.scroll_tm);
that.conf.dnd.scroll = false;
}
return;
} else {
if (that.conf.dnd.scroll == true) {
if (force != true) return; // call from script, already performed, aborting
} else {
that.conf.dnd.scroll = true;
}
var stopScroll = false;
if (mode == "up") {
that.cont.scrollTop = Math.max(0, that.cont.scrollTop-that.conf.dnd.scroll_ofs);
if (that.cont.scrollTop == 0) stopScroll = true;
} else {
that.cont.scrollTop = Math.min(that.cont.scrollHeight-that.cont.clientHeight, that.cont.scrollTop+that.conf.dnd.scroll_ofs);
if (that.cont.scrollTop+that.cont.clientHeight == that.cont.scrollHeight) stopScroll = true;
}
if (stopScroll != true) {
that.conf.dnd.scroll_tm = window.setTimeout(function(){
that._dndScroll(mode, true);
}, that.conf.dnd.scroll_time);
}
}
}
if (typeof(window.addEventListener) == "function") {
this.cont.addEventListener("mousedown", this._dndOnMouseDown, false);
} else {
this.cont.attachEvent("onmousedown", this._dndOnMouseDown);
}
// unload
this._dndUnload = function() {
if (typeof(window.addEventListener) == "function") {
this.cont.removeEventListener("mousedown", this._dndOnMouseDown, false);
} else {
this.cont.detachEvent("onmousedown", this._dndOnMouseDown);
}
that = null;
}
conf = null;
};
// register context menu module
dhtmlXTreeView.prototype.modules.ctx = {
init: "_ctxInit",
unload: "_ctxUnload"
};
// public
dhtmlXTreeView.prototype.enableContextMenu = function(mode) {
this.conf.ctx = window.dhx4.s2b(mode);
};
// private
dhtmlXTreeView.prototype._ctxInit = function(conf) { // init
var that = this;
this._ctxCall = function(e) {
if (that.conf.ctx != true) return;
e = e||event;
var t = (e.target||e.srcElement);
if (t.tagName.toLowerCase() == "i") t = t.parentNode; // check if icon
var id = (t.parentNode._itemId||t.parentNode.parentNode._itemId);
var cx = window.dhx4.absLeft(t)+(typeof(e.offsetX)=="undefined"?e.layerX:e.offsetX);
var cy = window.dhx4.absTop(t)+(typeof(e.offsetY)=="undefined"?e.layerY:e.offsetY);
if (id != null && that._callPublicEvent("onContextMenu", [id, cx, cy, e]) !== true) {
if (e.preventDefault) e.preventDefault();
e.cancelBubble = true;
e.returnValue = false;
return false;
}
}
if (typeof(window.addEventListener) == "function") {
this.cont.addEventListener("contextmenu", this._ctxCall, false);
} else {
this.cont.attachEvent("oncontextmenu", this._ctxCall);
}
// unload
this._ctxUnload = function() {
if (typeof(window.addEventListener) == "function") {
this.cont.removeEventListener("contextmenu", this._ctxCall, false);
} else {
this.cont.detachEvent("oncontextmenu", this._ctxCall);
}
that = null;
};
// autoload if any
this.enableContextMenu(conf.context_menu);
};
// reguster dynload module
dhtmlXTreeView.prototype.modules.dynload = {
init: "_dynLoadInit"
};
dhtmlXTreeView.prototype._dynLoadInit = function() {
this.attachEvent("_onItemInited", function(id, data){
// true/false to send extra request to server
this.items[id].kids_request = window.dhx4.s2b(data.kids);
// kids dyn load if any
if (this.items[id].kids_request == true) {
this._initKidsNode(id);
}
// dynload + open, load more data right after item added
if (this.items[id].opened == true && this.items[id].kids_request == true) {
var t = this;
window.setTimeout(function(){
t._dynLoadRequest(id);
t = null;
}, 100);
}
});
this.attachEvent("_onBeforeOpen", function(id){
// load more kids if any
if (this.items[id].opened != true && this.items[id].kids_request == true) {
if (this._dynLoadRequest(id) != true) {
// change only plus-minus, will opened after data loaded
this.items[id].half_opened = true;
this._signUpdate(id);
return false;
}
}
return true;
});
};
dhtmlXTreeView.prototype._dynLoadRequest = function(id) {
// return true/false for node auto-open
// if false - open after data will loaded
if (typeof(this.conf.autoload.mode) == "function") {
this.conf.autoload.mode.apply(window,[id]);
return true;
}
if (this.conf.autoload.url == null) return; // data was loaded in different way
this._dhxdataload.onBeforeXLS = function(url){
return {url:url.replace(/\{id\}/gi,id)};
}
// loading icon
var t = this;
this.items[id].kids_loading_tm = window.setTimeout(function(){
t._dynLoadUpdateIcon(id, true);
t = null;
}, 100);
this.loadStruct(this.conf.autoload.url, function(){
window.clearTimeout(this.items[id].kids_loading_tm);
this._dynLoadUpdateIcon(id, false);
if (this.items[id].half_opened) {
this.items[id].half_opened = false;
this._openCloseItem(id, true);
}
});
this.items[id].kids_request = false;
return false;
};
dhtmlXTreeView.prototype._dynLoadUpdateIcon = function(id, mode) {
this.items[id].loading = (mode == true);
if (this.items[id].loading == true) {
this.items[id].item.childNodes[0].childNodes[this.conf.idx.icon].innerHTML = "<i class='"+this.conf.icons.prefix+" "+this.conf.icons.loading+"'></i>";
} else {
this._iconUpdate(id);
}
};