2015-02-20 15 views
6

Zgodnie z tytułem, mam strukturę katalogów, chcę ją przekonwertować na format JSON zgodny z jsTree usage. więc wyjście dla danej listyWydajna funkcja do tworzenia danych JSON ze struktury katalogu plików?

INPUT:

./Simple Root Node 
./Root Node 2 
./Root Node 2/Child 1 
./Root Node 2/Child 2 

WYJŚCIE:

treeJSON = [ 
     { "id" : "ajson1", "parent" : "#", "text" : "Simple root node" }, 
     { "id" : "ajson2", "parent" : "#", "text" : "Root node 2" }, 
     { "id" : "ajson3", "parent" : "ajson2", "text" : "Child 1" }, 
     { "id" : "ajson4", "parent" : "ajson2", "text" : "Child 2" }, 
    ] 

moja metoda:

Obecnie biorę każdy linia od wejścia. Powiedzmy ./Root Node 2/Child 1, a następnie wzorzec pasuje do pierwszego folderu, tworząc tablicę taką jak { "id" : "ajson2", "parent" : "#", "text" : "Root node 2" }. Następnie przejdź rekursywnie do następnego usuwania pierwszego folderu. Stwórz, tworząc tablicę sieci jako { "id" : "ajson4", "parent" : "ajson2", "text" : "Child 2" }.

Robię to dla każdej linii na wejściu, a następnie używam mojej unikatowej funkcji tablicowej, jak w http://jsfiddle.net/bsw5s60j/8/, aby usunąć wszystkie duplikaty tablic, które zostały utworzone. Na przykład: { "id" : "ajson2", "parent" : "#", "text" : "Root node 2" } zostanie utworzony dwa razy. Raz podczas przechodzenia przez trzecią linię, a następnie w czwartą linię.

Oczywiście ten kod jest WYSOCE nieefektywny. Jeśli mam katalogi około 1.3K, to zakładam, że każdy ma 4 podkatalogi, mamy tablice 5.2K, które muszą być sprawdzone pod kątem duplikatów.

To powoduje problem z hge. Czy istnieje inny skuteczny sposób, w jaki mogę zrobić ten kod?

Fiddle: (działa z Chrome tylko ze względu na atrybut pliku WebKit)http://jsfiddle.net/bsw5s60j/8/

JavaScript

var input = document.getElementById('files'); 
var narr = []; 
var fileICON = "file.png"; 

//when browse button is pressed 
input.onchange = function (e) { 
    var dummyObj = []; 
    var files = e.target.files; // FileList 
    for (var i = 0, f; f = files[i]; ++i) { 
     var fname = './' + files[i].webkitRelativePath; 
     narr = $.merge(dummyObj, (cat(fname))); 
    } 

    treeJSON = narr.getUnique(); // getting the JSON tree after processing input 
    console.log(JSON.stringify(treeJSON)); 

    //creating the tree using jstree 

    $('#tree') 
     .jstree({ 
     'core': { 
      'check_callback': true, 
       'data': function (node, cb) { 
       cb.call(this, treeJSON); 
      } 
     } 
    }); 
    var tree = $('#tree').jstree(true); 
    tree.refresh(); 
}; 

//get unqiue array function 
Array.prototype.getUnique = function() { 
    var o = {}, a = []; 
    for (var i = 0, l = this.length; i < l; ++i) { 
     if (o.hasOwnProperty(JSON.stringify(this[i]))) { 
      continue; 
     } 
     a.push(this[i]); 
     o[JSON.stringify(this[i])] = 1; 
    } 
    return a; 
}; 

// categorizing function which converts each ./Files/Root/File.jpg to a JSON 

var objArr = []; 
var folderArr = []; 

