Durchsuchbare Dokumentation aufrufen | Zurück zur Dokumentationsübersicht
Navigation: Dokumentationen agorum core > Übersicht tags
Dieses Widget ist eine Erweiterung des BasicTree-Widgets, das dynamisches Nachladen von Knoten erlaubt.
Ein typischer Einsatzzweck für dieses Widget ist die Darstellung eines Ordnerbaums. Ordnerbäume sind potenziell groß, weswegen sie nicht vollständig im Voraus geladen werden sollten:
let objects = require('common/objects'); let aguila = require('common/aguila'); const LOAD_DEPTH = 1; let byType = (a, b) => (a.isFolder ? 0 : 1) - (b.isFolder ? 0 : 1); let byName = (a, b) => (a.displayName || '').localeCompare(b.displayName); let fileSort = (a, b) => byType(a, b) || byName(a, b); let build = (id, object, depth) => { let node = { text: object.displayName, id: id }; if (object.isFolder) { if (depth > 0) { node.items = object.items().sort(fileSort).map(item => build(id + '|' + item.ID, item, depth - 1)); } else { node.veiled = true; } } else { node.icon = 'aguila-icon-page-white-text'; } return node; }; let tree = aguila.create({ type: 'agorum.tree', width: 500, height: 800, hideRoot: true, data: { id: '', items: [ { id: '/agorum/roi/Files', text: 'Dateien', veiled: true }, { id: 'home:MyFiles', text: 'Eigene Dateien', veiled: true } ] } }); tree.on('reveal', id => aguila.fork(() => build(id, objects.find(id), LOAD_DEPTH)).then(node => tree.update(node))); tree;
Löst aus, wenn ein Benutzer einen als veiled markierten Knoten öffnet.
Das System erwartet, dass dieser Knoten danach durch die Funktion update() aktualisiert wird.
Beispiel
tree.on('reveal', id => { // TODO: update the tree node referenced by the id });
Wert | Beschreibung |
---|---|
true | Erzwingt die Darstellung eines Rahmens um dieses Widgets, sofern unterstützt. |
false | Unterdrückt die Darstellung eines Rahmens um dieses Widgets, sofern unterstützt. |
Die Struktur der data-Property entspricht derjenigen des BasicTree-Widgets, allerdings mit einer Erweiterung.
Statt die Unterknoten eines nicht-Blatt-Elements explizit anzugeben, können Sie den Knoten als veiled markieren. Das signalisiert dem Client, dass dieser Knoten zwar Unterknoten besitzt, diese jedoch noch nicht mitgeschickt wurden.
Wird ein derartig markierter Knoten auf dem Client geöffnet, löst das Event reveal aus, was das Widget dazu auffordert, den Knoten samt seiner Unterknoten zu aktualisieren.
Beispiel
tree.data = { text: 'Root', id: 'Root', items: [ { text: 'Element 1', id: 'Element 1', items: [] }, { text: 'Element 2', id: 'Element 2', veiled: true } ] };
Ersetzt einen bereits im Baum vorhandenen Knoten mit derselben ID durch den übergebenen Knoten. Das kann geschehen:
• nach Aufforderung durch den Client, wenn ein reveal-Event ausgelöst wurde und ein noch nicht vollständig geladener Knoten weiter geladen werden soll
• ohne Aufforderung, etwa, weil sich die Daten geändert haben und der Baum aktualisiert werden soll
Beispiel
Im Beispiel wird als Reaktion auf das reveal-Event asynchron der Unterbaum des gewünschten Knotens nachgeladen und danach der Baum per update() aktualisiert.
tree.update({ id: '<ID eines vorhandenen Knotens>', text: '<Neuer Text>', items: [ <Neue Unterknoten> ] });
let objects = require('common/objects'); let aguila = require('common/aguila'); // sample tree level definitions let levels = [ { categories: [ { text: '< 1kB', query: 'contentsize:[0 TO 1000}' }, { text: '1kB - 1MB', query: 'contentsize:[1000 TO 1000000]' }, { text: '> 1MB', query: 'contentsize:{1000000 TO *]' } ] }, { categories: [ { text: 'Dieses Jahr', query: 'createdate_date_range:[NOW/YEAR TO *]' }, { text: 'älter', query: 'createdate_date_range:[* TO NOW/YEAR}' } ] }, { terms: 'nameextension' }, { categories: [ { text: 'A-M', query: 'name_ci:[A* TO M*]' }, { text: 'N-Z', query: 'name_ci:[N* TO Z*]' }, { text: '0-9', query: 'name_ci:[0* TO 9*]' } ] } ]; let search = (id, query) => { // decode the query path up to this node let path = id.split('|').filter(x => x).map(decodeURIComponent); // look up the next tree level definition let next = levels[path.length]; // prepare the query object let q = objects.query([ query ].concat(path).join(' ')); if (next) { // next tree level is still a faceting level if (next.categories) { // category faceting (using set queries) let f = {}; next.categories.forEach((category, i) => { f[i.toFixed(0)] = { type: 'query', q: category.query }; }); let facets = q.facets(f).limit(0).search().facets; return next.categories.map((category, i) => { let count = (facets[i.toFixed(0)] || {}).count; return { empty: !count, text: category.text + (count ? (' (' + count.toFixed(0) + ')') : ''), query: category.query }; }); } else if (next.terms) { // term faceting (using a metadata field name) let terms = q.facets({ terms: { type: 'terms', field: next.terms, limit: 100, missing: true, sort: 'index' } }).limit(0).search().facets.terms || {}; let results = (terms.buckets || []).map(bucket => ({ text: bucket.val + ' (' + bucket.count.toFixed(0) + ')', query: next.terms + ':' + bucket.val })); if (terms.missing && terms.missing.count) { results.push({ text: '- (' + terms.missing.count.toFixed(0) + ')', query: '(* NOT ' + next.terms + ':*)' }); } return results; } else { throw new Error('Unsupported level definition: ' + JSON.stringify(next)); } } else { return q.limit(100).sort('name_ci').search('name', 'id').rows.map(row => ({ text: row.name, id: row.id })); } }; let build = (id, query) => ({ id: id, items: search(id, query).map(result => { let node = { text: result.text }; if (result.id) { // object result - show as leaf node node.id = result.id; node.icon = 'aguila-icon-page-white-text'; } else { // facet result - show as folder node, encoding the query up to this point inside its ID node.id = id + '|' + encodeURIComponent(result.query); if (result.empty) { node.items = []; } else { node.veiled = true; } } return node; }) }); let widget = aguila.create({ type: 'agorum.vbox', width: 500, height: 800, items: [ { name: 'query', type: 'agorum.textInput' }, { name: 'tree', type: 'agorum.tree', border: true, flexible: true, hideRoot: true } ] }); let query = widget.down('query'); let tree = widget.down('tree'); // begin searching immediately and each time the enter key is pressed inside the query field let current; let start = () => { current = query.value || '*'; aguila.fork(() => build('', current)).then(node => tree.data = node); }; start(); query.on('enter', start); // continue faceting on reveal tree.on('reveal', id => aguila.fork(() => build(id, current)).then(node => tree.update(node))); query.focus(); widget;