deploy1 6 роки тому
батько
коміт
d046bd3d1a
5 змінених файлів з 5337 додано та 233 видалено
  1. 2191 0
      editor_types.js
  2. 801 194
      index.js
  3. 2251 0
      index2.js
  4. 3 1
      package.json
  5. 91 38
      templates.js

+ 2191 - 0
editor_types.js

@@ -0,0 +1,2191 @@
+module.exports = function(self) {
+    function mmb(t, d) {
+        return '<div class="mb"><h3>' + t + '</h3>' + d + '</div>';
+    }
+
+    function allchildren(obj_) {
+        var obj = typeof(obj_) === "function" ? obj_() : obj_;
+        return [].concat.apply([obj], _.map(obj.children, allchildren))
+    }
+
+    var _ = require("lodash");
+    var opath = require("opath");
+
+    var types = {}
+
+    types.allmodules = function(obj, field) {
+        return '<pre>' + self.allchildren().filter(function(a) {
+            return a._metas.modules ? true : false
+        }).map(function(a) {
+            return _.repeat(" ", a.path.split("/").length) + '<a href="#" elepath="' + a.path + '" class="elecontent ' + (a.path === obj.path ? 'active' : '') +
+                '">' + a.path + '</a>'
+        }).join("\n") + '</pre>';
+    }
+    types.availablemodules = function(obj, field) {
+        var s = '<pre>' + _.map(self.editorTypes(), function(func, name) {
+            return name;
+        }).join("\n");
+        s += "\n";
+        s += self.allchildren().filter(function(a) {
+            return a.modulefunc
+        }).map(function(child) {
+            return '<a href="#" class="elecontent" elepath="' + child.path + '">' + child.path + '.modulefunc</a>';
+        }).join("\n");
+        s += '</pre>';
+        return s;
+    }
+
+    types.layouttabedit = function(obj, field) {
+        field.excludekeys = field.excludekeys || ["layouts"];
+        return types.alineedit(obj, field);
+    }
+
+    types.alineedit = function(obj, field) {
+        var oa = opath.get(obj, field.path);
+
+
+        /*if(!oa){
+            opath.set(obj, field.path,{})
+        }
+     */
+
+        var excludekeys = ["type", "modules"].concat(field.excludekeys || []);
+        console.log("EEEEEEEEEEEEEEEEEEEEEE",excludekeys);
+        var tmp = {}
+
+        var s = _.keys(oa).filter(function(key) {
+            return excludekeys.indexOf(key) === -1;
+        }).map(function(key) {
+            if (_.isArray(oa[key])) {
+                return _.map(oa[key], function(tab, i) {
+                    return '<div class="' + key + '"><label>' + key + '</label><div class="subs">' + types.alineedit(obj, {
+                        path: field.path + "." + key + "." + i
+                    }) + '</div></div>'
+                }).join("\n");
+
+            } else {
+
+                if (typeof(oa[key]) === "function") {
+                    tmp[obj.path + '/.' + field.path + '.' + key] = true;
+                    return '<div class="' + key + '"><label>' + key + '</label> <textarea class="mini  " data-id="' + obj.path + '/.' + field.path + '.' +
+                        key + '" name="' + key + '" >' + oa[key] + '</textarea>' + ((oa.type && types[oa.type] && types[oa.type].settings && types[oa.type].settings[
+                            key]) ? types[oa.type].settings[key].info + ' def:' + types[oa.type].settings[key].default : '') + '</div>';
+
+                }
+
+
+
+                if (_.isObject(oa[key])) {
+
+                    return '<div class="' + key + '"><label>' + key + '</label><div class="subs">' + _.map(oa[key], function(taba, i) {
+                        return '<span>' + i + '</span>' + (typeof(taba) === "boolean" ? types.truefalse(obj, {
+                            path: field.path + "." + key + "." + i
+                        }) : '<input class="mini"   value="' + taba + '">')
+                    }).join("\n") + '</div></div>';
+
+                } else {
+                    if (key === "type") {
+                        return '<div class="' + key + '"><label>' + key + '</label> <select data-id="' + obj.path + '/.' + field.path + '.' + key + '" class="changetype">' +
+                            _.map(types, function(func, name) {
+                                return '<option value="' + name + '" ' + (name === oa[key] ? 'selected' : '') + '>' + name + '</option>'
+                            }).join("\n") + '</select>' + (types[oa[key]] ? types[oa[key]].help : 'na') + '</div>';
+
+                    } else {
+
+                        if (key.indexOf("data") === 0) {
+                            tmp[obj.path + '/.' + field.path + '.' + key] = true;
+
+                            return '<div class="' + key + '"><label>' + key + '</label> <textarea class="mini htmleditor" data-id="' + obj.path + '/.' + field.path + '.' +
+                                key + '" name="' + key + '">' + oa[key] + '</textarea>' + ((oa.type && types[oa.type] && types[oa.type].settings && types[oa.type].settings[
+                                    key]) ? types[oa.type].settings[key].info + ' def:' + types[oa.type].settings[key].default : '') + '</div>';
+                        } else {
+
+
+
+                            tmp[obj.path + '/.' + field.path + '.' + key] = true;
+
+                            return '<div class="' + key + '"><label>' + key + '</label> <input class="mini propeditor" data-id="' + obj.path + '/.' + field.path + '.' +
+                                key + '" name="' + key + '" value="' + oa[key] + '">' + ((oa.type && types[oa.type] && types[oa.type].settings && types[oa.type].settings[
+                                    key]) ? types[oa.type].settings[key].info + ' def:' + types[oa.type].settings[key].default : '') + '</div>';
+
+
+
+                        }
+
+
+
+                    }
+
+
+                }
+
+
+            }
+        }).join("\n");
+
+
+        if (types[oa.type]) {
+
+
+            s = '<div class="type"><label>type</label> <select  data-id="' + obj.path + '/.' + field.path + '.type" class="changetype" >' + _.map(types, function(func, name) {
+                return '<option value="' + name + '" ' + (name === oa.type ? 'selected' : '') + '>' + name + '</option>'
+            }).join("\n") + '</select>' + (types[oa.type] ? types[oa.type].help : 'na') + '</div>' + s
+
+            s += _.map(types[oa.type].settings || {}, function(val, key) {
+                if (tmp[obj.path + '/.' + field.path + '.' + key]) {
+                    return "";
+                }
+                return '<div class="' + key + '"><label>' + key + '</label> <input class="mini propeditor" data-id="' + obj.path + '/.' + field.path + '.' + key +
+                    '" name="' + key + '" value="' + (oa[key] || val.default) + '"> ' + (val.info ? val.info + ' def:' + val.default : '') + '</div>';
+
+            })
+
+
+        } else {
+
+            s = '<div class="type"><label>type</label> <select  data-id="' + obj.path + '/.' + field.path + '.type" class="changetype" >' + _.map(types, function(func, name) {
+                return '<option value="' + name + '" ' + (name === oa.type ? 'selected' : '') + '>' + name + '</option>'
+            }).join("\n") + '</select>' + (types[oa.type] ? types[oa.type].help : 'na') + '</div>' + s
+
+
+        }
+        s += '<div class="newprop" data-id="' + obj.path + '/.' + field.path +
+            '"><input class="newprop_prop" type="text" placeholder="key" ><input type="text" placeholder="value" class="newprop_value"></div>'
+
+        return s;
+    }
+
+
+
+
+    types.elementseditor = function(obj, field) {
+
+        console.log("FFFF", field);
+        var template_tab = ""
+        template_tab += '<li data-id="{{path}}" data-prop="{{childrenpath}}" class="{{clss}}">';
+
+        if ((!field.show) ||
+            (field.show && field.show.tool !== false)
+        ) {
+            template_tab += '<div class="tool">';
+            template_tab += '<span class="expand"> </span>';
+            if ((!field.show) ||
+                (field.show && field.show.mover !== false)
+            ) {
+                template_tab += '<span class="hh"> </span>';
+            }
+            if ((!field.show) ||
+                (field.show && field.show.add !== false)
+            ) {
+                template_tab += '<button tab-index=-1 data-id="{{path}}.{{childrenpath}}" class="addelement">Add</button>';
+            }
+            if ((!field.show) ||
+                (field.show && field.show.modules !== false)
+            ) {
+                template_tab += '<button tab-index=-1 data-id="{{path}}.modules" class="addmodules">Add module</button>';
+            }
+            if ((!field.show) ||
+                (field.show && field.show.delete !== false)
+            ) {
+                template_tab += '<button tab-index=-1 data-id="{{path}}" class="deletetab">Delete</button>';
+            }
+            if ((!field.show) ||
+                (field.show && field.show.title !== false)
+            ) {
+                template_tab += '<input class="mini propeditor" rerender=true data-id="{{path}}.title" value="{{tab.title}}" >';
+            }
+            if ((!field.show) ||
+                (field.show && field.show.name !== false)
+            ) {
+                template_tab += '<input class="mini propeditor" rerender=true data-id="{{path}}.name" value="{{tab.name}}" >';
+            }
+            template_tab += '</div>'
+        }
+        if ((!field.show) ||
+            (field.show && field.show.editor !== false)
+        ) {
+            if (field.defaults) {
+                template_tab += '<div class="dde">' + _.map(field.defaults, function(d, k) {
+                    return '<input type="text" '
+                }).join("\n") + '</div>'
+
+            }
+            template_tab += '<div class="edi">{{xtypeselect}}{{alinee}}</div>'
+        }
+
+
+
+        if ((!field.show) ||
+            (field.show && field.show.modules !== false)
+        ) {
+            template_tab += '<ol class="moda" data-id="{{path}}.modules">{{mods}}</ol>'
+        } else {
+            if (field.allsamemodule) {
+                template_tab += '<ol class="moda" data-id="{{path}}.modules">{{mods}}</ol>'
+            }
+        }
+
+
+
+        if ((!field.show) ||
+            (field.show && field.show.children !== false)
+        ) {
+            template_tab += '<ol class="tubu" data-id="{{path}}.{{childrenpath}}">{{content}}</ol>'
+        }
+        template_tab += '</li>'
+
+
+        var template_module = '<li data-id="{{path}}.modules.{{index}}">';
+
+        if ((!field.show) ||
+            (field.show && field.show.tool !== false)
+        ) {
+            template_module += '<div class="tool">'
+            template_module += '<span class="expandm"> </span>'
+            template_module += '<span class="hh"> </span>'
+            template_module += '{{xtypeselect}}'
+            template_module += '<span class="deletemod">Delete</span>'
+            template_module += '<div class="title">{{mod.type}} {{mod.name}} {{mod.title}}</div>'
+            template_module += '</div>'
+        }
+
+        template_module += '<div class="modcon"></div>'
+        template_module += '</li>'
+
+
+        var ta3 =
+            `<div  >
+            <div class="tool"><button data-id="{{obj.path}}/.{{fieldpath}}" data-name="{{dataname}}" class="addelement">Add</button></div>
+            <ol class="tibi" data-id="{{obj.path}}/.{{fieldpath}}">
+                {{basecontent}}
+            </ol>
+        </div>`;
+
+        function rec_go(arr, prop, path, func, level_) {
+            var level = level_ || 0;
+            return _.map((arr || []), function(a, i) {
+                if (a[prop] && _.isArray(a[prop])) {
+                    return func(a, path + "." + i, rec_go(a[prop], prop, path + "." + i + "." + prop, func, level + 1));
+                } else {
+                    return func(a, path + "." + i)
+                }
+            }).join("\n");
+        }
+
+
+
+        function gmods(tab, path) {
+            var arrr = (tab.modules || []);
+
+
+            return _.map(arrr, function(m, mi) {
+
+
+                return self.template(template_module, {
+                    tab: tab,
+                    path: path,
+                    mod: m,
+                    /*                    datas: types[m.type] ? types[m.type](obj, m) : "na",*/
+
+                    typeselect: '<select  data-id="' + path + '.modules.' + mi + '.type" class="changetype" >' + _.keys(types).filter(
+                        function(
+                            name) {
+                            return name.indexOf("element_") > -1
+                        }).map(function(name) {
+                        return '<option value="' + name + '" ' + (name === m.type ? 'selected' : '') + '>' + name + '</option>'
+                    }).join("\n") + '</select>',
+                    index: mi
+                })
+            }).join("\n")
+
+
+
+        }
+
+        var zearr = opath.get(obj, field.path);
+        if (field.find) {
+            /*  zearr = zearr.filter(function(a) {
+                return a.name.indexOf(field.find) > -1
+            })*/
+        }
+
+        return self.template(ta3, {
+            dataname: field.dataname,
+            obj: obj,
+            childrenpath: field.childrenpath,
+            fieldpath: field.path,
+            basecontent: rec_go(zearr, field.childrenpath, obj.path + "/." + field.path, function(tab, path, content) {
+                /* if(field.find && tab.name.indexOf(field.find)===-1){
+                    return "xx:"+field.find+":"+tab.name;
+                }*/
+                return self.template(template_tab, {
+                    clss: field.find && tab.name.indexOf(field.find) === -1 ? "hidden" : "show",
+                    tab: tab,
+                    path: path,
+                    typeselect: '<select  data-id="' + path + '.type" class="changetype" >' + _.keys(types).filter(function(name) {
+                        return name.indexOf("element_") > -1
+                    }).map(function(name) {
+                        return '<option value="' + name + '" ' + (name === tab.type ? 'selected' : '') + '>' + name + '</option>'
+                    }).join("\n") + '</select>',
+                    childrenpath: field.childrenpath,
+                    alinee: types.alineedit(obj, {
+                        path: path.split("/.").pop(),
+                        excludekeys: [field.childrenpath]
+                    }),
+                    mods: gmods(tab, path),
+                    content: content
+                })
+            })
+        });
+    }
+
+    types.elementseditor.help = "elementseditor help";
+    types.elementseditor.settings = {
+        "path": {
+            default: "_data.elements",
+            "info": "path to array"
+        },
+        "childrenpath": {
+            default: "elements",
+            "info": "array name"
+        },
+        "show": {
+            default: {
+                "tool": true,
+                "mover": true,
+                "add": true,
+                "modules": true,
+                "children": true,
+                "delete": true,
+                "editor": true
+            },
+            "info": "shows"
+
+        }
+    };
+
+
+
+
+
+    types.elementstree = function(obj, field) {
+
+
+        var ta1 =
+            `<li data-id="{{path}}" data-prop="{{childrenpath}}">
+                <div class="tool">
+                    <div class="title">{{tab.title}}</div>
+                </div>
+                <div class="edi">
+                   
+                </div>
+                <ol class="moda" data-id="{{path}}.modules">
+                    {{mods}}
+                </ol>
+                <ol class="tubu" data-id="{{path}}.{{childrenpath}}">
+                    {{content}}
+                </ol>
+            </li>`;
+        var ta2 =
+            `<li data-id="{{path}}.modules.{{index}}">
+             <div class="title">{{mod.title}}</div>
+             <div>
+             {{datas}}
+             </div>
+            </li>`;
+        var ta3 =
+            `<div class="t_{{obj.name}} {{field.unc}}">
+                <ol class="tibi" data-id="{{obj.path}}/.{{fieldpath}}">
+                    {{basecontent}}
+                </ol>
+             </div>`;
+
+
+
+
+        function rec_go(arr, prop, path, func, level_) {
+            var level = level_ || 0;
+            return _.map((arr || []), function(a, i) {
+                if (a[prop] && _.isArray(a[prop])) {
+                    return func(a, path + "." + i, rec_go(a[prop], prop, path + "." + i + "." + prop, func, level + 1));
+                } else {
+                    return func(a, path + "." + i)
+                }
+            }).join("\n");
+        }
+        return self.template(ta3, {
+            obj: obj,
+            childrenpath: field.childrenpath,
+            fieldpath: field.path,
+            field: field,
+            basecontent: rec_go(opath.get(obj, field.path), field.childrenpath, obj.path + "/." + field.path, function(tab, path, content) {
+                return self.template(ta1, {
+                    tab: tab,
+                    path: path,
+                    childrenpath: field.childrenpath,
+                    mods: _.map((tab.modules || []), function(m, mi) {
+
+                        return self.template(ta2, {
+                            tab: tab,
+                            path: path,
+                            mod: m,
+                            datas: types[m.type] ? types[m.type](obj, m) : "na",
+                            index: mi
+                        })
+                    }).join("\n"),
+                    content: content
+                })
+            })
+        });
+    }
+    types.elementstree.help = "elements view";
+    types.elementstree.settings = {
+        "path": {
+            default: "_data.elements",
+            "info": "path to array"
+        },
+        "childrenpath": {
+            default: "elements",
+            "info": "array name"
+        }
+    };
+
+
+
+
+    types.get_renders = function(obj, field) {
+
+        var layouts = obj.getStuff3(field.path, function(a) {
+            return a
+        }, field.path);
+
+        var yy = {}
+        while (layouts.length) {
+            var ta = layouts.pop();
+            ta.data.map(function(tta) {
+                var t = _.cloneDeep(tta);
+                t.froma = ta.name;
+                var tname = t.name;
+                if (t.target) {
+                    tname = t.target
+                }
+                if (t.method) {
+                    if (t.method == "replace") {
+                        if (yy[tname]) {
+                            var tt = yy[tname].froma;
+                            yy[tname] = t;
+                            yy[tname].froma_replaced = tt;
+                        } else {
+                            yy[tname] = t;
+                        }
+                    }
+                    if (t.method == "append") {
+                        if (yy[tname]) {
+                            yy[tname].content = yy[tname].content || []
+                            yy[tname].content.push(t);
+                        } else {
+                            yy[tname] = t;
+                        }
+                    }
+                    if (t.method == "prepend") {
+                        if (yy[tname]) {
+                            yy[tname].content = yy[tname].content || []
+                            yy[tname].content.unshift(t);
+                        } else {
+                            yy[tname] = t;
+                        }
+                    }
+                } else {
+                    if (yy[tname]) {
+                        yy[tname].content = yy[tname].content || []
+                        yy[tname].content.push(t);
+                    } else {
+                        yy[tname] = t;
+                    }
+                }
+            })
+        }
+        return yy;
+    }
+
+    types.renderlayout = function(obj, field) {
+        console.log("FFFFFFFFFFFFFFFFFFFFFFFFFFFFF", field);
+
+
+        function rega(a) {
+
+            return self.template(field.data ? field.data : '<div class="{{keya}}" data-froma="{{val.froma}}">{{mods}}{{content}}</div>', {
+                keya: a.name,
+                val: a,
+                mods: (a.modules || []).map(function(m) {
+                    return types[m.type] ? types[m.type](obj, m) : self.template(m.data, {
+                        obj: obj,
+                        m: m,
+                        tab: a
+                    })
+                }).join("\n"),
+                content: a[field.childrenpath] ? a[field.childrenpath].map(rega).join("\n") : a.data
+
+            })
+        }
+
+        function kmap(a, pa) {
+            var s = _.map(a, function(val, key) {
+                return self.template(field.data ? (field.data_before + field.data + field.data_after) :
+                    '<div id="{{key}}" data-froma="{{val.froma}}">{{selfa}}{{mods}}{{content}}</div>', {
+                        key: key,
+
+                        val: val,
+                        mods: (val.modules || []).map(function(m) {
+                            console.log("MMMM", m)
+                            return types[m.type] ? types[m.type](obj, m) : self.template(m.data, {
+                                obj: obj,
+                                m: m,
+                                tab: val
+                            })
+                        }).join("\n"),
+                        selfa: val.data ? self.template(val.data, obj) : "",
+                        content: (val[field.childrenpath] || []).map(rega).join("\n") + (val.content || []).map(rega).join("\n")
+                    });
+
+            }).join("\n");
+            return s;
+        }
+
+        var yy = types.get_renders(obj, field);
+        var ssa = "";
+        if (field.debug) {
+            var cont = JSON.stringify(yy, true, 2)
+            ssa = '<div style="width: 100%; float: left;">' + '<textarea cols="80" rows="80" style="width: 600px; font-size: 8px;">' + kmap(yy, []) +
+                '</textarea>' + '<hr><textarea cols="80" rows="80" style="width: 600px; font-size: 8px;">' + cont +
+                '</textarea></div>'
+
+        }
+
+
+
+
+        return self.template(kmap(yy, []).replace("%%CONTENT%%", field.content), obj) + ssa
+
+
+
+
+
+        console.log("YYYYYYYYYYYYYYY", yy);
+
+        return JSON.stringify(yy, true, 2);
+
+
+        /*
+
+        var layouts = [];
+        var x = obj.getStuff3("_data.layouts", function(a) {
+            return a
+        }, "_data.layouts").map(function(a) {
+            layouts = layouts.concat(a.data);
+            return a;
+        });
+
+
+
+
+
+
+
+
+        console.log(layouts, x)
+
+
+
+        function rec_go(arr, prop, path, func, level_) {
+            var level = level_ || 0;
+            return _.map((arr || []), function(a, i) {
+                if (a[prop] && _.isArray(a[prop])) {
+                    return func(a, path.concat(a.name).join("."), rec_go(a[prop], prop, path.length === 0 && !a.name ? path : path.concat(a.name), func, level + 1));
+                } else {
+                    return func(a, path.concat(a.name).join("."))
+                }
+            }).join("\n");
+        }
+
+        var s = "";
+
+
+        var cont = "";
+        var obja = {};
+        var ps = {};
+        var alle = [];
+        x.reverse();
+        var ind = 0;
+        while (x.length) {
+            var t = x.shift();
+            console.log("TTTTTTTTTT_", t.data, t);
+
+            if (ind === 0) {
+                //first
+                t.data.map(function(ta) {
+                    obja[ta.name] = {
+                        data: ta.data,
+                        name: ta.name,
+                        modules: ta.modules
+                    }
+                })
+            } else {
+                t.data.map(function(ta) {
+                    if (obja[ta.name]) {
+                        obja[ta.name].layouts = obja[ta.name].layouts || []
+                        obja[ta.name].layouts.push(ta);
+                    } else {
+                        //obja[ta.name] = ta
+                        console.log("NAAAAAAA", ta.name);
+                    }
+                })
+
+
+            }
+            ind++
+            //   
+
+                      var nn = t.name.split("/").pop();
+            rec_go([{
+                layouts: t.data
+            }], "layouts", [], function(taba, path, content) {
+                var ta = _.omit(taba, ["layouts"]);
+                ta.path = path;
+                ta.from = t.name + "/." + t.from
+                alle.push(ta)
+            })
+ 
+
+        }
+
+
+        cont = JSON.stringify(obja, true, 2)
+
+
+        function kmap(a, pa) {
+            return _.map(a, function(val, key) {
+                return _.repeat(" ", pa.length) + '<div class="' + pa.concat(key).join("-") + (pa.length > 0 ? ' ' + key : '') + '" >\n' + _.repeat(" ", pa.length) + (
+                        typeof(val) === "object" ? kmap(val, pa.concat(key)) : (["content", "data"].indexOf(key) > -1 ? self.template(val, obj) : val)) + '\n' + _.repeat(
+                        " ", pa.length) +
+                    '</div>'
+            }).join("\n");
+        }
+
+
+        var ssa = '<div style="width: 100%; float: left;">' + '<textarea cols="80" rows="80" style="width: 600px; font-size: 8px;">' + kmap(obja, []) +
+            '</textarea>' + '<hr><textarea cols="80" rows="80" style="width: 600px; font-size: 8px;">' + cont +
+            '</textarea></div>'
+
+
+        return self.template(kmap(obja, []).replace("%%CONTENT%%", field.content), obj) + ssa
+
+
+
+        return s;
+
+
+        return rec_go(layouts, "layouts", "layouts", function(tab, path, content) {
+            return tab.title + " " + path;
+
+        })
+
+        return layouts.map(function(a) {
+            return a.name === obj.path ? types.renderlayout_t(self.oget(a.name), {}) : types.renderlayout_t(self.oget(a.name), {});
+        }).join("\n");
+    */
+
+    }
+
+    types.renderlayout22 = function(obj, field) {
+
+        var layouts = [];
+        var x = obj.getStuff3("_data.layouts", function(a) {
+            return a
+        }, "_data.layouts").map(function(a) {
+            layouts = layouts.concat(a.data);
+            return a;
+        });
+
+        console.log(layouts, x)
+
+
+
+        function rec_go(arr, prop, path, func, level_) {
+            var level = level_ || 0;
+            return _.map((arr || []), function(a, i) {
+                if (a[prop] && _.isArray(a[prop])) {
+                    return func(a, path + "." + a.name, rec_go(a[prop], prop, path + "." + a.name, func, level + 1));
+                } else {
+                    return func(a, path + "." + a.name)
+                }
+            }).join("\n");
+        }
+
+        var s = "";
+
+
+        var cont = "";
+        var obja = {};
+        while (x.length) {
+            var t = x.pop();
+            console.log("T", t.name);
+
+            t.data.map(function(tab) {
+                if (tab.target) {} else {
+                    console.log("mmmmmmmm      ", tab.name, tab);
+
+                    obja[tab.name] = {
+                        "data": tab.data,
+                        "modules": tab.modules
+                    };
+
+                    rec_go(tab.layouts, "layouts", tab.name, function(taba, path, content) {
+                        if (taba.target && !obja[taba.target]) {
+                            //    console.log("TTTTT      ", path, taba);
+                        } else {
+
+                            //                            console.log(":::::::::::", path, taba);
+                            opath.set(obja, path + ".data", taba.data);
+                            opath.set(obja, path + ".modules", taba.modules);
+                        }
+
+
+                    })
+
+
+
+
+
+                    // obja[tab.name] = tab;
+                }
+            })
+
+            t.data.map(function(tab) {
+
+                rec_go(tab.layouts, "layouts", tab.name, function(taba, path, content) {
+                    if (taba.target) {
+                        opath.set(obja, taba.target + "." + tab.name + ".data", tab.data);
+                        opath.set(obja, taba.target + "." + tab.name + ".modules", tab.modules);
+                    }
+                })
+
+
+
+
+
+            })
+
+
+            t.data.map(function(tab) {
+                if (tab.target) {
+
+
+                    opath.set(obja, tab.target + "." + tab.name + ".data", tab.data);
+                    opath.set(obja, tab.target + "." + tab.name + ".modules", tab.modules);
+
+                    rec_go(tab.layouts, "layouts", tab.name, function(taba, path, content) {
+                        if (taba.target) {
+                            console.log("TTTTT      ", path, taba);
+                        } else {
+                            opath.set(obja, tab.target + "." + path + ".data", taba.data);
+                            opath.set(obja, tab.target + "." + path + ".modules", taba.modules);
+                            console.log(":::::::::::", tab.target + "." + path, taba);
+                        }
+
+                    })
+                }
+            })
+
+
+
+
+
+
+            /*t.data.map(function(tab){
+            if(obja[tab.name]){
+
+            }else{
+                if(tab.target){
+
+                    obja[tab.target] = obja[tab.target] || [];
+                    obja[tab.target].push(tab);                    
+                }else{
+                    obja[tab.name]=[tab]
+                }
+
+            }
+
+        })*/
+
+        }
+
+        /*
+        løb over 2-3 gange ...obja[name] = [] ..push.
+
+
+*/
+
+        cont = '<pre>' + JSON.stringify(obja, true, 2) + '</pre>'
+
+
+        function kmap(a, pa) {
+            return _.map(a, function(val, key) {
+                return _.repeat(" ", pa.length) + '<div class="' + pa.concat(key).join("-") + (pa.length > 0 ? ' ' + key : '') + '" >\n' + _.repeat(" ", pa.length) + (
+                        typeof(val) === "object" ? kmap(val, pa.concat(key)) : (key === "content" ? self.template(val, obj) : val)) + '\n' + _.repeat(" ", pa.length) +
+                    '</div>'
+            }).join("\n");
+        }
+
+
+
+
+        return self.template(kmap(obja, []).replace("%%CONTENT%%", field.content), obj) + ' ' + '<textarea cols="80" rows="120" style="width: 600px;">' + kmap(obja, []) +
+            '</textarea>'
+
+
+        return s;
+
+
+        return rec_go(layouts, "layouts", "layouts", function(tab, path, content) {
+            return tab.title + " " + path;
+
+        })
+
+        return layouts.map(function(a) {
+            return a.name === obj.path ? types.renderlayout_t(self.oget(a.name), {}) : types.renderlayout_t(self.oget(a.name), {});
+        }).join("\n");
+
+
+    }
+    types.renderlayout_t = function(obj, field) {
+        var ta1 =
+            `<li data-id="{{path}}" data-prop="{{childrenpath}}">
+                <div class="tool">
+                    <div class="title">{{tab.name}}  {{tab.id}} {{tab.title}}  {{tab.title}}</div>
+                </div>
+                <div class="edi">
+                   
+                </div>
+                <ol class="moda" data-id="{{path}}.modules">
+                    {{mods}}
+                </ol>
+                <ol class="tubu" data-id="{{path}}.{{childrenpath}}">
+                    {{content}}
+                </ol>
+            </li>`;
+        var ta2 =
+            `<li data-id="{{path}}.modules.{{index}}">
+             <div class="title">{{mod.title}}</div>
+             <div>
+             {{datas}}
+             </div>
+            </li>`;
+        var ta3 =
+            `<div class="t_{{obj.name}} {{field.unc}}">
+                <ol class="tibi" data-id="{{obj.path}}/.{{fieldpath}}">
+                    {{basecontent}}
+                </ol>
+             </div>`;
+
+
+
+
+        function rec_go(arr, prop, path, func, level_) {
+            var level = level_ || 0;
+            return _.map((arr || []), function(a, i) {
+                if (a[prop] && _.isArray(a[prop])) {
+                    return func(a, path + "." + i, rec_go(a[prop], prop, path + "." + i + "." + prop, func, level + 1));
+                } else {
+                    return func(a, path + "." + i)
+                }
+            }).join("\n");
+        }
+
+        field.childrenpath = "layouts";
+        field.path = "_data.layouts";
+
+        return self.template(ta3, {
+            obj: obj,
+            childrenpath: field.childrenpath,
+            fieldpath: field.path,
+            field: field,
+            basecontent: rec_go(opath.get(obj, field.path), field.childrenpath, obj.path + "/." + field.path, function(tab, path, content) {
+                return self.template(ta1, {
+                    tab: tab,
+                    path: path,
+                    childrenpath: field.childrenpath,
+                    mods: _.map((tab.modules || []), function(m, mi) {
+
+                        return self.template(ta2, {
+                            tab: tab,
+                            path: path,
+                            mod: m,
+                            datas: types[m.type] ? types[m.type](obj, m) : "na",
+                            index: mi
+                        })
+                    }).join("\n"),
+                    content: content
+                })
+            })
+        });
+    }
+    types.layouteditor = function(obj, field) {
+
+
+        var layouts = obj.getStuff3("_data.layouts", function(a) {
+            return a
+        }, "_data.layouts");
+        var s = "";
+        /*if (!obj._data.layouts || obj._data.layouts.length === 0) {
+            s += types.elementseditor(obj, {
+                "path": "_data.layouts",
+                "childrenpath": "layouts",
+                "show": {
+                    "title": false,
+                    "name": true
+                }
+            });
+
+        }*/
+
+        s += types.elementseditor(obj, {
+            "path": "_data.layouts",
+            "childrenpath": "layouts",
+            "show": {
+                "title": false,
+                "name": true
+            }
+        });
+
+
+        // var selfi = layouts.shift();
+
+        var yy = {}
+        while (layouts.length) {
+            var ta = layouts.pop();
+
+            ta.data.map(function(tta) {
+                var t = _.clone(tta);
+                t.froma = ta.name;
+                if (t.method) {
+                    if (t.method == "replace") {
+                        if (yy[t.name]) {
+                            var tt = yy[t.name].froma;
+                            yy[t.name] = t;
+                            yy[t.name].froma_replaced = tt;
+                        } else {
+                            yy[t.name] = t;
+
+                        }
+                    }
+                } else {
+                    yy[t.name] = t;
+                }
+                console.log("TTT", t);
+
+            })
+
+
+        }
+
+        console.log("YYYYYYYYYYYYYYY", yy);
+
+        return s;
+
+
+
+        if (layouts.length === 0) {
+            return 'no layout'
+        }
+        var alltabs = [];
+        var sil = layouts.shift();
+
+        layouts.map(function(a) {
+            alltabs = alltabs.concat(a.data)
+        })
+
+        s += sil.data.map(function(t) {
+            return '<h6>' + t.name + '</h6>' + JSON.stringify(t);
+        }).join("\n")
+
+        s += alltabs.map(function(t) {
+            return '<h3>' + t.name + '</h3>' + JSON.stringify(t);
+        }).join("\n")
+
+
+
+        return s;
+
+
+        if (layouts.length > 1) {
+            /* s += layouts.map(function(a) {
+                return a.name === obj.path ? "FFF" : types.layouteditor_tree(self.oget(a.name), {}, obj);
+            }).join("\n");
+            */
+            //s += types.layouteditor_tree(self.oget(layouts[layouts.length - 1].name), {}, obj)
+
+
+            /*          types.elementseditor(obj, {
+                        "path": "_data.layouts",
+                        "childrenpath": "layouts",
+                        "find": tab.name,
+                        "dataname": tab.name
+                    }
+*/
+        } else {
+
+            s += layouts.map(function(a) {
+                return a.name === obj.path ? types.elementseditor(obj, {
+                    "path": "_data.layouts",
+                    "childrenpath": "layouts",
+                    "show": {
+                        "title": false,
+                        "name": true
+                    }
+                }) : types.layouteditor_tree(self.oget(a.name), {}, obj);
+            }).join("\n");
+
+
+        }
+
+        return s;
+
+
+    }
+    types.layouteditor_tree = function(obj, field, obj2) {
+        var ta1 =
+            `<li data-id="{{path}}" data-prop="{{childrenpath}}">
+            <div class="tool">
+                ddd {{tab.id}}  {{tab.name}}  {{tab.title}}
+             </div>
+             {{mods}}
+            <ol class="tubu" data-id="{{path}}.{{childrenpath}}">
+                {{content}}
+            </ol>
+            <div>{{obj2thing}}</div>
+
+        </li>`;
+        var ta2 =
+            `<li data-id="{{path}}.modules.{{index}}">
+            <div class="tool">
+                <div class="title">{{mod.type}} {{mod.name}} {{mod.title}}</div>
+
+
+            </div>
+            <div class="modcon"></div>
+        </li>`;
+        var ta3 =
+            `<div >
+            <ol class="tibi" data-id="{{obj.path}}/.{{fieldpath}}">
+                {{basecontent}}
+            </ol>
+         </div>`;
+
+        function rec_go(arr, prop, path, func, level_) {
+            var level = level_ || 0;
+            return _.map((arr || []), function(a, i) {
+                if (a[prop] && _.isArray(a[prop])) {
+                    return func(a, path + "." + i, rec_go(a[prop], prop, path + "." + i + "." + prop, func, level + 1));
+                } else {
+                    return func(a, path + "." + i)
+                }
+            }).join("\n");
+        }
+        field.childrenpath = "layouts";
+        field.path = "_data.layouts";
+
+        return self.template(ta3, {
+            obj: obj,
+            childrenpath: field.childrenpath,
+            fieldpath: field.path,
+            basecontent: rec_go(opath.get(obj, field.path), field.childrenpath, obj.path + "/." + field.path, function(tab, path, content) {
+                return self.template(ta1, {
+                    obj2thing: types.elementseditor(obj2, {
+                        "path": "_data.layouts",
+                        "childrenpath": "layouts",
+                        "find": tab.name,
+                        "dataname": tab.name
+                    }),
+                    tab: tab,
+                    path: path,
+                    typeselect: '<select  data-id="' + path + '.type" class="changetype" >' + _.keys(types).filter(function(name) {
+                        return name.indexOf("element_") > -1
+                    }).map(function(name) {
+                        return '<option value="' + name + '" ' + (name === tab.type ? 'selected' : '') + '>' + name + '</option>'
+                    }).join("\n") + '</select>',
+                    childrenpath: field.childrenpath,
+                    alinee: types.alineedit(obj, {
+                        path: path.split("/.").pop(),
+                        excludekeys: [field.childrenpath]
+                    }),
+                    mods: _.map((tab.modules || []), function(m, mi) {
+                        return self.template(ta2, {
+                            tab: tab,
+                            path: path,
+                            mod: m,
+                            typeselect: '<select  data-id="' + path + '.modules.' + mi + '.type" class="changetype" >' + _.keys(types).filter(
+                                function(
+                                    name) {
+                                    return name.indexOf("element_") > -1
+                                }).map(function(name) {
+                                return '<option value="' + name + '" ' + (name === m.type ? 'selected' : '') + '>' + name + '</option>'
+                            }).join("\n") + '</select>',
+                            index: mi
+                        })
+                    }).join("\n"),
+                    content: content
+                })
+            })
+        });
+
+    }
+    types.layouteditor_editor = function(obj, field) {
+        var ta1 =
+            `<li data-id="{{path}}" data-prop="{{childrenpath}}">
+            <div class="tool">
+                 <span class="expand"> </span>
+                 <span class="hh"> </span>
+                <button tab-index="-1" data-id="{{path}}.{{childrenpath}}" class="addelement">Add</button>
+                <button tab-index="-1" data-id="{{path}}" class="deletetab">Delete</button>
+                <button tab-index=-1 data-id="{{path}}.modules" class="addmodules" title="Add module">M</button>
+                <input class="mini propeditor" rerender=true data-id="{{path}}.name" value="{{tab.name}}" >
+                <input class="mini propeditor" rerender=true data-id="{{path}}.target" value="{{tab.target}}" >
+ 
+
+            </div>
+            <div class="edi">
+            {{alinee}}
+
+            </div>
+            <ol class="moda" data-id="{{path}}.modules">
+                {{mods}}
+            </ol>
+            <ol class="tubu" data-id="{{path}}.{{childrenpath}}">
+                {{content}}
+            </ol>
+        </li>`;
+        var ta2 =
+            `<li data-id="{{path}}.modules.{{index}}">
+            <div class="tool">
+                <span class="expand"> </span>
+                <span class="hh"> </span>
+                {{xtypeselect}}
+                <span class="deletemod">Delete</span>
+                <div class="title">{{mod.type}}</div>
+
+
+            </div>
+
+
+            <div class="modcon"></div>
+        </li>`;
+        var ta3 =
+            `<div id="nested">
+            <ol class="tibi" data-id="{{obj.path}}/.{{fieldpath}}">
+                {{basecontent}}
+            </ol>
+            <button data-id="{{obj.path}}/.{{fieldpath}}" class="addelement">Add child</button>
+        </div>`;
+
+        function rec_go(arr, prop, path, func, level_) {
+            var level = level_ || 0;
+            return _.map((arr || []), function(a, i) {
+                if (a[prop] && _.isArray(a[prop])) {
+                    return func(a, path + "." + i, rec_go(a[prop], prop, path + "." + i + "." + prop, func, level + 1));
+                } else {
+                    return func(a, path + "." + i)
+                }
+            }).join("\n");
+        }
+        field.childrenpath = "layouts";
+        field.path = "_data.layouts";
+
+        return self.template(ta3, {
+            obj: obj,
+            childrenpath: field.childrenpath,
+            fieldpath: field.path,
+            basecontent: rec_go(opath.get(obj, field.path), field.childrenpath, obj.path + "/." + field.path, function(tab, path, content) {
+                return self.template(ta1, {
+                    tab: tab,
+                    path: path,
+                    typeselect: '<select  data-id="' + path + '.type" class="changetype" >' + _.keys(types).filter(function(name) {
+                        return name.indexOf("element_") > -1
+                    }).map(function(name) {
+                        return '<option value="' + name + '" ' + (name === tab.type ? 'selected' : '') + '>' + name + '</option>'
+                    }).join("\n") + '</select>',
+                    childrenpath: field.childrenpath,
+                    alinee: types.layouttabedit(obj, {
+                        path: path.split("/.").pop()
+                    }),
+                    mods: _.map((tab.modules || []), function(m, mi) {
+                        return self.template(ta2, {
+                            tab: tab,
+                            path: path,
+                            mod: m,
+                            typeselect: '<select  data-id="' + path + '.modules.' + mi + '.type" class="changetype" >' + _.keys(types).filter(
+                                function(
+                                    name) {
+                                    return name.indexOf("element_") > -1
+                                }).map(function(name) {
+                                return '<option value="' + name + '" ' + (name === m.type ? 'selected' : '') + '>' + name + '</option>'
+                            }).join("\n") + '</select>',
+                            index: mi
+                        })
+                    }).join("\n"),
+                    content: content
+                })
+            })
+        });
+    }
+
+
+
+
+
+
+
+    types.breakpoint_editor = function(obj, field) {
+        //  console.log(Object.assign({field: field}, obj ))
+
+        return '<input type="text" value="">'
+
+    }
+
+
+    types.element_ = function(obj, field) {
+        //  console.log(Object.assign({field: field}, obj ))
+        return self.template(field.data, Object.assign({
+            field: field
+        }, obj));
+    }
+    types.element_rows = function() {
+        return self.template(field.data, obj);
+    }
+    types.element_cols = function() {
+        return self.template(field.data, {
+            obj: obj,
+            field: field
+        });
+    }
+    types.element_link = function() {
+        return self.template(field.data, {
+            obj: obj,
+            field: field
+        });
+    }
+    types.element_image = function() {
+        return self.template(field.data, {
+            obj: obj,
+            field: field
+        });
+    }
+
+
+
+    types.thismodules = function(obj, field) {
+        var s = ""
+        s += '<pre>' + _.map(obj._metas.modules, function(mod) {
+            return mod.type + " : " + mod.title;
+        }).join("\n") + '</pre>';
+        s += "<textarea class=dataeditor data-id=\"" + obj.path + "/._metas.modules\">" + self.jsonstringify(obj._metas.modules, true, 2) +
+            '</textarea>'
+        return s;
+    }
+    types.status = function(obj, field) {
+        var aa = []
+        _.keys(self.oo).filter(aa => ["trash", ""].indexOf(aa) === -1 && typeof(self.oo[aa]) === "function").map(function(key) {
+
+            aa = [].concat.apply(aa, allchildren(self.oo[key]()).filter(function(a) {
+                return a._isdirty
+            }))
+        })
+        var s = ""
+
+        s += '<h3>Dirty pages</h3><table><thead><tr><th>Obj</th><th> </th></tr></thead><tbody>' + aa.map(function(a) {
+            return self.template('<tr><td><a href="#{{path}}" class="elecontent" elepath="{{path}}">{{path}}</a></td><td></td></tr>', a)
+        }).join("\n") + '</tbody></table><hr><button onclick="siten.saveZip().then((zzs) => zzs.map((zz) => saveAs(zz.blob, zz.filename)))" class="bnt">Save...</button>';
+
+
+
+        return s
+
+    }
+
+    types.tree = function(obj, field) {
+        return '<pre>' + self.allchildren(field.from ? field.from : undefined).map(function(a) {
+            return _.repeat(" ", a.path.split("/").length) + '<a href="#" elepath="' + a.path + '" class="elecontent ' + (a.path === obj.path ? 'active' : '') +
+                '">' + a.name + '</a>'
+        }).join("\n") + '</pre>';
+    }
+
+
+    types.source = function(obj, field) {
+        var s = "";
+        s += '<textarea id="sourcen">' + self.jsonstringify(obj.innerExport(""), true, 2) + '</textarea>';
+        s += '<hr>'
+
+
+        return s
+    }
+    types.sourcefull = function(obj, field) {
+        var s = "";
+        s += '<textarea id="sourcen">' + self.jsonstringify(obj.exportSync(""), true, 2) + '</textarea>';
+        s += '<hr>'
+
+
+        return s
+    }
+    types.sourcefulla = function(obj, field) {
+        var s = "";
+        s += '<div class="status">Edit</div><hr><textarea id="sourcefulla" data-id="' + obj.path + '">' + self.jsonstringify(obj.exportSync(""), true, 2) + '</textarea>';
+        s += '<hr>'
+        s +=
+            '<div class="upload-btn-wrapper"><button class="btn" onclick="$(\'#myupload\').click()">Upload files</button><input id="myupload" type="file" class="afile" style="opacity: 0;" name="file1" multiple data-id="' +
+            obj.path +
+            '" data-action="browser_handlefilen" data-emit="filesloaded"  /></div> '
+        if (!obj._metas.undeletable) {
+            s += '<li style="float: right;"><button class="zapele" data-id="' + obj.path +
+                '">Delete Permanently</button></li>'
+
+        }
+        return s
+    }
+    types.export = function(obj, field) {
+        var s = "";
+        s += '<h3>' + obj.path + '</h3>';
+        s += '<button onclick="saveAs(new Blob([siten.jsonstringify(siten.oget(\'' + obj.path + '\').exportSync(), true, 2)],{\'type\':\'application/json\'}),\'' + obj.path +
+            '.json\')">Save as</button>'
+        s += '<hr><button onclick="$(\'#exporta\').val(siten.jsonstringify(siten.oget(\'' + obj.path +
+            '\').exportSync(), true, 2))">Export Standard</button><button onclick="$(\'#exporta\').val(siten.jsonstringify(siten.oget(\'' + obj.path +
+            '\').exportFlatSync(), true, 2))">Export flat</button>' +
+            " Export size: " + ((self.jsonstringify(obj.exportSync("")).length / (1024 * 1024)).toFixed(2) + "mb");
+
+        s += '<textarea id="exporta">' + '</textarea>';
+        s += '<hr>'
+
+
+        return s
+    }
+    types.globalexport = function(obj, field, run) {
+
+        if (run) {
+
+            var s = "";
+            s += '<table><thead><tr><th>Path</th><th>Bytes</th></tr></thead><tbody>' + _.filter(self.oo, function(a) {
+                return typeof(a) === "function"
+            }).map(function(a) {
+                return a()
+            }).map(function(a) {
+                return '<tr><td>' + a.path + '</td><td>' + ((self.jsonstringify(a.exportSync("")).length / (1))) +
+                    '</td><td><button onclick="saveAs(new Blob([siten.jsonstringify(siten.oget(\'' + a.path +
+                    '\').exportSync(), true, 2)],{\'type\':\'application/json\'}),\'' + a.path + '.json\')">Save as</button></td></tr>'
+            }).join("\n") + '</tbody></table>';
+            s += '<textarea id="exportx">' + '</textarea>';
+            return s
+        } else {
+
+            var s = "";
+            s += '<button onclick="$(\'#exportstats\').html(siten.otypes.globalexport({},1))">Calculate</button>';
+            s += '<div id="exportstats">' + '</div>';
+            return s;
+        }
+    }
+    types.clone = function(obj, field) {
+        return "<div class=\"status\"></div> <input type=\"text\" class=cloneeditor data-id=\"" + obj.path + "\" value=\"" + '"> '
+
+    }
+    types.delete = function(obj, field) {
+        return '<li> <button class="deleteele" data-id="' + obj.path + '">Trash</button>  <button class="zapele" data-id="' + obj.path +
+            '">Delete Permanently</button></li>'
+
+    }
+
+    types.keyseditor = function(obj, field) {
+
+
+
+
+    }
+
+
+
+    types.allprops = function(obj, field) {
+
+
+        var stash = [];
+
+        var prot = {}
+        var meta = {}
+        self.allchildren().map(function(c) {
+            var arr = opath.flatten(c._data, "");
+            arr.map(function(a) {
+                prot[a[0]] = prot[a[0]] || {}
+                prot[a[0]][a[1]] = prot[a[0]][a[1]] || 0
+                prot[a[0]][a[1]] += 1;
+            })
+
+            var arr = opath.flatten(c._metas, "");
+            arr.map(function(a) {
+                if (a[0].indexOf('_wp_attachment_backup_sizes') > -1) {
+                    return;
+                }
+                meta[a[0]] = meta[a[0]] || {}
+                meta[a[0]][a[1]] = meta[a[0]][a[1]] || 0
+                meta[a[0]][a[1]] += 1;
+            })
+        });
+        var prota = _.map(prot, function(vala, nama) {
+            return nama + " : " + _.size(vala)
+        });
+        var metas = _.map(meta, function(vala, nama) {
+            return nama + " : " + _.size(vala)
+        });
+
+        stash.push(["Data Properties", '<pre>' + JSON.stringify(prota, true, 2) + '</pre>'])
+        stash.push(["Meta Properties", '<pre>' + JSON.stringify(metas, true, 2) + '</pre>'])
+
+        var ss = ('<div class="stash">' + stash.map(function(a) {
+            return '<div class="stt"><div class="st1">' + (a[0] === false ? "" : a[0] + "") + '</div><div class="st2">' + a[1] + '</div></div>'
+        }).join("\n") + '</div>');
+        return ss
+
+
+
+    }
+    types.jsfuncs = function(obj, field) {
+        var qq = [];
+        _.map(_.omit(obj, ignores), function(val, prop) {
+            if (typeof(val) === "function") {
+                qq.push(["JS " + prop + '<li><button class="deletefunc" data-id="' + obj.path + "/." + prop + '">Delete</button></li>',
+                    "<div class=\"status\"></div> <textarea class=jseditor data-id=\"" + obj.path + "/." + prop + "\">" + (obj[prop] + "") +
+                    '</textarea> '
+                ]);
+
+            }
+        })
+        qq.push(["JS ", "<input class=\"createfunc\"   data-id=\"" + obj.path + "\"> "]);
+
+        var ss = ('<div class="sas">' + qq.map(function(a) {
+            return '<div class="sa"><div class="inn"><div class="saa">' + (a[0] === false ? "" : a[0] + "") + '</div><div class="sab">' + a[1] +
+                '</div></div></div>'
+        }).join("\n") + '</div>');
+        return ss
+
+
+    }
+    types.relations = function(obj, field) {
+        var s = "";
+
+        var ss = []
+        _.map(obj._relations, function(rels, relname) {
+            var relators = _.keys(rels);
+            var sss = relators.slice(0, 25).map(function(relator) {
+                return '<li elepath="' + relator + '"><a href="#' + relator + '" class="elecontent" title="' + JSON.stringify(rels[relator].context).toHtmlEntities() +
+                    '">' + relator + '</a>  <button class="btn unrelate" data-id="' + obj
+                    .path + '" data-rel="' + relname + '" data-rela="' + relator + '" >X</button></li> '
+
+            }).join("\n");;
+            ss.push([relname + "(" + relators.length + ")", sss]);
+        });
+        s += ss.map(function(a) {
+            return '<div><h3>' + a[0] + '</h3><div>' + a[1] + '</div></div>'
+
+        }).join("\n")
+
+
+        return s;
+    }
+    types.relationsadd = function(obj, field) {
+        var s = "";
+
+
+        s += '<li class="relationseditor" data-id="' + obj.path +
+            '"><input class="relout" type="text" placeholder="is what " /><em><select  class=uniq_relnames target=".relout"></select>' +
+            '</em><hr> to: <input class="relaeditor" placeholder="find obj"><hr> as: <input type="text" class=relin data-id="' +
+            obj.path +
+            '" placeholder="as what " /> <select  class=uniq_relnames target=".relin"></select><hr> with: <input class="what" type="text" > <button class="relateasto">Relate</button></li>';
+        return s;
+    }
+    types.templatepaths = function(obj, field) {
+        return "<div class=\"status\"></div>" + _.map(self.getRenderTemplate(obj), function(a) {
+            return '<li elepath="' + a.name + '"  ><a href="#' + a.name + '" class="elecontent" title="' + a.from + ": " + a.data.toHtmlEntities() + '" > ' +
+                a.name +
+                '</a></li>'
+        }).join("\n");
+    }
+    types.visa = function(obj, fielda) {
+        var field = Object.assign({
+            "show": {},
+            "cap": 1000
+        }, fielda)
+
+
+
+        setTimeout(function() {
+
+
+            var statusa = document.getElementById('visastatus');
+
+            var colas = {
+                parent: "#000000",
+                child: "#ff00ff",
+                extends: "#00ff00",
+                inherits: "#ff0000",
+                isa: "#ff9900",
+                hasa: "#00ff99"
+            }
+
+            function lokup(tp) {
+                return colas[tp];
+
+            }
+
+
+            var graph = Viva.Graph.graph();
+            var graphics = Viva.Graph.View.svgGraphics(),
+                nodeSize = 10;
+
+            var oba = obj; // obj.parents[_.keys(obj.parents).shift()] || obj;
+
+
+
+            var alle = allchildren(oba).filter(function(c) {
+                return true //c.path.indexOf("trash/") === -1 && c.path.indexOf("folders/") === -1 && c.path.indexOf("blobs/") === -1
+            });
+
+
+            /*                alle.slice(0,2).map(addobj);
+
+                            setTimeout(function(){
+                            alle.slice(2,20).map(addobj);
+
+                            },2000)
+            */
+            /*            
+                            if(alle.length>0){
+                                stepa();
+                            }
+            */
+            var cols = [];
+
+            alle.map(addobj);
+
+            if (obj.parents[_.keys(obj.parents).shift()]) {
+                addobj2(obj.parents[_.keys(obj.parents).shift()]);
+                cols.unshift([obj.path, _.keys(obj.parents).shift(), "child of"])
+            }
+
+            var colsori = cols.length;
+
+            if (cols.length > field.cap) {
+                cols = cols.slice(0, field.cap);
+                //	cols = cols.filter(function(a){return a[2] !== "isa" })
+                //  	cols = cols.filter(function(a){return a[2] !== "child" })
+                //  	cols = cols.filter(function(a){return a[2] !== "hasa" })
+
+            }
+
+            function stepa() {
+                statusa.innerHTML = ' ' + alle.length + " : " + colsori + " " + field.cap + " " + cols.length;
+                var i = 0,
+                    c;
+                while (i < 10 && cols.length > 0) {
+                    i++
+                    c = cols.shift();
+                    graph.addLink(c[0], c[1], c[2])
+                }
+                if (cols.length > 0) {
+                    setTimeout(stepa, 100)
+                } else {
+                    statusa.innerHTML = ' ' + alle.length + " : " + colsori + " " + field.cap + " " + cols.length;
+
+                }
+            }
+
+            stepa()
+
+            function addobj2(c) {
+                // graph.addNode(c.path);
+
+                _.map(c._isa, function(child, name) {
+                    cols.push([c.path, child.path, 'isa'])
+                });
+                _.map(c._hasa, function(child, name) {
+                    cols.push([c.path, child.path, 'hasa'])
+                });
+
+                _.map(c._extends, function(child, name) {
+                    cols.push([c.path, child.path, 'extends'])
+                });
+                _.map(c._inherits, function(child, name) {
+                    cols.push([c.path, child.path, 'inherits'])
+                });
+                _.map(c._relations, function(rels, relname) {
+                    _.map(rels, function(child, name) {
+                        cols.push([c.path, name, relname])
+                    })
+                });
+
+            }
+
+
+
+            function addobj(c) {
+                // graph.addNode(c.path);
+
+                if (field.show.children) {
+                    _.map(c.children, function(child, name) {
+                        cols.push([c.path, child().path, 'child'])
+                    });
+                }
+
+
+                if (field.show.isa) {
+                    _.map(c._isa, function(child, name) {
+                        cols.push([c.path, child.path, 'isa'])
+                    });
+                }
+                if (field.show.hasa) {
+                    _.map(c._hasa, function(child, name) {
+                        cols.push([c.path, child.path, 'hasa'])
+                    });
+                }
+
+                if (field.show.extends) {
+                    _.map(c._extends, function(child, name) {
+                        cols.push([c.path, child.path, 'extends'])
+                    });
+                }
+                if (field.show.inherits) {
+                    _.map(c._inherits, function(child, name) {
+                        cols.push([c.path, child.path, 'inherits'])
+                    });
+                }
+                if (field.show.relations) {
+                    _.map(c._relations, function(rels, relname) {
+                        _.map(rels, function(child, name) {
+                            cols.push([c.path, name, relname + " with " + child.context.d])
+                        })
+                    });
+                }
+            }
+
+
+            var idas = 1;
+            var ida = function() {
+                return "ida" + (idas++)
+            }
+
+            graphics.node(function(node) {
+                var ui = Viva.Graph.svg('g');
+                var circle = Viva.Graph.svg('circle')
+                    .attr('cx', 2)
+                    .attr('cy', 2)
+                    .attr('r', 2)
+                    .attr('fill', obj.path === node.id ? "#ff0000" : "#dadada");
+                ui.append(circle);
+                var svgText = Viva.Graph.svg('text').attr("fill", obj.path === node.id ? "#ff0000" : "#333333").attr('font-size', obj.path === node.id ? "18px" :
+                    "12px").attr('y', '4px').text(node.id.split("/").slice(-2).join("/"));
+                ui.append(svgText);
+                return ui;
+            }).placeNode(function(nodeUI, pos) {
+                nodeUI.attr('transform',
+                    'translate(' +
+                    (pos.x - nodeSize / 2) + ',' + (pos.y - nodeSize / 2) +
+                    ')');
+            });
+            var createMarker = function(id) {
+                    return Viva.Graph.svg('marker')
+                        .attr('id', id)
+                        .attr('viewBox', "0 0 10 10")
+                        .attr('refX', "10")
+                        .attr('refY', "5")
+                        .attr('markerUnits', "strokeWidth")
+                        .attr('markerWidth', "10")
+                        .attr('markerHeight', "5")
+                        .attr('orient', "auto");
+                },
+
+                marker = createMarker('Triangle');
+            marker.append('path').attr('d', 'M 0 0 L 10 5 L 0 10 z');
+
+            // Marker should be defined only once in <defs> child element of root <svg> element:
+            var defs = graphics.getSvgRoot().append('defs');
+            defs.append(marker);
+
+            var geom = Viva.Graph.geom();
+
+            graphics.link(function(link) {
+                // Notice the Triangle marker-end attribe:
+
+                var isParent = (link.data === 'parent');
+
+                var ui = Viva.Graph.svg('g');
+                var p = Viva.Graph.svg('path')
+                    .attr('stroke', lokup(link.data) || "#000000")
+                    .attr('fill', 'none')
+                    .attr('marker-end', 'url(#Triangle)')
+                    .attr('id', ida())
+                ui.isParent = isParent; // remember for future.
+                ui.linka = link.data;
+                ui.ry = 50 //- (Math.random() * 100);
+
+                ui.pp = p;
+
+
+
+                var svgText = Viva.Graph.svg('text').attr("dy", -4).attr("class", "slabel");
+
+                var textPath = Viva.Graph.svg("textPath");
+                textPath.attr("href", "#" + p.id).attr("startOffset", "25%").text(link.data + " >");
+
+                svgText.append(textPath)
+                ui.tt = svgText;
+
+                ////<textPath xlink:href="#'+link.id+'">
+
+                //                    svgText.attr('xlink', link.id);
+
+
+                ui.append(svgText)
+
+                ui.append(p);
+
+                return ui;
+
+
+            }).placeLink(function(linkUI, fromPos, toPos) {
+                // using arc command: http://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
+                //var data = 'M' + fromPos.x + ',' + fromPos.y +
+                //  ' A 4,' + linkUI.ry + ',-' + linkUI.ry + ',0,1,' + toPos.x + ',' + toPos.y;
+
+                var data = 'M' + fromPos.x + ',' + fromPos.y +
+                    ' C ' + (fromPos.x + 50) + ' ' + (fromPos.y + 10) + ',' + (toPos.x - 50) + ' ' + (toPos.y - 10) + ',' + toPos.x + ' ' + toPos.y;
+
+
+
+                linkUI.pp.attr("d", data);
+
+                return;
+                //  linkUI.tt.attr("y", ((fromPos.y + toPos.y) / 2) - linkUI.ry);
+                // linkUI.tt.attr("x", ((fromPos.x + toPos.x) / 2) );
+
+
+
+
+            });
+
+
+
+            var layout = Viva.Graph.Layout.forceDirected(graph, {
+                springLength: 80,
+                springCoeff: 0.00001,
+                dragCoeff: 0.001,
+                gravity: -1.2
+            });
+
+
+
+
+            var renderer = Viva.Graph.View.renderer(graph, {
+                graphics: graphics,
+                container: document.getElementById('visagraf'),
+                layout: layout
+            });
+            renderer.run();
+        }, 200);
+        return '<div id="visastatus" >xxxx</div><div id="visagraf" class="svga"></div>'
+    }
+    types.visa.help = "Shows linked visualization of obj";
+    types.visa.settings = {
+        "cap": {
+            default: 500,
+            "info": "Max render object"
+        },
+        "show": {}
+    };
+
+
+
+
+
+    types.meta = function(obj, field) {
+        return "<div class=\"status\"></div> <textarea class=dataeditor data-id=\"" + obj.path + "/._metas\">" + self.jsonstringify(obj._metas, true, 2) + '</textarea>'
+    }
+    types.data = function(obj, field) {
+        return "<div class=\"status\"></div> <textarea class=dataeditor data-id=\"" + obj.path + "/._data\">" + self.jsonstringify(obj._data, true, 2) + '</textarea>'
+    }
+    types.hasas = function(obj, field) {
+        return '<div class="hasas">' + _.map(obj._hasa, function(tob, name) {
+            return self.template(
+                '<li elepath="{{tob.path}}" pelepath="{{obj.path}}" ><a href="#{{name}}" class="elecontent">{{name}}</a> <button class="btn unhasa">X</button></li>', {
+                    tob: tob,
+                    obj: obj,
+                    name: name
+                });
+        }).join("\n") + '</div>'
+    }
+    types.isas = function(obj, field) {
+        return '<div class="isas">' + _.map(obj._isa, function(tob, name) {
+            return self.template(
+                '<li elepath="{{tob.path}}" pelepath="{{obj.path}}" ><a href="#{{name}}" class="elecontent">{{name}}</a> <button class="btn unisa">X</button></li>', {
+                    tob: tob,
+                    obj: obj,
+                    name: name
+                });
+        }).join("\n") + '</div>' + self.template('<input class=isaeditor data-id="{{obj.path}}" placeholder="find isas here.." />', {
+            obj: obj
+        });
+    }
+    types.extends = function(obj, field) {
+        return '<div class="extends">' + _.map(obj._extends, function(tob, name) {
+            return self.template(
+                '<li elepath="{{tob.path}}" pelepath="{{obj.path}}" ><a href="#{{name}}" class="elecontent">{{name}}</a> <button class="btn unextend">X</button></li>', {
+                    tob: tob,
+                    obj: obj,
+                    name: name
+                });
+        }).join("\n") + '</div>' + self.template('<input class=extendeditor data-id="{{obj.path}}" placeholder="find inheritants here.." />', {
+            obj: obj
+        });
+    }
+    types.inherits = function(obj, field) {
+        return '<div class="inherits">' + _.map(obj._inherits, function(tob, name) {
+            return self.template(
+                '<li elepath="{{tob.path}}" pelepath="{{obj.path}}" ><a href="#{{name}}" class="elecontent">{{name}}</a> <button class="btn uninherit">X</button></li>', {
+                    tob: tob,
+                    obj: obj,
+                    name: name
+                });
+        }).join("\n") + '</div>' + self.template('<input class=inheriteditor data-id="{{obj.path}}" placeholder="find extenders here.." />', {
+            obj: obj
+        });
+
+    }
+    types.children = function(obj, field) {
+        var s = '';
+        s += mmb("Add child", "<input type=\"text\" class=addchildeditor data-id=\"" + obj.path + "\" value=\"" + '"> ');
+
+        s += '<div class="children">' + _.map(obj.children, function(a) {
+            return a().path
+        }).map(function(k) {
+            return '<li elepath="' + k + '" pelepath="' + obj.path + '"><a href="#' + k + '" class="elecontent" > ' + k +
+                '</a>  '
+        }).join("\n") + '</div>'
+        return s;
+    }
+    types.parents = function(obj, field) {
+        return self.template('{{parents::}}', obj);
+    }
+    types.path = function(obj, fiels) {
+        return "<input type=\"text\" class=patheditor data-id=\"" + obj.path + "\" value=\"" + obj.path + '">';
+    }
+    types.info = function(obj, field) {
+        return "Path:  " + obj.path
+    }
+    types.upload = function(obj, field) {
+        return (
+            '<div class="upload-btn-wrapper"><button class="btn" onclick="$(\'#myupload\').click()">Upload files</button><input id="myupload" type="file" class="afile" style="opacity: 0;" name="file1" multiple data-id="' +
+            obj.path +
+            '" data-action="browser_handlefilen" data-emit="filesloaded"  /></div> ');
+    }
+    types.content = function(obj, field) {
+        var content_type = "<div><input type=\"text\" class=propeditor data-id=\"" + obj.path + "/._metas.type\" value=\"" +
+            obj._metas.type +
+            '">' + "<select  class=propselector data-id=\"" + obj.path + "/._metas.type\"></select></div>";
+        var s = '';
+
+        s += mmb("Title", types.propeditor(obj, {
+            "path": "_data.title"
+        }))
+
+        if (obj._metas.type && obj._metas.type == "html") {
+            s += mmb("Content", "<div class=\"adj\"><div class=\"status\"></div> <textarea class=mceeditor data-id=\"" + obj.path + "/._data.content\">" + obj._data.content +
+                '</textarea></div>')
+        } else {
+            s += mmb("Body", "<div class=\"adj\"><div class=\"status\"></div> <textarea class=htmleditor data-id=\"" + obj.path + "/._data.content\">" + obj._data.content +
+                '</textarea></div>')
+        }
+        s += mmb("Type", content_type);
+        return s;
+    }
+    types.truefalse = function(obj, field) {
+        return ' <input type="checkbox" class="truefalse" data-id="' + obj.path + '/.' + field.path + '" ' + (opath.get(obj, field.path) ? 'checked' : '') + '>'
+    }
+    types.position = function(obj, field) {
+        return ' <input type="text" class="propeditor" data-id="' + obj.path + '/.' + field.path + '" value="' + opath.get(obj, field.path) + '">'
+    }
+    types.rootzip = function(obj, field, run) {
+        if (run == 1) {
+            var ns = self.oget("namespace")._data;
+            var arr = _.filter(self.oo, function(a, k) {
+                return typeof(a) === "function" && k !== "namespace"
+            }).map(function(a) {
+                return a()
+            });
+            var s = "";
+            var total = 0;
+            var totallc = 0;
+            s +=
+                '<table><thead><tr><th class="path">Path</th><th class="filename">Filename</th><th class="nn">Objs</th><th class="nn">Bytes</th><th class="nn">Avg</th></tr></thead><tbody>' +
+                arr.map(function(a) {
+                    var ll = ((self.jsonstringify(
+                        a.exportSync("")).length / (1)));
+                    var lc = (a.exportFlatSync().length);
+                    total += ll;
+                    totallc += lc;
+                    return '<tr> <td class="path">' + a.path + ((ns.linked && ns.linked[a.path + ".link"] ? '*' : '')) + '</td><td  class="filename">' + a.path +
+                        '.json</td><td class="nn">' + lc + '</td><td class="nn">' + ll +
+                        '</td><td class="nn">' + (ll / lc).toFixed(2) + '</td></tr>'
+                }).join("\n")
+            s += '<tr> <td> </td><td> </td><td class="nn">' + totallc + '</td><td class="nn">' + total + '</td><td class="nn">' + (total / totallc).toFixed(2) +
+                '</td></tr>'
+            s += '</tbody></table>';
+            s += '<hr>Output</h3>';
+            s += '<button onclick="$(\'#rootzipresult\').html(siten.otypes.rootzip({},2))">Calculate zip</button>';
+            s += '<div id="rootzipresult"></div>'
+            return s;
+        } else if (run == 2) {
+            self.saveZip().then(function(files) {
+                var ss = '<table><thead><tr>  <th class="filename">Filename</th> <th class="nn">Size</th> <th class="nn"></th><th class="nn"></th></thead><tbody>' +
+                    files.map(function(file) {
+                        return '<tr> <td>' + file.filename + '</td> <td class="nn">' + file.blob.size + '</td> <td class="nn"></td> <td class="nn"></td>  </tr>';
+                    }).join("\n") + '</tbody></table>';
+                $("#rootzipresult").html(ss)
+            })
+            return 'zipping...'
+        } else {
+            var s = "";
+            s += '<button onclick="$(\'#rootzipstats\').html(siten.otypes.rootzip({},1))">Calculate</button>';
+            s += '<div id="rootzipstats">' + '</div>';
+            return s;
+        }
+    }
+    types.yearmonth = function(obj, field) {
+        var s = "";
+        s += '<input class="propeditor" data-id="' + obj.path + '/.' + field.path + '" value="' + opath.get(obj, field.path) + '">'
+        return s
+    }
+    types.checkboxes = function(obj, field) {
+        return '<h3>' + field.title + '</h3><table>' + _.map(opath.get(obj, field.path), function(val, key) {
+
+            return '<tr><td>' + key + '</td><td>' + types.truefalse(obj, {
+                path: field.path + "." + key
+            }) + '</td></tr>';
+
+        }).join("\n") + '</table>';
+    }
+
+    types.elements = function(obj, field) {
+        return '<table>' + _.map(opath.get(obj, field.path), function(val, key) {
+
+            return '<tr><td>' + key + '</td><td>' + types.truefalse(obj, {
+                path: field.path + "." + key + ".visible"
+            }) + '</td><td>' + types.position(obj, {
+                path: field.path + "." + key + ".x"
+            }) + '</td><td>' + types.position(obj, {
+                path: field.path + "." + key + ".y"
+            }) + '</td></tr>';
+
+        }).join("\n") + '</table>';
+
+    }
+    types.template = function(obj, field) {
+        return "<textarea class=htmleditor data-id=\"" + obj.path + "/._data.template\">" + obj._data.template +
+            '</textarea>'
+    }
+    types.dataeditor = function(obj, field) {
+        var s = "";
+        s += '<textarea class="dataeditor" data-id="' + obj.path + '/.' + field.path + '">' + self.jsonstringify(opath.get(obj, field.path), true, 2) + '</textarea>'
+        return s
+    }
+    types.dataeditorarray = function(obj, field) {
+        var s = "";
+        s += '<textarea class="dataeditorarray" data-id="' + obj.path + '/.' + field.path + '">' + (opath.get(obj, field.path) || []).join("\n") + '</textarea>'
+        return s
+    },
+    types.texteditor = function(obj, field) {
+        var s = "";
+        s += '<textarea class="htmleditor" data-id="' + obj.path + '/.' + field.path + '">' + opath.get(obj, field.path) + '</textarea>'
+        return s
+    }
+    types.namespaceedit = function(obj, field) {
+        var s = "";
+        s += '<input class="namespaceedit" value="' + self.name + '">'
+        return s
+    }
+    types.propeditor = function(obj, field) {
+        var s = "";
+        s += '<input class="propeditor" data-id="' + obj.path + '/.' + field.path + '" value="' + opath.get(obj, field.path) + '">'
+        return s
+    }
+
+    function sort_by_1_col_alpha(a, b) {
+        var x = a[0].toLowerCase(),
+            y = b[0].toLowerCase();
+        return x < y ? -1 : x > y ? 1 : 0;
+    }
+
+    function xflatten(obj, pre) {
+        var pre = pre || "";
+        var r = [];
+        for (var i in obj) {
+            if (typeof(obj[i]) === "object") {
+                r = r.concat(xflatten(obj[i], (pre.length > 0 ? pre + "." : "") + i));
+            } else {
+                r.push([(pre.length > 0 ? pre + "." : "") + i, obj[i]]);
+
+            }
+
+        }
+        r.sort(sort_by_1_col_alpha)
+        return r;
+
+
+    }
+
+    types.advpropeditor = function(obj, field) {
+        var sa = "";
+        var oa = opath.get(obj, field.path);
+
+        function rrr(oo, key, path) {
+            var s = "";
+            if (_.isArray(oo)) {
+                s += '<ul>' + _.map(oo, function(val, key) {
+                    return rrr(val, key, path + "." + key);
+                }).join("\n") + '</ul>';
+            } else if (_.isObject(oo)) {
+
+                s += '<ol>' + _.map(oo, function(val, key) {
+                    return rrr(val, key, path + "." + key);
+                }).join("\n") + '</ol>';
+
+            } else if (_.isBoolean(oo)) {
+                s += '<li>' + key + ":" + types.truefalse(obj, {
+                    path: path
+                }) + '</li>';
+
+            } else if (_.isString(oo)) {
+                s += '<li>' + key + ":" + '<input type="text" value="' + oo + '"></li>';
+
+            }
+            return s;
+        }
+
+        //        var ss = rrr(oa, "", obj.path + "/." + field.path);
+
+        /*        var tt = xflatten(oa, "_metas");
+
+        var ss = tt.map(function(a) {
+            var prop = a[0];
+            var val = a[1];
+            var type =  typeof(val);
+
+            if(type==="boolean"){
+                    return '<li>'+prop+' <input type="checkbox" class="truefalse" data-id="' +obj.path+"/."+prop+ '" ' + (val ? 'checked' : '') + '></li>'
+            }
+
+            if(type==="string"){
+                    return '<li>'+prop+' <input type="text" class="propeditor" data-id="' +obj.path+"/."+prop+ '" value="' + val + '"></li>'
+            }
+        }).join("\n");
+
+        */
+
+        /*
+                _metas.modules = []
+                _metas.tabs = []
+                _metas.fields  = [];
+                
+        
+
+            */
+
+
+
+        var ss = "";
+
+
+        //s += '<input class="propeditor" data-id="' + obj.path + '/.' + field.path + '" value="' + opath.get(obj, field.path) + '">'
+        return ss
+    }
+
+    types.lookup = function(obj, field) {
+        var temps = obj.getStuff3(field.path, function(a) {
+            return a
+        }, field.path)
+        var current_name = "",
+            current_data = "";
+        if (temps.length > 0) {
+            current_name = temps[0].name
+            current_data = temps[0].data;
+        }
+
+        var s = ''; //' <input type="text" data-id="'+obj.path+'/.'+field.path+'" value="' + opath.get(obj,field.path) + '">'
+
+
+
+        var path = opath.get(obj, field.path);
+
+
+        if (current_name !== "" && !path) {
+            path = opath.get(self.oget(current_name), field.path);
+            s += ' inherit <a elepath="' + path + '" href="#' + path + '" class="elecontent" > ' + path + '</a>';
+            s += ' from ' + '<a elepath="' + current_name + '" href="#' + current_name + '" class="elecontent" > ' + current_name + '</a>'
+        } else {
+            if (!path) {
+                s += 'no object selected'
+            } else {
+                s += 'Current: <li> <a elepath="' + path + '" href="#' + path + '" class="elecontent" > ' + path + '</a> <button class="btn unset" data-id="' + obj.path +
+                    '" ele-prop="' + field.path + '">X</button> </li>';
+
+            }
+        }
+
+        s += "<br><input class=\"propselector22\" ele-has=\"" + field.has + "\" ele-list=\"" + field.lookup + "\" ele-pick=\"" + field.pick + "\" data-id=\"" + obj.path +
+            "\" ele-prop=\"" + field.path + "\" >";
+
+
+
+
+        return s;
+    }
+
+    types.lookup2 = function(obj, field) {
+        var temps = obj.getStuff3(field.path, function(a) {
+            return a
+        }, field.path)
+        var current_name = "",
+            current_data = "";
+        if (temps.length > 0) {
+            current_name = temps[0].name
+            current_data = temps[0].data;
+        }
+
+        var s = ''; //' <input type="text" data-id="'+obj.path+'/.'+field.path+'" value="' + opath.get(obj,field.path) + '">'
+        s += "<select class=propselector2 data-has=\"" + field.has + "\" data-list=\"" + field.lookup + "\" data-pick=\"" + field.pick + "\" data-id=\"" +
+            obj.path + "/." +
+            field.path + "\"></select>";
+
+        var path = opath.get(obj, field.path);
+
+
+        if (current_name !== "" && !path) {
+            path = opath.get(self.oget(current_name), field.path);
+            s += ' inherit <a elepath="' + path + '" href="#' + path + '" class="elecontent" > ' + path + '</a>';
+            s += ' from ' + '<a elepath="' + current_name + '" href="#' + current_name + '" class="elecontent" > ' + current_name + '</a>'
+        } else {
+            s += '<a elepath="' + path + '" href="#' + path + '" class="elecontent" > ' + path + '</a>';
+        }
+
+        return s;
+    }
+
+
+
+
+    return types;
+
+
+}