function cat(a) { 
    if (!a.match(/\/(.+?)\//)) { 
     var dummyObj = {}; 
     var fname = a.match(/\/(.*)/)[1]; 
     dummyObj.id = fname; 
     dummyObj.text = fname; 
     if (folderArr === undefined || folderArr.length == 0) { 
      dummyObj.parent = '#'; 
     } else { 
      dummyObj.parent = folderArr[(folderArr.length) - 1]; 
      dummyObj.icon = fileICON; // add extention and icon support 
     } 
     objArr.push(dummyObj); 
     return objArr; 
    } else { 
     if (a.charAt(0) == '.') { 
      var dummyObj = {}; 
      var dir1 = a.match(/^.*?\/(.*?)\//)[1]; 
      dummyObj.id = dir1; 
      dummyObj.text = dir1; 
      dummyObj.parent = '#'; 
      dummyObj.state = { 
       'opened': true, 
        'selected': true 
      }; // not working 
      folderArr.push(dir1); 
      objArr.push(dummyObj); 
      var remStr = a.replace(/^[^\/]*\/[^\/]+/, ''); 
      cat(remStr); 
      return objArr; 
     } else { 
      var dummyObj = {}; 
      var dir1 = a.match(/^.*?\/(.*?)\//)[1]; 
      dummyObj.id = dir1; 
      dummyObj.text = dir1; 
      dummyObj.parent = folderArr[(folderArr.length) - 1]; 
      folderArr.push(dir1); 
      objArr.push(dummyObj); 
      var remStr = a.replace(/^[^\/]*\/[^\/]+/, ''); 
      cat(remStr); 
      return objArr; 
     } 
    } 
} 

HTML

<input type="file" id="files" name="files[]" multiple webkitdirectory /> 
<div id="tree"></div> 

Wszelkie zmiany lub propozycje byłoby bardzo pomocne! Dzięki

+0

Proszę zaksięgować swój kod w pytaniu. – Bergi

+0

Czy dane wejściowe wymagają weryfikacji? Czy to jest posortowane, jak w twoim przykładzie? – Bergi

+0

@Bergi Dodałem jako kodowane zgodnie z życzeniem. –

Odpowiedz

2

Oto prosty algorytm, który powinien zrobić całkiem sprawnie, za pomocą mapy z filepaths do ich identyfikatory:

var idcount = 0; 
var treeJSON = []; 
var idmap = {}; 
function add(dirs) { 
    if (!dirs.length) return "#"; 
    var name = dirs.join("/"); 
    if (name in idmap) 
     return idmap[name]; 
    var dir = dirs.pop(); 
    var parent = add(dirs); 
    var id = "ajson" + ++idcount; 
    treeJSON.push({id: id, parent: parent, text: dir}); 
    return idmap[name] = id; 
} 

var files = e.target.files; // FileList 
for (var i=0; i<files.length; ++i) { 
    var name = files[i].webkitRelativePath; 
    add(name.split("/")); 
} 
return treeJSON; 

(updated jsfiddle demo)

W ten sposób można wykorzystać do aktualizacji dynamicznych:

// initalise JStree here 

var idcount = 0; 
var treeJSON = []; 
var idmap = {}; 
function add(dirs, isfolder) { 
    if (!dirs.length) return "#"; 
    var name = dirs.join("/"); 
    if (name in idmap) { 
     if (isfolder && idmap[name].icon) 
      delete idmap[name].icon; 
     return idmap[name]; 
    } 
    var dir = dirs.pop(); 
    var parent = add(dirs, true); 
    var id = "ajson" + ++idcount; 
    var item = {id: id, parent: parent, text: dir} 

    if (parent == "#") 
     item.state = {opened:true, selected:true}; 
    if (!isfolder && dir.indexOf(".") > 0) 
     item.icon = fileICON; 

    treeJSON.push(item); 
    return idmap[name] = id; 
} 

input.onchange = function(e) { 
    var files = e.target.files; // FileList 
    for (var i=0; i<files.length; ++i) { 
     var name = files[i].webkitRelativePath; 
     add(name.split("/"), false); 
    } 
    // refresh JStree 
}; 
+0

Pliki stają się folderami w [tym skrypcie] (http://jsfiddle.net/bsw5s60j/10/). Think pliki powinny być ignorowane. – skobaljic

+0

@skobaljic Myślę, że to drobny błąd. Ja też się nad tym zastanawiam. Twoja funkcja wydaje się być miła. Przyjmuję, jeśli nie ma innego dobrego rozwiązania. Nadal zajmuję się kodem –

+0

Uważam też, że jest to niewielki problem, ale [Bergi] (http://stackoverflow.com/users/1048572/bergi) powinien to naprawić. – skobaljic

Powiązane problemy