: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
self.toggle(e.ctrlKey || e.metaKey);
el.classList.add('jsontree_node_expanded');
self.childNodes = childNodes;
self.childNodesUl = childNodesUl;
utils.forEachNode(val, function(label, node, isLast) {
self.addChild(new Node(label, node, isLast));
self.isEmpty = !Boolean(childNodes.length);
el.classList.add('jsontree_node_empty');
utils.inherits(_NodeComplex, _NodeSimple);
utils.extend(_NodeComplex.prototype, {
constructor : _NodeComplex,
* Add child node to list of child nodes
* @param child {Node} - child node
addChild : function(child) {
this.childNodes.push(child);
this.childNodesUl.appendChild(child.el);
* Expands this list of node child nodes
* @param isRecursive {boolean} - if true, expands all child nodes
expand : function(isRecursive){
this.el.classList.add('jsontree_node_expanded');
this.childNodes.forEach(function(item, i) {
item.expand(isRecursive);
* Collapses this list of node child nodes
* @param isRecursive {boolean} - if true, collapses all child nodes
collapse : function(isRecursive) {
this.el.classList.remove('jsontree_node_expanded');
this.childNodes.forEach(function(item, i) {
item.collapse(isRecursive);
* Expands collapsed or collapses expanded node
* @param {boolean} isRecursive - Expand all child nodes if this node is expanded
* and collapse it otherwise
toggle : function(isRecursive) {
this.el.classList.toggle('jsontree_node_expanded');
var isExpanded = this.el.classList.contains('jsontree_node_expanded');
this.childNodes.forEach(function(item, i) {
item[isExpanded ? 'expand' : 'collapse'](isRecursive);
* Find child nodes that match some conditions and handle it
* @param {Function} matcher
* @param {Function} handler
* @param {boolean} isRecursive
findChildren : function(matcher, handler, isRecursive) {
this.childNodes.forEach(function(item, i) {
if (item.isComplex && isRecursive) {
item.findChildren(matcher, handler, isRecursive);
* The constructor for object values
* object = {"abc": "def"}
* @param label {string} - key name
* @param val {Object} - value of object type, {"abc": "def"}
* @param isLast {boolean} - true if node is last in list of siblings
function NodeObject(label, val, isLast) {
_NodeComplex.call(this, label, val, isLast);
utils.inherits(NodeObject,_NodeComplex);
* The constructor for array values
* @param label {string} - key name
* @param val {Array} - value of array type, [1,2,3]
* @param isLast {boolean} - true if node is last in list of siblings
function NodeArray(label, val, isLast) {
_NodeComplex.call(this, label, val, isLast);
utils.inherits(NodeArray, _NodeComplex);
/* ---------- The tree constructor ---------- */
* The constructor for json tree.
* It contains only one Node (Array or Object), without property name.
* CSS-styles of .tree define main tree styles like font-family,
* font-size and own margins.
* <ul class="jsontree_tree clearfix">
* @param jsonObj {Object | Array} - data for tree
* @param domEl {DOMElement} - DOM-element, wrapper for tree
function Tree(jsonObj, domEl) {
this.wrapper = document.createElement('ul');
this.wrapper.className = 'jsontree_tree clearfix';
this.sourceJSONObj = jsonObj;
* Fill new data in current json tree
* @param {Object | Array} jsonObj - json-data
loadData : function(jsonObj) {
if (!utils.isValidRoot(jsonObj)) {
alert('The root should be an object or an array');
this.sourceJSONObj = jsonObj;
this.rootNode = new Node(null, jsonObj, 'last');
this.wrapper.innerHTML = '';
this.wrapper.appendChild(this.rootNode.el);
* Appends tree to DOM-element (or move it to new place)
* @param {DOMElement} domEl
appendTo : function(domEl) {
domEl.appendChild(this.wrapper);
* Expands all tree nodes (objects or arrays) recursively
* @param {Function} filterFunc - 'true' if this node should be expanded
expand : function(filterFunc) {
if (this.rootNode.isComplex) {
if (typeof filterFunc == 'function') {
this.rootNode.childNodes.forEach(function(item, i) {
if (item.isComplex && filterFunc(item)) {
this.rootNode.expand('recursive');
* Collapses all tree nodes (objects or arrays) recursively
if (typeof this.rootNode.collapse === 'function') {
this.rootNode.collapse('recursive');
* Returns the source json-string (pretty-printed)
* @param {boolean} isPrettyPrinted - 'true' for pretty-printed string
* @returns {string} - for exemple, '{"a":2,"b":3}'
toSourceJSON : function(isPrettyPrinted) {
return JSON.stringify(this.sourceJSONObj);
var DELIMETER = "[%^$#$%^%]",
jsonStr = JSON.stringify(this.sourceJSONObj, null, DELIMETER);
jsonStr = jsonStr.split("\n").join("<br />");
jsonStr = jsonStr.split(DELIMETER).join(" ");
* Find all nodes that match some conditions and handle it
findAndHandle : function(matcher, handler) {
this.rootNode.findChildren(matcher, handler, 'isRecursive');
this.rootNode.findChildren(function(node) {
/* ---------- Public methods ---------- */
* Creates new tree by data and appends it to the DOM-element
* @param jsonObj {Object | Array} - json-data
* @param domEl {DOMElement} - the wrapper element
create : function(jsonObj, domEl) {
return new Tree(jsonObj, domEl);