Різницю між файлами не показано, бо вона завелика
+ 801 - 194
index.js


+ 2251 - 0
index2.js

@@ -0,0 +1,2251 @@
+var EventEmitter = require("events").EventEmitter;
+
+var opath = require("opath");
+var async = require("async");
+
+var tool = require("tools2")();
+
+var getthezip = require("libs/getthezip");
+var unpackzip = require("libs/unpackzip");
+var generatezip = require("libs/generatezip");
+var random = require("sharedkey-thing").randoma(0xbadebabe)("#CHANGE BEFORE CHRISTMAS#");
+var _ = require("lodash");
+var templates = require("./templates");
+
+var ignores =
+    "_created _data _events _extends _hasa _inherits _isa _maxListeners _metas _references _relations _rootname addListener children data data2 domain emit emita emitas eventNames export export2 exportFlatSync exportSerialised exportSync exporta extends getMaxListeners getStuff getStuff2 getStuff3 inherits innerExport isa listenerCount listeners metas metas2 metas3 name on once parents path pickdeep pingup prependListener prependOnceListener rawListeners relatesAsToWith removeAllListeners removeListener setMaxListeners test unextends uninherits unisa withAll withAllSync"
+    .split(" ");
+
+function template_helpers(self) {
+    return {
+        "toTextArea": function(str) {
+            return '<textarea>' + str + '</textarea>'
+        },
+        "toWrap": function(str, tag, attr) {
+            return '<' + tag + ' ' + attr + '>' + str + '</' + tag + '>';
+        },
+        toLowerCase: function(str) {
+            return str.toLowerCase();
+        },
+        toUpperCase: function(str) {
+            return str.toUpperCase();
+        },
+        "pagecontent": function(obj) {
+            console.log("pagecontent", obj, arguments);
+            return self.template(obj._data.content, obj);
+        },
+        "siblings": function(obj) {
+            return [_.keys(obj.parents).shift()].map(function(parentpath) {
+                var ares = _.map(obj.parents[parentpath] ? obj.parents[parentpath].children : [], function(a) {
+                    return a();
+                })
+                ares.sort(sorter(function(a) {
+                    return a._metas.menu_order || 100
+                }, -1));
+                var ss = _.map(ares, function(child, name) {
+                    return child.path
+                });
+                if (ss.length > 12) {
+                    var cindex = ss.indexOf(obj.path);
+                    cindex = cindex < 6 ? 6 : cindex;
+                    var spp = _.map(ares, renderlin(obj))
+                    var sasa = [].concat(spp.slice(cindex - 6, cindex + 7))
+                } else {
+                    var sasa = _.map(ares, renderlin(obj))
+                }
+                return sasa.join("\n")
+            }).join("\n")
+        },
+        "parents": function(obj, ss_, sss_) {
+            if (typeof(ss_) !== "undefined" && typeof(sss_) !== "undefined") {
+                return gpath(obj, []).slice(parseInt(ss_), parseInt(sss_)).map(function(p, i) {
+                    return '<a href="#' + p + '" elepath="' + p + '" class="ele elecontent button button-rounded button-' + (i == 0 ? 'small' : 'tiny') + ' button-royal">' +
+                        self.oget(p +
+                            "/._data.title", p) + '</a>';
+                }).join("\n");
+            } else {
+                return gpath(obj, []).slice(1).map(function(p, i) {
+                    return '<a href="#' + p + '" elepath="' + p + '" class="ele elecontent button button-rounded button-' + (i == 0 ? 'small' : 'tiny') + ' button-royal">' +
+                        self.oget(p +
+                            "/._data.title", p) + '</a>';
+                }).join("\n");
+            }
+        },
+        "parent": function(obj) {
+            return _.map(obj.parents, function(par, nam) {
+                self.rendertemplate(par)
+            }).join("\n");
+        },
+        "children2": function(obj) {
+            var ret = [];
+            _.map(obj.children, function(child) {
+                var cho = typeof(child) === "function" ? child() : child;
+                ret.push(self.rendertemplate(cho))
+            })
+            return ret.join("\n")
+        },
+        "children": function(obj) {
+            var ret = [];
+            _.map(obj.children, function(child) {
+                var cho = typeof(child) === "function" ? child() : child;
+                ret.push(renderlin(cho)(cho, cho.name))
+            })
+            return ret.join("\n");
+        },
+        "relations": function(obj) {
+            var stash = [];
+            _.map(obj._relations, function(rels, relname) {
+                var relators = _.keys(rels);
+                var sss = relators.slice(0, 25).map(function(relator) {
+                    return '<li elepath="' + relator + '"><a href="#' + relator + '" class="elecontent" title="' + JSON.stringify(rels[relator].context).toHtmlEntities() +
+                        '">' + relator + '</a> </li> '
+                }).join("\n");;
+                stash.push([relname + "(" + relators.length + ")", sss]);
+            })
+            var ss = ('<div class="stash">' + stash.map(function(a) {
+                return '<div class="stt">  <div class="st1">' + (a[0] === false ? "" : a[0] + "") + '</div><div class="st2">' + a[1] +
+                    '</div> </div>'
+            }).join("\n") + '</div>');
+            return ss
+        },
+        "grandchildren": function(obj) {
+            var ret = [];
+            _.map(obj.children, function(child) {
+                var cho = typeof(child) === "function" ? child() : child;
+                ret = [].concat.apply(ret, _.map(cho.children, renderlin(cho)))
+            })
+            return ret
+        },
+        "created": function(obj) {
+            return obj._created.toJSON();
+        },
+        "_isa": function(obj) {
+            return _.map(obj._isa, renderlin(obj)).join("\n")
+        },
+        "_isa2": function(obj) {
+            return _.map(obj._isa, function(o, n) {
+                return self.rendertemplate(o)
+            }).join("\n")
+        },
+        "_isa3": function(obj, a, b) {
+            console.log(";;;;;;;;;;;", a, b);
+            return _.map(obj._isa, function(o, n) {
+                return self.rendertemplate(o)
+            }).slice(parseInt(a), parseInt(b)).join("\n")
+        },
+        "_hasa": function(obj) {
+            return _.map(obj._hasa, renderlin(obj)).join("\n")
+        },
+        "findall": function(obj, withprop, target_) {
+            var target = target_ || "content";
+            var aa = []
+            _.keys(self.oo).filter(aa => ["trash", "system", ""].indexOf(aa) === -1 && typeof(self.oo[aa]) === "function").map(function(key) {
+
+                aa = [].concat.apply(aa, allchildren(self.oo[key]()).filter(function(a) {
+                    return a._isdirty
+                }))
+            })
+            return aa.map(function(a) {
+                return renderlin2(obj, {
+                    target: target
+                })(a, a.name)
+            }).join("\n");
+        },
+        "jsondata": function(obj) {
+            return JSON.stringify(obj._data, true, 2).toHtmlEntities();
+        }
+    }
+}
+
+function gpath(cc, p) {
+    if (cc.parents) {
+        var k = _.keys(cc.parents).shift();
+        if (k) {
+            return gpath(cc.parents[k], p.concat(cc.path))
+        } else {
+            return p.concat(cc.path)
+
+        }
+    }
+}
+
+function renderlin2(obj, opt) {
+    return function(child, name) {
+        var pp = typeof(child) === "function" ? child() : child;
+        return '<a href="#' + pp.path + '" elepath="' + pp.path + '" eletarget="' + opt.target + '" class="elecontent button button-rounded button-small button-' + (pp.path ==
+                obj.path ? 'royal' : 'inverse') +
+            '">' + (pp._data.title ?
+                pp._data.title : pp.name) +
+            '</a>'
+    }
+}
+
+function renderlin(obj) {
+    return function(child, name) {
+        var pp = typeof(child) === "function" ? child() : child;
+        return '<a href="#' + pp.path + '" elepath="' + pp.path + '" class="elecontent button button-rounded button-small button-' + (pp.path == obj.path ? 'royal' : 'inverse') +
+            '">' + (pp._data.title ?
+                pp._data.title : pp.name) +
+            '</a>'
+    }
+}
+
+
+
+function Asystem(oo) {
+    this.oo = oo;
+    this.name = "noname"
+    this._logs = [];
+    this._linked = {};
+    this._templatefunction = templates(this, template_helpers(this));
+}
+Asystem.prototype.__proto__ = EventEmitter.prototype;
+
+Asystem.prototype.slugger = function(str) {
+    var ret = ("" + str).replace(/\/+/g, '/').replace(/[^\x20-\x7E]/g, '')
+        //  ret=decodeURIComponent(ret);
+    ret = ret.replace(/[\<\>]/g, '')
+    if (ret.indexOf("/") == ret.length - 1) {
+        ret = ret.substring(0, ret.length - 1);
+    }
+    return ret
+}
+
+Asystem.prototype.t_content = function(path) {
+    return this.oget(path)._data.content
+}
+
+Asystem.prototype.odelete = function(path) {
+    var self = this;
+    self.omove(path, "trash/" + path)
+    if (self.oo[path]) {
+        _.map(self.oo[path]().children, function(child, name) {
+            self.odelete(child().path)
+        })
+        delete self.oo[path]
+    }
+    self.emit("deleted", path)
+}
+Asystem.prototype.ozap = function(path) {
+    var t = path.split("/");
+    var ta = t.pop();
+    delete this.oget(t.join("/")).children[ta];
+    this.emit("deleted", path)
+}
+Asystem.prototype.omove = function(path, topath) {
+    var self = this;
+    var newa = self.oget(topath)
+    var olda = self.oget(path);
+    var ss = olda.exportSync();
+    if (!ss) {
+        return false;
+    }
+    ss.name = topath.split("/").pop();
+    ss.path = topath;
+    var np = topath.split("/")
+    np.pop();
+    _.map(olda._relations, function(rels, relsname) {
+        _.map(rels, function(rel, name) {
+            delete rel.ref._relations[rel.context.out]
+        })
+        delete olda._relations[relsname]
+    })
+    _.map(olda._isa, function(isa, name) {
+        delete isa._hasa[name]
+        delete olda._isa[name]
+    })
+    _.map(olda._hasa, function(hasa, name) {
+        delete hasa._isa[olda.path]
+        delete olda._hasa[name]
+    })
+    _.map(olda._inherits, function(inheri, name) {
+        delete inheri._extends[olda.path]
+        delete olda._inherits[name]
+    })
+    _.map(olda._extends, function(extendi, name) {
+        delete extendi._inherits[olda.path]
+        delete olda._extends[name]
+    })
+    _.map(olda.parents, function(par, nam) {
+        delete par.children[olda.name];
+    })
+    _.keys(olda.children, function(key) {
+        delete olda.children[key];
+    })
+    delete olda;
+    self.rev_conv2(ss, np.join("/"));
+    self.emit("moved", path, topath)
+}
+Asystem.prototype.oclone = function(path, topath) {
+    var self = this;
+    var newa = self.oget(topath)
+    var olda = self.oget(path);
+    var ss = olda.exportSync();
+    ss.name = topath.split("/").pop();
+    ss.path = topath;
+    var np = topath.split("/")
+    np.pop();
+    self.rev_conv2(ss, np.join("/"));
+    self.emit("cloned", path, topath)
+}
+Asystem.prototype.oset = function(path_, data) {
+    var self = this;
+    var path = self.slugger(path_);
+    var ar = path.split("/");
+    var first = ar.shift();
+    var prop, obj;
+    if (typeof(self.oo[first]) === "undefined") {
+        self.oo[first] = self.oo(first);
+        self.oo[first]()._isdirty = true;
+        self.emit("rootcreated", self.oo[first]())
+    }
+    if (ar.length > 0 && ar[ar.length - 1].indexOf(".") === 0) {
+        prop = ar.pop().substring(1);
+    }
+    path = ar.join("/")
+    if (path !== "") {
+        var exists = self.ofind(path_);
+        if (exists.remainder !== "") {
+            obj = self.oo[first](path)();
+            self.emit("created1", obj)
+        } else {
+            obj = self.oo[first](path)();
+        }
+    } else {
+        obj = self.oo[first]()
+    }
+    if (prop) {
+        obj._isdirty = true;
+        opath.set(obj, prop, data);
+        //return obj[prop] || getpath(obj, prop)
+        self.emit("changed", obj.path + "/" + prop, data)
+    }
+    return obj;
+}
+Asystem.prototype.ogetsilent = function(path_, alternative) {
+    var self = this;
+    var path = self.slugger(path_);
+    var ar = path.split("/");
+    var first = ar.shift();
+    var prop, obj;
+    if (typeof(self.oo[first]) === "undefined") {
+        self.oo[first] = self.oo(first);
+    }
+    if (ar.length > 0 && ar[ar.length - 1].indexOf(".") === 0) {
+        prop = ar.pop().substring(1);
+    }
+    path = ar.join("/")
+    if (path !== "") {
+        var exists = self.ofind(path_);
+        if (exists.remainder !== "") {
+            obj = self.oo[first](path)();
+        } else {
+            obj = self.oo[first](path)();
+        }
+    } else {
+        obj = self.oo[first]()
+    }
+    if (prop) {
+        return obj[prop] || opath.get(obj, prop) || alternative;
+    }
+    return obj;
+}
+Asystem.prototype.oget = function(path_, alternative) {
+    var self = this;
+    var path = self.slugger(path_);
+    var ar = path.split("/");
+    var first = ar.shift();
+    var prop, obj;
+    if (typeof(self.oo[first]) === "undefined") {
+        self.oo[first] = self.oo(first);
+        self.oo[first]()._isdirty = true;
+        self.emit("rootcreated", self.oo(first)())
+    }
+    if (ar.length > 0 && ar[ar.length - 1].indexOf(".") === 0) {
+        prop = ar.pop().substring(1);
+    }
+    path = ar.join("/")
+    if (path !== "") {
+        var exists = self.ofind(path_);
+        if (exists.remainder !== "" && exists.remainder.indexOf("/") > -1) {
+            obj = self.oo[first](path)();
+            obj._isdirty = true;
+            self.emit("created2", obj)
+        } else {
+            obj = self.oo[first](path)();
+        }
+    } else {
+        obj = self.oo[first]()
+    }
+    if (prop) {
+        return obj[prop] || opath.get(obj, prop) || alternative;
+    }
+    return obj;
+}
+Asystem.prototype.getele = function(action) {
+    var self = this;
+    action = self.slugger(action);
+    var a = action.split("/");
+    var roo = a.shift();
+    var ffu;
+    if (a[a.length - 1].indexOf(".") > -1) {
+        //function call;
+        ffu = a.pop().split(".").pop();
+    } else {
+        //straight
+    }
+    var name = a.join("/");
+    var eles = self.oo[roo](name)();
+
+    if (ffu && eles[ffu]) {
+        return {
+            ele: eles,
+            func: eles[ffu]
+        };
+    }
+    return {
+        ele: eles
+    }
+
+}
+Asystem.prototype.ofind = function(path) {
+    /* returns  {found: "spath"|false , remainder: "rest"|"" , obj: obj}*/
+    var self = this;
+    path = self.slugger(path);
+    var ar = path.split("/");
+    var first = ar.shift();
+    if (typeof(self.oo[first]) === "undefined") {
+        return {
+            found: false
+        }
+    } else {
+        var pa = self.oo[first]()
+        var ch = "";
+        var rest = [];
+        while (ar.length) {
+            ch = ar.shift();
+            if (pa.children[ch]) {
+                pa = pa.children[ch]();
+            } else {
+                rest.push(ch)
+            }
+        }
+        return {
+            found: pa.path,
+            /* is false if not found*/
+            remainder: rest.join("/"),
+            /* is not "" if not found rest of path*/
+            obj: pa /* the found object*/
+        }
+    }
+}
+Asystem.prototype.rev_conv = function(obj, path) {
+    if (typeof(obj) !== "object" || obj == null) {
+        return false;
+    }
+    var self = this;
+    var zzz = self.ogetsilent(obj.path);
+    zzz.data(obj.data)
+    zzz._created = new Date(obj.created);
+
+    zzz.metas(obj.meta);
+
+    if (_.size(obj.rel) > 0) {
+        _.map(obj.rel, function(rels, name) {
+            _.map(rels, function(dats, relator) {
+                if (name === dats.in) {} else {
+                    // console.log("RR:  ", obj.path, relator, name, dats.in, dats.out);
+                    zzz.relatesAsToWith(dats.out, self.ogetsilent(relator), dats.in, dats)
+                }
+            })
+        })
+    }
+    if (obj.inherits && obj.inherits.length) {
+        obj.inherits.map(function(alp) {
+            zzz.inherits(self.ogetsilent(alp))
+        })
+    }
+    if (obj.extends && obj.extends.length) {
+        obj.extends.map(function(alp) {
+            zzz.extends(self.ogetsilent(alp))
+        })
+    }
+    if (obj.isa && obj.isa.length) {
+        obj.isa.map(function(alp) {
+            zzz.isa(self.ogetsilent(alp))
+        })
+    }
+    if (obj.hasa && obj.hasa.length) {
+        obj.hasa.map(function(alp) {
+            self.ogetsilent(alp).isa(zzz)
+        })
+    }
+    _.map(_.omit(obj, ["getStuff3", "name", "hasa", "meta", "data", "parents", "children", "path", "_rootname", "created", "rel", "inherits", "extends", "isa", "children",
+            "_isdirty"
+        ]),
+        function(
+            val,
+            ke) {
+            if (typeof(val) === "string" && val.indexOf("$$$FUNCTION$$$") === 0) {
+                if (zzz._metas && zzz._metas.protected && zzz._metas.protected[ke]) {} else {
+                    var ttt = {};
+                    try {
+                        eval("(function(tt){ tt.func = " + val.split("$$$FUNCTION$$$").pop() + ";})(ttt)");
+                        zzz[ke] = ttt.func;
+                    } catch (ea) {
+                        console.log("error func: ", ea)
+                    }
+                }
+            } else {
+                if (typeof(val) === "object") {
+                    var r = {}
+                    _.map(val, function(v, kp) {
+                        if (typeof(v) === "string" && v.indexOf("$$$FUNCTION$$$") === 0) {
+                            var ttt = {};
+                            try {
+                                eval("(function(tt){ tt.func = " + v.split("$$$FUNCTION$$$").pop() + ";})(ttt)");
+                                r[kp] = ttt.func;
+                            } catch (ea) {
+                                console.log("error func: ", ea)
+                            }
+                        } else {
+                            r[kp] = v
+                        }
+                    })
+                    zzz[ke] = r;
+                } else {
+                    zzz[ke] = val
+                }
+            }
+        })
+    delete obj._isdirty;
+    if (obj.children && obj.children.length) {
+        obj.children.map(function(child) {
+            self.rev_conv(child)
+        })
+    }
+}
+Asystem.prototype.rev_conv2 = function(obj, path) {
+    var self = this;
+    var zzz = self.ogetsilent(path + "/" + obj.name);
+    zzz.data(obj.data)
+    zzz._created = new Date(obj.created);
+    zzz.metas(obj.meta);
+    if (_.size(obj.rel) > 0) {
+        _.map(obj.rel, function(rels, name) {
+            _.map(rels, function(dats, relator) {
+                if (name === dats.in) {} else {
+                    // console.log("RR:  ", obj.path, relator, name, dats.in, dats.out);
+                    zzz.relatesAsToWith(dats.out, self.ogetsilent(relator), dats.in, dats)
+                }
+            })
+        })
+    }
+    if (obj.inherits && obj.inherits.length) {
+        obj.inherits.map(function(alp) {
+            zzz.inherits(self.ogetsilent(alp))
+        })
+    }
+    if (obj.extends && obj.extends.length) {
+        obj.extends.map(function(alp) {
+            zzz.extends(self.ogetsilent(alp))
+        })
+    }
+    if (obj.isa && obj.isa.length) {
+        obj.isa.map(function(alp) {
+            zzz.isa(self.ogetsilent(alp))
+        })
+    }
+    if (obj.hasa && obj.hasa.length) {
+        obj.hasa.map(function(alp) {
+            self.ogetsilent(alp).isa(zzz)
+        })
+    }
+    _.map(_.omit(obj, ["getStuff3", "name", "hasa", "meta", "data", "parents", "children", "path", "_rootname", "created", "rel", "inherits", "extends", "isa", "children",
+            "_isdirty"
+        ]),
+        function(
+            val,
+            ke) {
+            if (typeof(val) === "string" && val.indexOf("$$$FUNCTION$$$") === 0) {
+                // console.log(val.split("$$$FUNCTION$$$").pop())
+                if (zzz._metas && zzz._metas.protected && zzz._metas.protected[ke]) {} else {
+                    var ttt = {};
+                    try {
+                        eval("(function(tt){ tt.func = " + val.split("$$$FUNCTION$$$").pop() + ";})(ttt)");
+                        zzz[ke] = ttt.func;
+                    } catch (ea) {
+                        console.log("error func: ", ea)
+                    }
+                }
+            } else {
+                if (typeof(val) === "object") {
+                    var r = {}
+                    _.map(val, function(v, kp) {
+                        if (typeof(v) === "string" && v.indexOf("$$$FUNCTION$$$") === 0) {
+                            var ttt = {};
+                            try {
+                                eval("(function(tt){ tt.func = " + v.split("$$$FUNCTION$$$").pop() + ";})(ttt)");
+                                r[kp] = ttt.func;
+                            } catch (ea) {
+                                console.log("error func: ", ea)
+                            }
+                        } else {
+                            r[kp] = v
+                        }
+                    })
+                    zzz[ke] = r;
+                } else {
+                    zzz[ke] = val
+                }
+            }
+        })
+    delete obj._isdirty;
+    if (obj.children && obj.children.length) {
+        obj.children.map(function(child) {
+            self.rev_conv2(child, zzz.path)
+        })
+    }
+}
+
+/*Asystem.prototype.save = function() {
+    var self = this;
+    return new Promise(function(resolve, reject) {
+        $lib.exporter(self, function(err, data) {
+            $lib.generate_thezip(self.name + "-" + $lib.getTimedName() + ".zip",
+                $lib.arrayedToObject(data, "name"), function(err, zz) {
+                    console.log(err);
+                    resolve(zz)
+                })
+        })
+    })
+}
+*/
+
+Asystem.prototype.exporter = function(cb) {
+    var self = this;
+    var obj = self.oo;
+    var stores = _.keys(obj).filter(function(a) {
+        return typeof(obj[a]) === "function"
+    }).map(function(a) {
+        return obj[a]()
+    }).map(function(a) {
+        var da = a.exportSync("");
+        return da
+    });
+    stores.unshift({
+        "name": "namespace.manifest",
+        "data": {
+            "namespace": self.name
+        }
+    })
+    var ret = {}
+    stores.map(function(a) {
+        ret[a.name] = a;
+    })
+    cb(null, ret)
+}
+Asystem.prototype.log = function() {}
+Asystem.prototype.template = function() {
+    return this._templatefunction.apply(this, arguments)
+}
+Asystem.prototype.loadInto = function(url, callback, linked) {
+    var self = this;
+    getthezip(url, function(res) {
+        return res.json()
+    })
+        .then(function(obj) {
+            self.rev_conv(obj);
+            self.restart();
+
+        })
+
+}
+Asystem.prototype.loadZipLocal = function(blob, callback) {
+    var self = this;
+    var importer = self.importer_zip();
+    unpackzip(importer)(blob)
+        .then(
+            function() {
+                self.emit("status", "early ready yes yes")
+                if (self._loadqueue && self._loadqueue.length) {
+                    var ff = self._loadqueue.shift()
+                    self.ozap(importer.path);
+
+                    self.loadZip(ff[1], callback, ff[0]);
+                } else {
+                    if (self.name_imported) {
+                        self.name = self.name_imported;
+                    }
+                    self.ozap(importer.path);
+                    callback(null, self);
+                }
+            }
+    ).catch(console.log)
+}
+Asystem.prototype.loadZip = function(url, callback, linked) {
+    var self = this;
+    if (linked) {
+        self._linked[linked] = url;
+    }
+    getthezip(url)
+        .then(function(data) {
+            self.emit("status", "got data" + data.length)
+            var importer = self.importer_zip();
+            unpackzip(importer)(data)
+                .then(
+                    function() {
+                        self.emit("status", "early ready yes yes")
+                        if (self._loadqueue && self._loadqueue.length) {
+                            var ff = self._loadqueue.shift()
+                            self.ozap(importer.path);
+
+                            self.loadZip(ff[1], callback, ff[0]);
+                        } else {
+                            if (self.name_imported) {
+                                self.name = self.name_imported;
+                            }
+                            self.ozap(importer.path);
+                            callback(null, self);
+                        }
+                    }
+            )
+                .catch(console.log)
+        })
+        .catch(console.log)
+}
+Asystem.prototype.saveZip = function() {
+    var self = this;
+    return new Promise(function(resolve, reject) {
+        self.exporter(function(err, data) {
+            var seperate_save = _.keys(data).filter(function(name) {
+                return self._linked && self._linked[name + ".link"]
+            })
+            var ddata = _.omit(data, seperate_save);
+            seperate_save.map(function(om) {
+                var url = self._linked[om + ".link"].split("/");
+                url.pop();
+                url.push(self.name + "-" + om + ".zip");
+                ddata[om + ".link"] = url.join("/");
+            })
+            generatezip(self.name + "-" + "" + ".zip", ddata, function(err, zz) {
+                async.mapSeries(seperate_save, function(name, next) {
+                    var dda = {};
+                    dda[name] = data[name];
+                    generatezip(self.name + "-" + name + ".zip", dda, next)
+                }, function(err, all) {
+                    all.push(zz);
+                    resolve(all)
+                })
+            })
+        })
+    })
+}
+Asystem.prototype.saveAsJS = function() {
+    var self = this;
+    return new Promise(function(resolve, reject) {
+        self.exporterJS(function(err, data) {
+            var tm = {}
+            _.map(data, function(dat, name) {
+                if (typeof(dat.data) === "object" && dat.data.length) {
+                    tm[name + ".js"] = {
+                        data: dat.data.map(function(a) {
+                            return '$E(' + JSON.stringify(a) + ');'
+                        }).join("\n")
+                    };
+                } else {
+                    tm[name] = {
+                        data: dat.data
+                    };
+                }
+            })
+            generatezip(self.name + "-" + "" + ".zip", tm, function(err, zz) {
+                resolve(zz);
+            })
+            //console.log("TTTT",tm);
+            //            console.log("DDD",data);
+        })
+    })
+}
+Asystem.prototype.exporterJS = function(cb) {
+    var self = this;
+    var obj = self.oo;
+    var stores = _.keys(obj).filter(function(a) {
+        return typeof(obj[a]) === "function"
+    }).map(function(a) {
+        return obj[a]()
+    }).map(function(a) {
+        var da = a.exportFlatSync(a.name);
+        return {
+            name: a.name,
+            data: da
+        }
+    });
+    stores.unshift({
+        "name": "namespace.manifest",
+        "data": {
+            "namespace": self.name
+        }
+    })
+    var ret = {}
+    stores.map(function(a) {
+        ret[a.name] = a;
+    })
+    cb(null, ret)
+}
+Asystem.prototype.importer_zip = function() {
+    var self = this;
+    self.oget("system/emmm").metas("_hide", true);
+    var emname = "system/emmm/a/" + random(0xffffff)
+    var emmm = self.oget(emname);
+    emmm.metas("unsaveable", true);
+    emmm.on("file", function(filename, data) {
+        if (filename.indexOf(".link") > -1) {
+            emmm.emit("link", data);
+            self._loadqueue = self._loadqueue || [];
+            self._loadqueue.push([filename, data])
+            self.emit("status", "gotlink", filename);
+        } else {
+            self.emit("status", "gotfile", filename + " : " + typeof(data) + " : " + data.substring(0, 20));
+            self.oget("folders/" + filename.indexOf("/") > -1 ? filename : "folders/" + filename).data("data", data);
+        }
+    })
+    emmm.on("json", function(filename, data) {
+        self.emit("status", "gotfile", filename);
+        self.rev_conv(data)
+    })
+    emmm.on("namespace", function(data, cont) {
+        self.emit("status", "gotnamespace", data.namespace);
+        self.name_imported = data.namespace;
+        cont();
+    })
+    emmm.on("nonamespace", function(cont) {
+        //self.name = url.split("/").pop().split(".").shift();
+        self.emit("status", "gotnonamespace", self.name);
+        cont();
+    })
+    return emmm
+}
+
+function createnav(rk, key) {
+    return '#' + key;
+}
+$linkstr2 = '<li class="{{liclass}}"><i class="{{iclass}}"></i> <a href="{{href}}" class="eletree">{{title}}</a> <em>{{size}}</em></li>';
+
+function allchildpaths(obj_) {
+    var obj = typeof(obj_) === "function" ? obj_() : obj_;
+    return [].concat.apply([obj.path], _.map(obj.children, allchildpaths))
+}
+
+function allchildren(obj_) {
+    var obj = typeof(obj_) === "function" ? obj_() : obj_;
+    return [].concat.apply([obj], _.map(obj.children, allchildren))
+}
+
+function sorter(prop, dir) {
+    return function(aa, bb) {
+        var a = prop(aa);
+        var b = prop(bb);
+        return a > b ? dir * -1 : a < b ? dir * 1 : 0;
+    }
+}
+Asystem.prototype.t_icon = function(obj) {
+    var self = this;
+    if (obj._data.iconclass) {
+        var dd = self.oget(obj._data.iconclass)._data.data;
+        if (!dd) {
+            return "";
+        }
+        if (dd.indexOf("data:") === 0) {
+
+            return '<i><img src="' + dd + '"></i>';
+        } else {
+            return '<i>' + dd + '</i>';
+
+        }
+    }
+    return "<i> </i>"
+}
+Asystem.prototype.t_title = function(obj) {
+    var self = this;
+    //contexts;
+    return opath.get(obj._data, "title") || obj.name
+}
+
+Asystem.prototype.renderme = function(obj, maxlevels, atlevel, viewa) {
+    var self = this;
+    var ssi = _.size(obj.children);
+    var childas = obj;
+    if (ssi === 1) {
+        var ooj = obj.children[_.keys(obj.children).shift()]()
+        if (ooj._metas.skipme) {
+            childas = ooj;
+        }
+    }
+    var ssia = allchildpaths(obj).length - 1;
+    //(ssi > 0 ? ssi : '') +
+    if (obj._metas.pickchild) {
+        childas = obj.children[obj._metas.pickchild]();
+    }
+    if (obj._metas.pickpath) {
+        childas = self.oget(obj._metas.pickpath);
+    }
+
+    var s = "";
+
+    if (viewa && typeof(viewa) === "function") {
+        s += "" + viewa(obj, atlevel);
+    }
+
+    if (obj._metas._hide) {
+        return "";
+    }
+
+    s += '<div class="obj l' + atlevel + ' ' + (obj._metas.hide ? 'hidden' : '') + '" eleview="menulink" elepath="' + obj.path + '" atlevel="' + atlevel + '">'
+    s += '<a href="#' + obj.path + '" >' + self.t_icon(obj) + self.t_title(obj) + '<em>' + (ssia > 0 ? ssia : '') + '</em></a>'
+    if (atlevel < maxlevels) {
+        if (ssi > 0) {
+            var xxx = _.map(childas.children, function(cc) {
+                return cc()
+            })
+            xxx.sort(sorter(function(a) {
+                return a._metas.menu_order || 100
+            }, -1));
+
+            var aa = xxx.slice(0, 25).map(function(cc) {
+                return self.renderme(cc, maxlevels, atlevel + 1, viewa)
+            }).join("\n")
+            return s + '<div class="children">' + aa + '</div></div>'
+
+
+        } else {
+            return s + '</div>';
+        }
+    } else {
+        return s + '</div>'
+    }
+}
+
+
+Asystem.prototype.render = function() {
+    var self = this;
+    return new Promise(function(resolve, reject) {
+        var rooten = self.oget("root");
+        var ss = [self.template('<div id="{{_data.id}}" class="obj root" eleview="" elepath="">', rooten)];
+        // ss.push('<pre onclick="$lib.toggle_admin()">' + self.oget("root/._data.title") + '</pre><hr>')
+
+
+        /*        var kka = _.keys(self.oo).filter(aa => ["trash", "system", "root"].indexOf(aa) === -1 && typeof(self.oo[aa]) === "function")
+        kka.sort(function(aa, bb) {
+            var a = self.oo[aa]()._metas.menu_order;
+            var b = self.oo[bb]()._metas.menu_order;
+            return a > b ? 1 : a < b ? -1 : 0
+        })
+*/
+
+        var kkas = _.filter(self.oo, function(sto) {
+            return typeof(sto) === "function"
+        }).map(function(sto, nam) {
+            return sto();
+        })
+
+        kkas.sort(sorter(function(a) {
+            return a._metas.menu_order || 100
+        }, -1));
+
+        var privates = [];
+        var publics = [];
+
+        kkas.filter(function(obj) {
+            return obj._metas.public !== true
+        }).map(function(obj) {
+            privates.push(self.rendera("menulink", obj, 0, 0));
+        })
+        kkas.filter(function(obj) {
+            return obj._metas.public === true
+        }).map(function(obj) {
+            publics.push(self.rendera("menulink", obj, 2, 0));
+        })
+
+
+        publics.map(function(a) {
+            ss.push(a);
+        })
+
+        /*        kka.map(function(key) {
+            ss.push(self.rendera("menulink", self.oo[key](), 0, 0));
+        })
+*/
+        ss.push('</div>')
+
+        ss.push('<div id="editorlinks">');
+
+        ss.push('<div id="mmme" class="obj root" eleview="" elepath="">');
+
+        privates.map(function(a) {
+            ss.push(a);
+        })
+        ss.push('</div>');
+
+
+
+        ss.push('</div>')
+        resolve(ss.join("\n"));
+    })
+
+
+}
+Asystem.prototype.render_editorlinks = function(levels) {
+    var self = this;
+    var kkas = _.filter(self.oo, function(sto) {
+        return typeof(sto) === "function"
+    }).map(function(sto, nam) {
+        return sto();
+    })
+
+    kkas.sort(sorter(function(a) {
+        return a._metas.menu_order || 100
+    }, -1));
+
+    return kkas.map(function(obj) {
+        return self.renderme(obj, levels || 0, 0);
+    }).join("\n");
+
+
+}
+
+Asystem.prototype.rendermenu = function(obj, levels) {
+    var self = this;
+
+    var temps = obj.getStuff3("_data.menuobj", function(a) {
+        return a
+    }, "_data.menuobj")
+    console.log("TEMenu", temps);
+    if (temps.length > 0) {
+        return self.renderme(self.oget(temps[0].data), levels || 0, 0);
+    }
+    return self.renderme(obj, levels || 0, 0);
+}
+
+
+
+Asystem.prototype.renderq = function(kkey) {
+    var self = this;
+    return new Promise(function(resolve, reject) {
+        var rooten = self.oget("root");
+        var ss = [self.template('<div id="{{_data.id}}" class="obj root" eleview="" elepath="">', rooten)];
+        // ss.push('<pre onclick="$lib.toggle_admin()">' + self.oget("root/._data.title") + '</pre><hr>')
+
+        if (!self.oo[kkey]) {
+            self.oget(kkey);
+        }
+        ss.push(self.rendera("menulink", self.oo[kkey](), 1, 0));
+
+        ss.push('</div>')
+        resolve(ss.join("\n"));
+    })
+
+
+}
+
+
+
+
+Asystem.prototype.rendera = function(template) {
+    var args = Array.prototype.slice.apply(arguments, [1]);
+
+    if (template == "view") {
+        return "VIEW"
+    }
+    if (template == "menulink") {
+        return this.renderme.apply(this, args);
+    }
+    if (template == "editor") {
+        return this.renderEditorTools(args[0], "editor");
+    }
+
+    return "NOT VIEW " + template
+
+
+}
+//
+Asystem.prototype.renderEditorTools = function(obj, state) {
+    var buts = [];
+
+    if (obj.path.indexOf("trash") == 0) {
+        buts.push('<button class="elerestore"><i class="fa fa-undo-alt"></i></button>')
+    }
+
+    if (state == "editor") {
+
+        buts.push('<button class="eleview"><i class="fa fa-eye"></i></button>')
+
+        if (!(obj._metas.nochildren)) {
+            buts.push('<button class="eleplus"><i class="fa fa-plus-circle"></i></button>')
+        }
+
+
+        if (obj.path.indexOf("trash") == -1 && !(obj._metas.undeletable)) {
+            buts.push('<button class="eledelete"><i class="fa fa-trash-alt"></i></button>')
+        }
+
+
+        buts.push('<button class="eleexport"><i class="fa fa-file-export"></i></button>')
+
+
+    } else {
+        buts.push('<button class="eleeditor"><i class="fa fa-edit"></i></button>')
+
+    }
+
+
+
+    return '<div id="editor" elepath="' + obj.path + '" eleview="editor" class="editorline" ><div class="buttons">' + buts.map(function(a) {
+        return a
+    }).join(" ") + '</div><div id="editor_context"></div></div>'
+
+}
+
+
+tool.add_filters("editor_sections", function(arr, obj) {
+    arr.push({
+        title: "Template",
+        content: function() {
+            return "<div class=\"status\">x</div> <textarea class=htmleditor data-id=\"" + obj.path + "/._data.template\">" + obj._data.template + '</textarea>'
+        }
+    })
+    return arr;
+}, 100, "Template")
+
+function wrap(tag, obj, content) {
+    var args = Array.prototype.slice.apply(arguments, [2]);
+    return '<' + tag + ' ' + _.map(obj, (val, prop) => prop + '="' + val + '"').join(" ") + '>' + args.join("\n") + '</' + tag + '>'
+}
+
+
+Asystem.prototype.renderEditor = function(obj) {
+    var self = this;
+    var ss = "";
+    //"<div class=\"status\">x</div> <textarea class=htmleditor data-id=\"" + obj.path + "/._data.content\">" +  obj._data.content  + '</textarea>'
+
+    // ss += self.template(self.oget("system/editor")._data.template,obj);
+
+    var self = this;
+    var aa = []
+    _.keys(self.oo).filter(aa => ["trash", ""].indexOf(aa) === -1 && typeof(self.oo[aa]) === "function").map(function(key) {
+        aa = [].concat.apply(aa, allchildren(self.oo[key]()).filter(function(a) {
+            return a.editor_function
+        }))
+    })
+
+    ss += aa.map(function(a) {
+        return wrap("div", {
+            elepath: a.path,
+            class: "editor_module"
+        }, wrap("h3", {}, a.name), wrap("div", {}, a._metas.help), wrap("div", {}, a.editor_function(obj)))
+    }).join("\n")
+
+
+    // return aa.map( function(a){ return renderlin(a)(a,a.name) } ).join("\n");    
+
+
+    ss += '<hr>'
+    ss += self.renderEditor2(obj);
+    return ss
+}
+
+String.prototype.toHtmlEntities = function() {
+    return this.replace(/./gm, function(s) {
+        return "&#" + s.charCodeAt(0) + ";";
+    });
+};
+
+/**
+ * Create string from HTML entities
+ */
+String.fromHtmlEntities = function(string) {
+    return (string + "").replace(/&#\d+;/gm, function(s) {
+        return String.fromCharCode(s.match(/\d+/gm)[0]);
+    })
+};
+
+Asystem.prototype.uniq_relnames = function() {
+    var self = this;
+
+
+    var rels = {}
+
+    self.allchildren().map(function(c) {
+        _.keys(c._relations).map(function(relname) {
+            rels[relname] = rels[relname] || 0;
+            rels[relname] = rels[relname] + 1;
+        })
+    })
+
+    return _.keys(rels).map(function(a) {
+        return {
+            name: a,
+            cnt: rels[a]
+        }
+    });
+
+}
+
+
+
+function mmb(t, d) {
+    return '<div class="mb"><h3>' + t + '</h3>' + d + '</div>';
+}
+
+Asystem.prototype.addEditorContext = function(conobj) {
+    this.editorContexts = this.editorContexts || [];
+    this.editorContexts.push(conobj);
+
+
+}
+
+
+Asystem.prototype.renderEditor2 = function(obj) {
+    var self = this;
+    var types = self.editorTypes();
+    var tabs_links = '<ul class="tabs">' + self.editorContexts.filter(function(con) {
+        return con.filter ? con.filter(obj) : true;
+    }).map(function(con) {
+        return self.template('<li data-id="{{name}}" class="tablink {{active}}">{{name}}</li>', {
+            name: con.name,
+            active: (self.current_tab === con.name ? 'active' : '')
+        });
+    }).join("\n") + '</ul>';
+
+    /* var tabs_content = _.map(self.editorContexts,function(con, name){
+        return self.template('<div id="t_{{name}}" class="tab-content">{{body}}</li>', {body: con(), name: name, });
+    }).join("\n");
+    */
+    var str = "";
+    if (self.current_tab) {} else {
+        self.current_tab = self.editorContexts[0].name;
+    }
+    str = self.editorContexts.filter((con) => con.name === self.current_tab).pop().func(obj, types);
+
+    return tabs_links + '<div id="etabcontent">' + str + '</div>';
+}
+Asystem.prototype.editorTypes = function() {
+    var self = this;
+    var types = {
+        jsfuncs: function(obj, fiels) {
+            var qq = [];
+            _.map(_.omit(obj, ignores), function(val, prop) {
+                if (typeof(val) === "function") {
+                    qq.push(["JS " + prop + '<li><button class="deletefunc" data-id="' + obj.path + "/." + prop + '">Delete</button></li>',
+                        "<div class=\"status\"></div> <textarea class=jseditor data-id=\"" + obj.path + "/." + prop + "\">" + (obj[prop] + "") +
+                        '</textarea> '
+                    ]);
+
+                }
+            })
+            qq.push(["JS ", "<input class=\"createfunc\"   data-id=\"" + obj.path + "\"> "]);
+
+            var ss = ('<div class="sas">' + qq.map(function(a) {
+                return '<div class="sa"><div class="inn"><div class="saa">' + (a[0] === false ? "" : a[0] + "") + '</div><div class="sab">' + a[1] +
+                    '</div></div></div>'
+            }).join("\n") + '</div>');
+            return ss
+
+
+        },
+        relations: function(obj, field) {
+            var s = "";
+
+            var ss = []
+            _.map(obj._relations, function(rels, relname) {
+                var relators = _.keys(rels);
+                var sss = relators.slice(0, 25).map(function(relator) {
+                    return '<li elepath="' + relator + '"><a href="#' + relator + '" class="elecontent" title="' + JSON.stringify(rels[relator].context).toHtmlEntities() +
+                        '">' + relator + '</a>  <button class="btn unrelate" data-id="' + obj
+                        .path + '" data-rel="' + relname + '" data-rela="' + relator + '" >X</button></li> '
+
+                }).join("\n");;
+                ss.push([relname + "(" + relators.length + ")", sss]);
+            });
+            s += ss.map(function(a) {
+                return '<div><h3>' + a[0] + '</h3><div>' + a[1] + '</div></div>'
+
+            }).join("\n")
+
+
+            return s;
+        },
+        relationsadd: function(obj, field) {
+            var s = "";
+
+
+            s += '<li class="relationseditor" data-id="' + obj.path +
+                '"><input class="relout" type="text" placeholder="is what " /><em><select  class=uniq_relnames target=".relout"></select>' +
+                '</em><hr> to: <input class="relaeditor" placeholder="find obj"><hr> as: <input type="text" class=relin data-id="' +
+                obj.path +
+                '" placeholder="as what " /> <select  class=uniq_relnames target=".relin"></select><hr> with: <input class="what" type="text" > <button class="relateasto">Relate</button></li>';
+            return s;
+        },
+        templatepaths: function(obj, field) {
+            return "<div class=\"status\"></div>" + _.map(self.getRenderTemplate(obj), function(a) {
+                return '<li elepath="' + a.name + '"  ><a href="#' + a.name + '" class="elecontent" title="' + a.from + ": " + a.data.toHtmlEntities() + '" > ' +
+                    a.name +
+                    '</a></li>'
+            }).join("\n");
+        },
+        visa: function(obj, field) {
+
+            function mkaa(obja) {
+
+
+            }
+
+
+            setTimeout(function() {
+                var cols = {
+                    parent: "#000000",
+                    child: "#ff00ff",
+                    extends: "#00ff00",
+                    inherits: "#ff0000",
+                    isa: "#ff9900",
+                    hasa: "#00ff99"
+                }
+
+                function lokup(tp) {
+                    return cols[tp];
+
+                }
+
+
+                var graph = Viva.Graph.graph();
+                var graphics = Viva.Graph.View.svgGraphics(),
+                    nodeSize = 10;
+
+
+                self.allchildren().filter(function(c) {
+                    return c.path.indexOf("trash/") === -1 && c.path.indexOf("folders/") === -1 && c.path.indexOf("blobs/") === -1
+                }).slice(0, 100).map(function(c) {
+                    graph.addNode(c.path);
+                    _.map(c.children, function(child, name) {
+                        graph.addLink(c.path, child().path, 'child')
+                    });
+                      _.map(c._isa, function(child, name) {
+                        graph.addLink(c.path, child.path, 'isa')
+                    });
+                    _.map(c._hasa, function(child, name) {
+                        graph.addLink(c.path, child.path, 'hasa')
+                    });
+                    
+                    _.map(c._extends, function(child, name) {
+                        graph.addLink(c.path, child.path, 'extends')
+
+                    });
+                    _.map(c._inherits, function(child, name) {
+                        graph.addLink( c.path,child.path, 'inherits')
+                    });
+
+                    
+                    _.map(c._relations, function(rels, relname) {
+                        _.map(rels, function(child, name) {
+                            graph.addLink(c.path, name, relname)
+                        })
+                    });
+                                    
+
+                })
+
+
+
+                var a = obj.path
+                    //graph.addNode(a, '91bad8ceeec43ae303790f8fe238164b');
+
+                /*              _.map(obj.parents, function(parent, name) {
+                    graph.addNode(name, '');
+                    graph.addLink(name, a, 'parent')
+                });
+*/
+                /*
+
+                var ogs = gpath(obj, []);
+                console.log("OOOOOOOOOOOO", ogs);
+                var roo = obj.path,
+                    nexta;
+
+                graph.addNode(roo, '');
+                while (ogs.length) {
+                    nexta = ogs.shift();
+                    graph.addLink(roo, nexta, 'parent')
+                    roo = nexta;
+                }
+
+                roo = obj.path
+
+                _.map(obj.children, function(child, name) {
+                    graph.addNode(name, '');
+                    graph.addLink(roo, name, 'child')
+                });
+                _.map(obj._isa, function(child, name) {
+                    graph.addNode(name, '');
+                    graph.addLink(roo, name, 'isa')
+                });
+                _.map(obj._hasa, function(child, name) {
+                    graph.addNode(name, '');
+                    graph.addLink(roo, name, 'hasa')
+                });
+
+                _.map(obj._extends, function(child, name) {
+                    graph.addNode(name, '');
+                    graph.addLink(roo, name, 'extends')
+                });
+                _.map(obj._inherits, function(child, name) {
+                    graph.addNode(name, '');
+                    graph.addLink(name, roo, 'inherits')
+                });
+                */
+                var idas = 1;
+                var ida = function(){
+                    return "ida"+(idas++)
+                }
+
+                graphics.node(function(node) {
+                    var ui = Viva.Graph.svg('g');
+
+
+                    var circle = Viva.Graph.svg('circle')
+                        .attr('cx', 2)
+                        .attr('cy', 2)
+                        .attr('r', 2)
+                        .attr('fill', obj.path === node.id ? "#ff0000" : "#dadada");
+                    ui.append(circle);
+
+                    var svgText = Viva.Graph.svg('text').attr('font-size', '12px').attr('y', '4px').text(node.id.split("/").pop());
+                    ui.append(svgText);
+                    return ui;
+                }).placeNode(function(nodeUI, pos) {
+                    nodeUI.attr('transform',
+                        'translate(' +
+                        (pos.x - nodeSize / 2) + ',' + (pos.y - nodeSize / 2) +
+                        ')');
+                });
+
+
+                var createMarker = function(id) {
+                        return Viva.Graph.svg('marker')
+                            .attr('id', id)
+                            .attr('viewBox', "0 0 10 10")
+                            .attr('refX', "10")
+                            .attr('refY', "5")
+                            .attr('markerUnits', "strokeWidth")
+                            .attr('markerWidth', "10")
+                            .attr('markerHeight', "5")
+                            .attr('orient', "auto");
+                    },
+
+                    marker = createMarker('Triangle');
+                marker.append('path').attr('d', 'M 0 0 L 10 5 L 0 10 z');
+
+                // Marker should be defined only once in <defs> child element of root <svg> element:
+                var defs = graphics.getSvgRoot().append('defs');
+                defs.append(marker);
+
+                var geom = Viva.Graph.geom();
+
+                graphics.link(function(link) {
+                    // Notice the Triangle marker-end attribe:
+
+                    var isParent = (link.data === 'parent');
+
+                    var ui = Viva.Graph.svg('g');
+                    var p = Viva.Graph.svg('path')
+                        .attr('stroke', lokup(link.data) || "#000000")
+                        .attr('fill', 'none')
+                        .attr('marker-end', 'url(#Triangle)')
+                        .attr('id',  ida() )
+                    ui.isParent = isParent; // remember for future.
+                    ui.linka = link.data;
+                    ui.ry = 50 //- (Math.random() * 100);
+
+                    ui.pp = p;
+                    
+                    
+
+                    var svgText = Viva.Graph.svg('text').attr("dy",-4).attr("class","slabel");
+
+                    var textPath = Viva.Graph.svg("textPath");
+                        textPath.attr("href","#"+p.id).attr("startOffset","25%").text( link.data+ " >");
+
+                    svgText.append(textPath)
+                    ui.tt = svgText;
+
+                    ////<textPath xlink:href="#'+link.id+'">
+
+//                    svgText.attr('xlink', link.id);
+
+
+                    ui.append(svgText)
+
+                    ui.append(p);
+
+                    return ui;
+
+
+                }).placeLink(function(linkUI, fromPos, toPos) {
+                    // using arc command: http://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
+                    //var data = 'M' + fromPos.x + ',' + fromPos.y +
+                      //  ' A 4,' + linkUI.ry + ',-' + linkUI.ry + ',0,1,' + toPos.x + ',' + toPos.y;
+
+                var data = 'M' + fromPos.x + ',' + fromPos.y +
+                        ' C ' + (fromPos.x+50)+' '+(fromPos.y+10)+','+ (toPos.x-50) + ' ' +(toPos.y-10) + ',' +toPos.x + ' ' + toPos.y ;
+
+
+
+                    linkUI.pp.attr("d", data);
+
+                    return;
+                 //  linkUI.tt.attr("y", ((fromPos.y + toPos.y) / 2) - linkUI.ry);
+                   // linkUI.tt.attr("x", ((fromPos.x + toPos.x) / 2) );
+
+                    if (linkUI.isParent) {
+                        /*    var ry = linkUI.isParent ? 4 : 0,
+                            // using arc command: http://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
+                            data = 'M' + fromPos.x + ',' + fromPos.y +
+                            ' A 4,' + ry + ',-4,0,1,' + toPos.x + ',' + toPos.y;
+
+                        linkUI.attr("d", data);
+*/
+                        var data = 'M' + fromPos.x + ',' + fromPos.y +
+                            'L' + toPos.x + ',' + toPos.y;
+                        linkUI.pp.attr("d", data);
+
+
+                    }
+                    if (linkUI.linka === 'isa') {
+                        var data = 'M' + fromPos.x + ',' + fromPos.y +
+                            'L' + toPos.x + ',' + toPos.y;
+                        linkUI.pp.attr("d", data);
+                    }
+
+                    if (linkUI.linka === 'hasa') {
+                        // var data = 'M' + fromPos.x + ',' + fromPos.y +
+                        //   'L' + toPos.x + ',' + toPos.y;
+
+                        var ry = 4;
+                        // using arc command: http://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
+                        var data = 'M' + fromPos.x + ',' + fromPos.y +
+                            ' A 4,' + ry + ',-4,0,1,' + toPos.x + ',' + toPos.y;
+
+
+                        linkUI.pp.attr("d", data);
+
+
+                    }
+                    if (linkUI.linka === 'inherits') {
+                        var data = 'M' + fromPos.x + ',' + fromPos.y +
+                            'L' + toPos.x + ',' + toPos.y;
+                        linkUI.pp.attr("d", data);
+                    }
+                    if (linkUI.linka === 'extends') {
+                        var data = 'M' + fromPos.x + ',' + fromPos.y +
+                            'L' + toPos.x + ',' + toPos.y;
+                        linkUI.pp.attr("d", data);
+                    }
+
+                    if (linkUI.linka === 'child') {
+
+                        var toNodeSize = nodeSize,
+                            fromNodeSize = nodeSize;
+
+                        var from = geom.intersectRect(
+                            // rectangle:
+                            fromPos.x - fromNodeSize / 2, // left
+                            fromPos.y - fromNodeSize / 2, // top
+                            fromPos.x + fromNodeSize / 2, // right
+                            fromPos.y + fromNodeSize / 2, // bottom
+                            // segment:
+                            fromPos.x, fromPos.y, toPos.x, toPos.y) || fromPos; // if no intersection found - return center of the node
+
+                        var to = geom.intersectRect(
+                            // rectangle:
+                            toPos.x - toNodeSize / 2, // left
+                            toPos.y - toNodeSize / 2, // top
+                            toPos.x + toNodeSize / 2, // right
+                            toPos.y + toNodeSize / 2, // bottom
+                            // segment:
+                            toPos.x, toPos.y, fromPos.x, fromPos.y) || toPos; // if no intersection found - return center of the node
+
+                        var data = 'M' + from.x + ',' + from.y +
+                            'L' + to.x + ',' + to.y;
+                        linkUI.pp.attr("d", data);
+
+                    }
+
+
+
+                });
+
+
+                //               graph.addNode( b, 'd43e8ea63b61e7669ded5b9d3c2e980f');
+                //             graph.addLink(a, b);
+                /* 
+                graphics.link(function(link) {
+                    var isParent = (link.data === 'parent'),
+                        ui = Viva.Graph.svg('path')
+                        .attr('stroke', isParent ? 'red' : 'blue')
+                        .attr('fill', 'none');
+                    ui.isParent = isParent; // remember for future.
+                    return ui;
+                }).placeLink(function(linkUI, fromPos, toPos) {
+                    // linkUI - is the object returend from link() callback above.
+                    var ry = linkUI.isParent ? 10 : 0,
+                        // using arc command: http://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
+                        data = 'M' + fromPos.x + ',' + fromPos.y +
+                        ' A 10,' + ry + ',-30,0,1,' + toPos.x + ',' + toPos.y;
+                    // 'Path data' (http://www.w3.org/TR/SVG/paths.html#DAttribute )
+                    // is a common way of rendering paths in SVG:
+                    linkUI.attr("d", data);
+                });
+
+*/
+
+
+                var layout = Viva.Graph.Layout.forceDirected(graph, {
+                    springLength: 80,
+                    springCoeff: 0.00001,
+                    dragCoeff: 0.001,
+                    gravity: -1.2
+                });
+
+                 
+
+
+                var renderer = Viva.Graph.View.renderer(graph, {
+                    graphics: graphics,
+                    container: document.getElementById('visagraf'),
+                    layout: layout
+                });
+                renderer.run();
+            }, 200)
+            return '<div id="visagraf" class="svga">v</div>'
+        },
+        meta: function(obj, field) {
+
+            return "<div class=\"status\"></div> <textarea class=dataeditor data-id=\"" + obj.path + "/._metas\">" + JSON.stringify(obj._metas, true, 2) + '</textarea>'
+
+        },
+        data: function(obj, field) {
+
+            return "<div class=\"status\"></div> <textarea class=dataeditor data-id=\"" + obj.path + "/._data\">" + JSON.stringify(obj._data, true, 2) + '</textarea>'
+
+        },
+
+        hasas: function(obj, field) {
+            return '<div class="hasas">' + _.map(obj._hasa, function(tob, name) {
+                return self.template(
+                    '<li elepath="{{tob.path}}" pelepath="{{obj.path}}" ><a href="#{{name}}" class="elecontent">{{name}}</a> <button class="btn unhasa">X</button></li>', {
+                        tob: tob,
+                        obj: obj,
+                        name: name
+                    });
+            }).join("\n") + '</div>'
+        },
+        isas: function(obj, field) {
+            return '<div class="isas">' + _.map(obj._isa, function(tob, name) {
+                return self.template(
+                    '<li elepath="{{tob.path}}" pelepath="{{obj.path}}" ><a href="#{{name}}" class="elecontent">{{name}}</a> <button class="btn unisa">X</button></li>', {
+                        tob: tob,
+                        obj: obj,
+                        name: name
+                    });
+            }).join("\n") + '</div>' + self.template('<input class=isaeditor data-id="{{obj.path}}" placeholder="find isas here.." />', {
+                obj: obj
+            });
+        },
+        extends: function(obj, field) {
+            return '<div class="extends">' + _.map(obj._extends, function(tob, name) {
+                return self.template(
+                    '<li elepath="{{tob.path}}" pelepath="{{obj.path}}" ><a href="#{{name}}" class="elecontent">{{name}}</a> <button class="btn unextend">X</button></li>', {
+                        tob: tob,
+                        obj: obj,
+                        name: name
+                    });
+            }).join("\n") + '</div>' + self.template('<input class=extendeditor data-id="{{obj.path}}" placeholder="find inheritants here.." />', {
+                obj: obj
+            });
+        },
+        inherits: function(obj, field) {
+            return '<div class="inherits">' + _.map(obj._inherits, function(tob, name) {
+                return self.template(
+                    '<li elepath="{{tob.path}}" pelepath="{{obj.path}}" ><a href="#{{name}}" class="elecontent">{{name}}</a> <button class="btn uninherit">X</button></li>', {
+                        tob: tob,
+                        obj: obj,
+                        name: name
+                    });
+            }).join("\n") + '</div>' + self.template('<input class=inheriteditor data-id="{{obj.path}}" placeholder="find extenders here.." />', {
+                obj: obj
+            });
+
+        },
+        children: function(obj, field) {
+            var s = '';
+            s += mmb("Add child", "<input type=\"text\" class=addchildeditor data-id=\"" + obj.path + "\" value=\"" + '"> ');
+
+            s += '<div class="children">' + _.map(obj.children, function(a) {
+                return a().path
+            }).map(function(k) {
+                return '<li elepath="' + k + '" pelepath="' + obj.path + '"><a href="#' + k + '" class="elecontent" > ' + k +
+                    '</a>  '
+            }).join("\n") + '</div>'
+
+
+
+            return s;
+
+        },
+        info: function(obj, field) {
+
+            return "Path:  " + obj.path
+        },
+        upload: function(obj, field) {
+            return (
+                '<div class="upload-btn-wrapper"><button class="btn" onclick="$(\'#myupload\').click()">Upload files</button><input id="myupload" type="file" class="afile" style="opacity: 0;" name="file1" multiple data-id="' +
+                obj.path +
+                '" data-action="browser_handlefilen" data-emit="filesloaded"  /></div> ');
+        },
+        content: function(obj, field) {
+            var content_type = "<div><input type=\"text\" class=propeditor data-id=\"" + obj.path + "/._metas.type\" value=\"" +
+                obj._metas.type +
+                '">' + "<select  class=propselector data-id=\"" + obj.path + "/._metas.type\"></select></div>";
+
+
+
+
+            var s = '';
+
+            s += mmb("Title", types.propeditor(obj, {
+                "path": "_data.title"
+            }))
+
+            if (obj._metas.type && obj._metas.type == "html") {
+                s += mmb("Content", "<div class=\"adj\"><div class=\"status\"></div> <textarea class=mceeditor data-id=\"" + obj.path + "/._data.content\">" + obj._data.content +
+                    '</textarea></div>')
+            } else {
+                s += mmb("Body", "<div class=\"adj\"><div class=\"status\"></div> <textarea class=htmleditor data-id=\"" + obj.path + "/._data.content\">" + obj._data.content +
+                    '</textarea></div>')
+            }
+            s += mmb("Type", content_type);
+            return s;
+
+        },
+
+        template: function(obj, field) {
+            return "<textarea class=htmleditor data-id=\"" + obj.path + "/._data.template\">" + obj._data.template +
+                '</textarea>'
+        },
+        texteditor: function(obj, field) {
+            var s = "";
+            s += '<textarea data-id="' + obj.path + '">' + opath.get(obj, field.path) + '</textarea>'
+            return s
+        },
+        propeditor: function(obj, field) {
+            var s = "";
+            s += '<input class="propeditor" data-id="' + obj.path + '/.' + field.path + '" value="' + opath.get(obj, field.path) + '">'
+            return s
+        },
+        lookup: function(obj, field) {
+            var temps = obj.getStuff3(field.path, function(a) {
+                return a
+            }, field.path)
+            var current_name = "",
+                current_data = "";
+            if (temps.length > 0) {
+                current_name = temps[0].name
+                current_data = temps[0].data;
+            }
+
+            var s = ''; //' <input type="text" data-id="'+obj.path+'/.'+field.path+'" value="' + opath.get(obj,field.path) + '">'
+
+
+
+            var path = opath.get(obj, field.path);
+
+
+            if (current_name !== "" && !path) {
+                path = opath.get(self.oget(current_name), field.path);
+                s += ' inherit <a elepath="' + path + '" href="#' + path + '" class="elecontent" > ' + path + '</a>';
+                s += ' from ' + '<a elepath="' + current_name + '" href="#' + current_name + '" class="elecontent" > ' + current_name + '</a>'
+            } else {
+                if (!path) {
+                    s += 'no object selected'
+                } else {
+                    s += 'Current: <li> <a elepath="' + path + '" href="#' + path + '" class="elecontent" > ' + path + '</a> <button class="btn unset" data-id="' + obj.path +
+                        '" ele-prop="' + field.path + '">X</button> </li>';
+
+                }
+            }
+
+            s += "<br><input class=\"propselector22\" ele-has=\"" + field.has + "\" ele-list=\"" + field.lookup + "\" ele-pick=\"" + field.pick + "\" data-id=\"" + obj.path +
+                "\" ele-prop=\"" + field.path + "\" >";
+
+
+
+
+            return s;
+        },
+        lookup2: function(obj, field) {
+            var temps = obj.getStuff3(field.path, function(a) {
+                return a
+            }, field.path)
+            var current_name = "",
+                current_data = "";
+            if (temps.length > 0) {
+                current_name = temps[0].name
+                current_data = temps[0].data;
+            }
+
+            var s = ''; //' <input type="text" data-id="'+obj.path+'/.'+field.path+'" value="' + opath.get(obj,field.path) + '">'
+            s += "<select class=propselector2 data-has=\"" + field.has + "\" data-list=\"" + field.lookup + "\" data-pick=\"" + field.pick + "\" data-id=\"" +
+                obj.path + "/." +
+                field.path + "\"></select>";
+
+            var path = opath.get(obj, field.path);
+
+
+            if (current_name !== "" && !path) {
+                path = opath.get(self.oget(current_name), field.path);
+                s += ' inherit <a elepath="' + path + '" href="#' + path + '" class="elecontent" > ' + path + '</a>';
+                s += ' from ' + '<a elepath="' + current_name + '" href="#' + current_name + '" class="elecontent" > ' + current_name + '</a>'
+            } else {
+                s += '<a elepath="' + path + '" href="#' + path + '" class="elecontent" > ' + path + '</a>';
+            }
+
+            return s;
+        }
+
+    }
+    return types;
+
+
+}
+
+Asystem.prototype.renderEditor2a = function(obj) {
+    var self = this;
+    var stash = [];
+
+    //   stash.push(["Parent", '<div class="parents">' + self.template("{{parents::}}", obj) + '</div>']);
+
+    // stash.push(["Path", "<input type=\"text\" class=patheditor data-id=\"" + obj.path + "\" value=\"" + obj.path + '">']);
+
+
+
+
+
+    /* stash.push(["Title", "<div class=\"status\"></div> <input type=\"text\" class=propeditor data-id=\"" + obj.path + "/._data.title\" value=\"" + obj._data.title +
+        '">'
+    ]);
+
+*/
+
+
+
+    /*  if (obj.name !== "root") {
+        (self.oget("root")._metas.fields || []).map(function(field) {
+            stash.push([field.title, types[field.type](obj, field)]);
+        })
+
+    }*/
+
+    /*
+    if (obj._metas && obj.name !== "root") {
+        (obj._metas.fields || []).map(function(field) {
+            stash.push([field.title, types[field.type](obj, field)]);
+        })
+    }*/
+
+    function mkmod(obj, field) {
+        var data = "";
+        if (types[field.type]) {
+            data = types[field.type](obj, field)
+        } else {
+            data = field.data;
+        }
+        var s = '<div class="module ' + field.type + '" ><div class="head">' + field.title + '</div><div class="content">' + data + '</div></div>'
+        return s
+    }
+
+    function mkmodg(name, title, data) {
+        var s = '<div id="m_' + name + '" class="modulegroup" ><div class="head">' + title + '</div><div class="content">' + data + '</div></div>'
+        return s
+    }
+
+    function mktab() {
+
+
+    }
+
+    var xx = []
+    if (obj._metas.notself) {} else {
+
+        var fff = obj.getStuff("_metas.fields", function(a) {
+            return a
+        }, "fi");
+        fff.map(function(ff) {
+            ff.data.map(function(field) {
+                xx.push(mkmod(obj, field));
+            })
+
+        })
+
+
+    }
+
+
+    stash.push([" ", mkmodg("info", " ", [mkmod(obj, {
+        "type": "info",
+        "title": "Info",
+        "data": "Path:  " + obj.path
+    }), '<div id="editorbuttons" class="buttons"></div>'].join("\n"))]);
+
+
+    /*   var qq = []
+    qq.push(mkmod(obj, {
+        "title": "Path",
+        "data": "<input type=\"text\" class=patheditor data-id=\"" + obj.path + "\" value=\"" + obj.path + '">'
+    }));
+    qq.push(mkmod(obj, {
+        "title": "Parents",
+        "data": self.template("{{parents::}}", obj)
+    }));
+
+    stash.push([" ", mkmodg("content", " ", qq.join("\n"))]);
+*/
+
+    stash.push([" ", mkmodg("content", " ", xx.join("\n"))]);
+
+
+
+
+    var left = [];
+    var right = [];
+    right.push(mkmod(obj, {
+        "type": "children",
+        "title": "Children"
+    }));
+    left.push(mkmod(obj, {
+        "type": "inherits",
+        "title": "Inherits"
+    }));
+    left.push(mkmod(obj, {
+        "type": "extends",
+        "title": "Extends"
+    }));
+
+
+
+    stash.push([" ", '<div class="dleft">' + mkmodg("x", " ", left.join("\n")) + '</div><div class="dright">' + mkmodg("y", " ", right.join("\n")) + '</div>']);
+
+
+    stash.push([" ", '<div class="toolsa">' + mkmodg("tools", " ", [mkmod(obj, {
+        "type": "upload",
+        "title": "Upload"
+    }), mkmod(obj, {
+        "type": "clone",
+        "title": "Clone",
+        "data": "<div class=\"status\"></div> <input type=\"text\" class=cloneeditor data-id=\"" + obj.path + "\" value=\"" + '"> '
+    }), mkmod(obj, {
+        "type": "delete",
+        "title": "Delete",
+        "data": '<li> <button class="deleteele" data-id="' + obj.path + '">Trash</button>  <button class="zapele" data-id="' + obj.path +
+            '">Delete Permanently</button></li>'
+    })].join("\n")) + '</div>']);
+
+
+
+
+
+
+
+
+
+    var left = [];
+    var right = [];
+
+    left.push(mkmod(obj, {
+        "type": "isas",
+        "title": "Is a thing"
+    }))
+
+    right.push(mkmod(obj, {
+        "type": "hasas",
+        "title": "Is thing to something"
+    }))
+
+    stash.push([" ", '<div class="dleft">' + mkmodg("xx", " ", left.join("\n")) + '</div><div class="dright">' + mkmodg(",yy", " ", right.join("\n")) + '</div>']);
+
+
+
+    var xx = [];
+
+    xx.push(mkmod(obj, {
+        "type": "template",
+        "title": "Template"
+    }))
+
+    xx.push(mkmod(obj, {
+        "type": "templatepaths",
+        "title": "Paths"
+    }))
+
+    stash.push([" ", mkmodg("x", "Template", xx.join("\n"))]);
+
+
+    stash.push([" ", "<hr>"]);
+
+
+
+
+    /*  stash.push(["Icon", "<div class=\"status\"></div> <input type=\"text\" class=iconselecter data-id=\"" + obj.path + "/._data.iconclass\" value=\"" + obj._data.iconclass +
+        '"> '
+    ]);
+*/
+
+
+
+
+
+
+
+    if (obj._data.data && obj._data.data.length > 8192) {
+        stash.push(["Data too big", obj._data.data.length + " :" + obj._data.data.substring(0, 200)])
+    } else {
+        stash.push(["Data", "<div class=\"status\"></div> <textarea class=dataeditor data-id=\"" + obj.path + "/._data\">" + JSON.stringify(obj._data, true, 2) +
+            '</textarea>'
+        ]);
+
+    }
+
+    stash.push(["Meta", "<div class=\"status\"></div> <textarea class=dataeditor data-id=\"" + obj.path + "/._metas\">" + JSON.stringify(obj._metas, true, 2) +
+        '</textarea>'
+    ]);
+
+
+    _.map(_.omit(obj, ignores), function(val, prop) {
+        if (typeof(val) === "function") {
+            stash.push(["JS " + prop + '<li><button class="deletefunc" data-id="' + obj.path + "/." + prop + '">Delete</button></li>',
+                "<div class=\"status\"></div> <textarea class=jseditor data-id=\"" + obj.path + "/." + prop + "\">" + (obj[prop] + "") +
+                '</textarea> '
+            ]);
+
+        }
+    })
+    stash.push(["JS ", "<input class=\"createfunc\"   data-id=\"" + obj.path + "\"> "]);
+
+
+
+    var ss = ('<div class="stash">' + stash.map(function(a) {
+        return '<div class="stt"><div class="inn"><div class="st1">' + (a[0] === false ? "" : a[0] + "") + '</div><div class="st2">' + a[1] +
+            '</div></div></div>'
+    }).join("\n") + '</div>');
+    return ss
+}
+Asystem.prototype.renderEditor3 = function(obj) {
+    var self = this;
+    var stash = [];
+
+    var prot = {}
+    var meta = {}
+    allchildren(obj).map(function(c) {
+        var arr = opath.flatten(c._data, "");
+        arr.map(function(a) {
+            prot[a[0]] = prot[a[0]] || {}
+            prot[a[0]][a[1]] = prot[a[0]][a[1]] || 0
+            prot[a[0]][a[1]] += 1;
+        })
+
+        var arr = opath.flatten(c._metas, "");
+        arr.map(function(a) {
+            if (a[0].indexOf('_wp_attachment_backup_sizes') > -1) {
+                return;
+            }
+            meta[a[0]] = meta[a[0]] || {}
+            meta[a[0]][a[1]] = meta[a[0]][a[1]] || 0
+            meta[a[0]][a[1]] += 1;
+        })
+    });
+    var prota = _.map(prot, function(vala, nama) {
+        return nama + " : " + _.size(vala)
+    });
+    var metas = _.map(meta, function(vala, nama) {
+        return nama + " : " + _.size(vala)
+    });
+
+    stash.push(["Data Properties", '<pre>' + JSON.stringify(prota, true, 2) + '</pre>'])
+    stash.push(["Meta Properties", '<pre>' + JSON.stringify(metas, true, 2) + '</pre>'])
+
+    var ss = ('<div class="stash">' + stash.map(function(a) {
+        return '<div class="stt"><div class="st1">' + (a[0] === false ? "" : a[0] + "") + '</div><div class="st2">' + a[1] + '</div></div>'
+    }).join("\n") + '</div>');
+    return ss
+}
+
+Asystem.prototype.getRenderTemplate = function(obj) {
+    var self = this;
+    var stash = [];
+    var templates = []
+
+    var temps = obj.getStuff3("_data.template", function(a) {
+        return a
+    }, "_data.template")
+    var myself;
+
+    var x = {};
+    temps.map(function(a) {
+        x[a.name] = a
+    });
+    temps = _.map(x, function(a) {
+        return a
+    });
+    return temps
+}
+
+
+
+Asystem.prototype.rendertemplate2 = function(obj) {
+    var self = this;
+    var stash = [];
+    var templates = []
+
+    var temps = obj.getStuff3("_data.template", function(a) {
+        return a
+    }, "_data.template")
+    var myself;
+
+    var x = {};
+    temps.map(function(a) {
+        x[a.name] = a
+    });
+    temps = _.map(x, function(a) {
+        return a
+    });
+
+    var ss = '<div eletemplate="' + obj.path + '"> ' + self.template(obj._data.template, obj) + ' </div>'
+    return ss;
+
+}
+
+Asystem.prototype.rendertemplate = function(obj) {
+    var self = this;
+    var stash = [];
+    var templates = []
+
+    var temps = obj.getStuff3("_data.template", function(a) {
+        return a
+    }, "_data.template")
+    var myself;
+
+    var x = {};
+    temps.map(function(a) {
+        x[a.name] = a
+    });
+    temps = _.map(x, function(a) {
+        return a
+    });
+    if (obj._data.template && obj._data.template.indexOf("{{output}}") > -1) {
+        myself = temps.shift();
+    }
+
+    var outer = temps.filter(function(a) {
+        return a.data.indexOf("{{output}}") > -1
+    })
+    var otemp = "{{output}}"
+    var outera = "";
+    if (outer.length) {
+        outera = outer[0];
+        otemp = outer[0].data;
+    }
+    var output = temps.filter(function(a) {
+        return a.data.indexOf("{{output}}") === -1 && a.name.indexOf("menu") === -1 && a.name.indexOf("header") === -1 && a.from.indexOf("isa_") === -1
+    }).map(function(tmp) {
+        return '<div eletemplate="' + tmp.name + '"> ' + self.template(tmp.data, obj) + ' </div>';
+    }).join("\n")
+
+    var menus = temps.filter(function(a) {
+        return a.name.indexOf("menu") > -1
+    }).slice(0, 1).map(function(tmp) {
+        return '<div eletemplate="' + tmp.name + '"> ' + self.template(tmp.data, obj) + ' </div>';
+    }).join("\n")
+
+
+    var headers = temps.filter(function(a) {
+            return a.name.indexOf("header") > -1
+        }).slice(0, 1).map(function(tmp) {
+            return '<div eletemplate="' + tmp.name + '"> ' + self.template(tmp.data, obj) + ' </div>';
+        }).join("\n")
+        /*
+    var isas = temps.filter(function(a) {
+        return a.from.indexOf("isa_") > -1
+    }).map(function(tmp) {
+        console.log("ISA,",tmp);
+        if(tmp.inas.length>2){
+            var tma=tmp.inas.pop();
+                tma=tmp.inas.pop();
+        return '<div eletemplate="' + tmp.name + '">IIS ' + self.template(tmp.data, self.oget(tma)) + ' </div>';
+
+        }else{
+        return '<div eletemplate="' + tmp.name + '">IIS ' + self.template(tmp.data, self.oget(tmp.name)) + ' </div>';
+
+        }
+    }).join("\n")
+*/
+    if (myself) {
+        var ai = Object.assign({
+            "output": output,
+            "menu": menus,
+            "header": headers,
+            "selfie": JSON.stringify(temps, true, 2)
+        }, obj);
+
+        var ss = '<div eletemplate="' + myself.name + '"> ' + self.template(myself.data, ai) + ' </div>'
+
+
+    } else {
+
+        var ai = Object.assign({
+            "output": output,
+            "menu": menus,
+            "header": headers,
+            "selfie": JSON.stringify(temps, true, 2)
+        }, obj);
+
+        var ss = '<div eletemplate="' + outer.name + '"> ' + self.template(otemp, ai) + ' </div>'
+
+
+    }
+
+
+    return ss
+
+}
+
+Asystem.prototype.allchildren = function(ronly) {
+    var self = this;
+    var arr = [];
+    if (ronly) {
+        return [].concat.apply(arr, allchildren(self.oo[ronly]))
+    }
+    _.keys(self.oo).filter((k) => typeof(self.oo[k]) === "function").map(function(key) {
+        arr = [].concat.apply(arr, allchildren(self.oo[key]))
+    })
+    return arr;
+}
+Asystem.prototype.allchildpaths = function(ronly) {
+    var self = this;
+    var arr = [];
+    _.keys(self.oo).filter((k) => typeof(self.oo[k]) === "function").map(function(key) {
+        ronly ? (ronly === key ? arr = [].concat.apply(arr, allchildpaths(self.oo[key])) : null) : arr = [].concat.apply(arr, allchildpaths(self.oo[key]))
+    })
+    return arr;
+}
+
+
+
+module.exports = Asystem;

