diff --git a/ui (gen4)/experiments/browse-dialog.html b/ui (gen4)/experiments/browse-dialog.html index 3dbd5f8c..cef7f87f 100755 --- a/ui (gen4)/experiments/browse-dialog.html +++ b/ui (gen4)/experiments/browse-dialog.html @@ -247,11 +247,36 @@ requirejs(['../lib/keyboard', '../object', './browse-dialog'], function(k, o, br // XXX need a way to trigger open ecents with touch/mouse... '/dir 1': function(_, p){ console.log('dir:', p) }, 'dir 1/option 1': function(_, p){ console.log('option:', p) }, - 'dir 1/option 2': function(_, p){ console.log('option:', p) }, + 'dir 1/option 2/': function(_, p){ console.log('option:', p) }, 'dir 2/option 3': function(_, p){ console.log('option:', p) }, 'option 4': function(_, p){ console.log('option:', p) }, - 'option 5': function(_, p){ console.log('option:', p) }, - 'option 6': function(_, p){ console.log('option:', p) }, + + // XXX this is the wrong way to do this, but it shows a bug... + // XXX BUG: for some reason 2 and 3 are set to traversable while + // 1 is not... + 'option 5': function(_, p){ + console.log('option:', p) + + f3.update(p + '/', function(){ return [1, 2, 3] }) + }, + + // render a custom sub-tree... + 'dynamic/*': function(path, make){ + console.log('option:', path) + + return [1,2,3] + .map(function(e){ + make(e, true) + return e + }) + }, + + // this will override the 'dynamic/*' in case of longer + // matches... + 'dynamic/1/1/*': function(path, make){ + make('mooo!/') + make('fooo!') + }, }) }) diff --git a/ui (gen4)/experiments/browse-dialog.js b/ui (gen4)/experiments/browse-dialog.js index c48030e6..685d1321 100755 --- a/ui (gen4)/experiments/browse-dialog.js +++ b/ui (gen4)/experiments/browse-dialog.js @@ -503,11 +503,12 @@ var BrowserPrototype = { // path due to an error, we need to be able to render the new // path both in the path and list sections... // NOTE: current behaviour is not wrong, it just not too flexible... - update: function(path){ + update: function(path, list){ path = path || this.path var browser = this.dom var that = this var focus = browser.find(':focus').length > 0 + list = list || this.list // string path and terminated with '/' -- no selection... if(typeof(path) == typeof('str') && !/[\\\/]/.test(path.trim().slice(-1))){ @@ -519,7 +520,7 @@ var BrowserPrototype = { var selection = null } - + // clear the ui... var p = browser.find('.path').empty() var l = browser.find('.list').empty() @@ -583,11 +584,18 @@ var BrowserPrototype = { } // fill the children list... + // NOTE: this will be set to true if make(..) is called at least once... var interactive = false var make = function(p, traversable){ - traversable = traversable == null ? true : traversable + p = p + '' + var dir = /[\\\/]\s*$/ + traversable = dir.test(p) && traversable == null ? true : traversable + traversable = traversable == null ? false : traversable + p = p.replace(dir, '') + interactive = true + var res = $('
') // handle clicks ONLY when not disabled... .click(function(){ @@ -603,8 +611,11 @@ var BrowserPrototype = { return res } - var res = this.list(path, make) + // build the list... + var res = list.call(this, path, make) + // second API: make is not called and .list(..) returns an Array + // that will get loaded as list items... if(!interactive){ res.forEach(make) } @@ -665,7 +676,7 @@ var BrowserPrototype = { // every element that was rejected by the predicate / not matching // the pattern. // - // By default, is false, thus this will ignore + // By default, is true, thus this will ignore // disabled elements. If is false then disabled // elements will be searched too. // @@ -1640,22 +1651,65 @@ module.makeList = function(elem, list){ /*********************************************************************/ -// This full compatible with List(..) but will parse paths in keys... +// This is similar to List(..) but will parse paths in keys... // -// For example: +// Format: // { -// 'a/b': .., -// 'a/c': .., -// 'd': .., +// // basic 'file' path... +// // NOTE: this path is non-traversable by default, but if a +// // sub-path handler is defined (e.g. 'dir/file/x') then this +// // will be set traversable... +// 'dir/file': function(evt, path){ .. }, // +// // file object at the tree root... +// // NOTE: the leading '/' is optional... +// 'file': function(evt, path){ .. }, +// +// // a directory handler is defined by path ending with '/', +// // set traversable... +// 'dir/dir/': function(evt, path){ .. }, +// +// +// // path lister... +// 'dynamic/*': function(path, make){ .. } // } // -// will translate into: -// a/ -// b -// c -// d +// The above definition will be interpreted into the following tree: // +// / +// dir/ +// file +// dir/ +// file +// dynamic/ +// .. +// +// Here the contents of the '/dynamic/' path are generated by the matching +// lister for that pattern path... +// +// NOTE: there may be multiple matching patterns/listers or a given path +// the one used is the longest match. +// +// +// Handler format: +// function(evt, path){ .. } +// +// This function will be called on the 'open' event for the defined +// item. +// +// +// Lister format: +// function(path, make){ .. } -> list +// +// This function will get called on .update(..) of the matching path. +// +// make(text, traversable) is a list item constructor. +// for more docs see: Browser.list(..) +// +// +// NOTE: currently only trailing '*' are supported. +// +// XXX add support for '*' and '**' glob patterns... var PathListPrototype = Object.create(BrowserPrototype) PathListPrototype.options = { @@ -1670,48 +1724,71 @@ PathListPrototype.options = { var visited = [] - return keys - .map(function(k){ - var kp = k.split(/[\\\/]+/g) - kp[0] == '' && kp.shift() + // get the '*' listers... + var lister = keys + .filter(function(k){ return k.trim().slice(-1) == '*' }) + .filter(function(k){ + return k + .split(/[\\\/]+/) + // remove the '*'... + .slice(0, -1) + // do the match... + .filter(function(e, i){ return e != path[i] }).length == 0 }) + .sort(function(a, b){ return a.length - b.length}) + .pop() - // get and check current path, continue if relevant... - var p = kp.splice(0, path.length) - if(kp.length == 0 - || p.length < path.length - || p.filter(function(e, i){ return e != path[i] }).length > 0){ - return false - } + // use the custom lister (defined by trailing '*')... + if(data !== keys && lister){ + return data[lister].call(this, '/' + path.join('/'), make) + // list via provided paths... + } else { + return keys + .map(function(k){ + var kp = k.split(/[\\\/]+/g) + kp[0] == '' && kp.shift() - // get current path element if one exists and we did not create it already... - cur = kp.shift() - if(cur == undefined){ - return false - } + // see if we have a star... + var star = kp.slice(-1)[0] == '*' + star && kp.pop() - if(visited.indexOf(cur) >= 0){ - // set element to traversable... - if(kp.length > 0){ - that.filter(cur).removeClass('not-traversable') + // get and check current path, continue if relevant... + var p = kp.splice(0, path.length) + if(kp.length == 0 + || p.length < path.length + || p.filter(function(e, i){ return e != path[i] }).length > 0){ + return false } - return false - } - visited.push(cur) - // build the element.... - var e = make(cur, kp.length > 0) + // get current path element if one exists and we did not create it already... + cur = kp.shift() + if(cur == undefined){ + return false + } - // setup handlers... - if(data !== keys && kp.length == 0){ - e.on('open', function(){ - return that.options.data[k].apply(this, arguments) - }) - } + if(visited.indexOf(cur) >= 0){ + // set element to traversable... + if(kp.length > 0){ + that.filter(cur).removeClass('not-traversable') + } + return false + } + visited.push(cur) - return cur - }) - .filter(function(e){ return e !== false }) + // build the element.... + var e = make(cur, star || kp.length > 0) + + // setup handlers... + if(!star && data !== keys && kp.length == 0){ + e.on('open', function(){ + return that.options.data[k].apply(this, arguments) + }) + } + + return cur + }) + .filter(function(e){ return e !== false }) + } }, } PathListPrototype.options.__proto__ = BrowserPrototype.options diff --git a/ui (gen4)/object.js b/ui (gen4)/object.js index baaceb55..32280256 100755 --- a/ui (gen4)/object.js +++ b/ui (gen4)/object.js @@ -64,6 +64,13 @@ function makeConstructor(name, a, b){ } +// super equivalent... +var parent = +module.parent = +function parent(obj){ + return obj.__proto__.__proto__ +} + /********************************************************************** * vim:set ts=4 sw=4 : */