+ 3 - 1
package.json

@@ -15,6 +15,8 @@
   "dependencies": {
     "async": "^2.6.1",
     "libs": "git+ssh://git@git.tum.dk/tum.dk/libs",
-    "opath": "git+ssh://git@git.tum.dk/tum.dk/opath"
+    "opath": "git+ssh://git@git.tum.dk/tum.dk/opath",
+    "sharedkey-thing": "git+ssh://git@git.tum.dk/tum.dk/sharedkey-thing.git",
+    "tools2": "git+ssh://git@git.tum.dk/tum.dk/tools2.js.git"
   }
 }

+ 91 - 38
templates.js

@@ -6,82 +6,135 @@ function mker(helper, templatehelpers) {
 
 
     return function template(str, obj) {
-        return (str + "").replace(/\{\{([a-zA-Z0-9-\|_\.\:/]*)\}\}/gi, function(a, m) {
+        return (str + "").replace(/\{\{([a-zA-Z0-9-\|_\!\.\=\: /]*)\}\}/gi, function(a, m) {
             var re
+                //string contains ::  its a function
             if (m.indexOf("::") > -1) {
                 /* program */
-                re = " TEST "
+                re = "[not found " + m + "]"
                 var ma = m.split("::");
                 fun = ma.shift();
                 if (fun.indexOf("/") > -1) {
                     //path mode ... go get
+                    //holy
                     var funs = fun.split("/");
                     fun = funs.pop();
-                    var zfun = helper.oget(funs.join("/"))[fun]
+                    var zfunobj = helper.oget(funs.join("/"))
+                    var zfun = zfunobj[fun];
+
                     if (typeof(zfun) === "function") {
+                        //ok ma is [arguments rest]..
+                        //if last has |
+                        var last = ma.pop();
+                        if (last) {
+                            var chain = last.split("|");
+                            if (chain.length > 1) {
+                                ma.push(chain.shift())
+                            } else {
+                                ma.push(last);
+                            }
+                        }
+
+                        ma.unshift(zfunobj);
                         re = zfun.apply(obj, ma);
+
+                        while (chain.length) {
+                            var ffuna = chain.shift();
+                            if (ffuna.indexOf(":") > -1) {
+                                var ffunas = ffuna.split(":");
+                                ffuna = ffunas.shift();
+
+                                re = templatehelpers[ffuna] ? templatehelpers[ffuna].apply(ffuna, [re].concat(ffunas)) : re;
+
+
+                            } else {
+                                re = templatehelpers[ffuna] ? templatehelpers[ffuna](re) : re;
+
+                            }
+                        }
+
                     }
                 } else {
+                    //string contains direct hit on templatehelper functions ?
+ 
                     if (templatehelpers[fun]) {
                         // rest skal være arguments
-                        re = templatehelpers[fun](obj);
-                    }
-                    if (obj[fun]) {
+ 
+                        re = templatehelpers[fun].apply(helper, [obj].concat(ma));
+                    } else {
+                        // does obj have fun ?
                         if (typeof(obj[fun]) === "function") {
                             re = obj[fun].apply(obj, ma)
                         } else {
+                            //not found 
                             //  console.log("FUUUUUUUUUU", fun, ma, obj[fun])
                         }
+
                     }
-                    //
+
+
                 }
             } else {
-                if (m.indexOf("||") > -1) {
-                    var mm = m.split("||");
-                    m = mm.shift();
-                    re = (obj[m] ? obj[m] : gget(obj, m));
-                    if (re) {
 
-                    } else {
+                //string contains /.  its a path oget
+                if (m.indexOf("/.") > -1) {
+                    //path mode
+                    re = helper.oget(m)
+                } else {
+
+                    //string contains ||  its a chain
+                    if (m.indexOf("||") > -1) {
+                        var mm = m.split("||");
                         m = mm.shift();
                         re = (obj[m] ? obj[m] : gget(obj, m));
-                    }
+                        if (re) {
 
-                } else {
-                    re = (obj[m] ? obj[m] : gget(obj, m));
-                    if (typeof(re) === "undefined") {
-                        re = "";
-                    } else if (typeof(re) === "number") {
-                        re = re + "";
-                    } else if (typeof(re) === "date") {
-                        re = re + "";
-                    }
+                        } else {
+                            m = mm.shift();
+                            re = (obj[m] ? obj[m] : gget(obj, m));
+                            if(re){
 
-                    if (typeof(re) === "object") {
-                        re = _.keys(re).map(function(k) {
-                            var ka = typeof(re[k]) === "function" ? re[k]() : re[k];
-                            return '<a href="#' + ka.path + '" class="ele">' + ka.path + '</a>'
-                        }).join(" ");
-                    } else {
-                        re = re + "";
-                    }
+                            }else{
+                                re = m;
+                            }
 
+                        }
 
-                    if (re.indexOf("$REF") === 0) {
-                        return re.split("=").slice(1).join("=")
                     } else {
-                        if (re.substring(0, 2) === "$$") {
-                            return helper.t_content(re.substring(2))
+                        //string contains just the prop ?
+                        re = (obj[m] ? obj[m] : gget(obj, m));
+
+                        if (typeof(re) === "undefined") {
+                            re = "";
+                        } else if (typeof(re) === "number") {
+                            re = re + "";
+                        } else if (typeof(re) === "date") {
+                            re = re + "";
                         }
-                    }
 
+                        if (typeof(re) === "object") {
+                            re = _.keys(re).map(function(k) {
+                                var ka = typeof(re[k]) === "function" ? re[k]() : re[k];
+                                return '<a href="#' + ka.path + '" class="ele">' + ka.path + '</a>'
+                            }).join(" ");
+                        } else {
+                            re = re + "";
+                        }
+
+                        if (re.indexOf("$REF") === 0) {
+                            return re.split("=").slice(1).join("=")
+                        } else {
+                            if (re.substring(0, 2) === "$$") {
+                                return helper.t_content(re.substring(2))
+                            }
+                        }
+
+                    }
                 }
             }
-
             return re
         })
     }
-
 }
 
 function gget(obj, path) {

Деякі файли не було показано, через те що забагато файлів було змінено