added support for custom listers in PathList(..)...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2015-08-31 20:13:29 +03:00
parent 21c46d5b75
commit 09a67ee983
3 changed files with 161 additions and 52 deletions

View File

@ -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... // XXX need a way to trigger open ecents with touch/mouse...
'/dir 1': function(_, p){ console.log('dir:', p) }, '/dir 1': function(_, p){ console.log('dir:', p) },
'dir 1/option 1': function(_, p){ console.log('option:', 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) }, 'dir 2/option 3': function(_, p){ console.log('option:', p) },
'option 4': 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!')
},
}) })
}) })

View File

@ -503,11 +503,12 @@ var BrowserPrototype = {
// path due to an error, we need to be able to render the new // path due to an error, we need to be able to render the new
// path both in the path and list sections... // path both in the path and list sections...
// NOTE: current behaviour is not wrong, it just not too flexible... // NOTE: current behaviour is not wrong, it just not too flexible...
update: function(path){ update: function(path, list){
path = path || this.path path = path || this.path
var browser = this.dom var browser = this.dom
var that = this var that = this
var focus = browser.find(':focus').length > 0 var focus = browser.find(':focus').length > 0
list = list || this.list
// string path and terminated with '/' -- no selection... // string path and terminated with '/' -- no selection...
if(typeof(path) == typeof('str') && !/[\\\/]/.test(path.trim().slice(-1))){ if(typeof(path) == typeof('str') && !/[\\\/]/.test(path.trim().slice(-1))){
@ -519,7 +520,7 @@ var BrowserPrototype = {
var selection = null var selection = null
} }
// clear the ui...
var p = browser.find('.path').empty() var p = browser.find('.path').empty()
var l = browser.find('.list').empty() var l = browser.find('.list').empty()
@ -583,11 +584,18 @@ var BrowserPrototype = {
} }
// fill the children list... // fill the children list...
// NOTE: this will be set to true if make(..) is called at least once...
var interactive = false var interactive = false
var make = function(p, traversable){ 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 interactive = true
var res = $('<div>') var res = $('<div>')
// handle clicks ONLY when not disabled... // handle clicks ONLY when not disabled...
.click(function(){ .click(function(){
@ -603,8 +611,11 @@ var BrowserPrototype = {
return res 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){ if(!interactive){
res.forEach(make) res.forEach(make)
} }
@ -665,7 +676,7 @@ var BrowserPrototype = {
// every element that was rejected by the predicate / not matching // every element that was rejected by the predicate / not matching
// the pattern. // the pattern.
// //
// By default, <ignore-disabled> is false, thus this will ignore // By default, <ignore-disabled> is true, thus this will ignore
// disabled elements. If <ignore_disabled> is false then disabled // disabled elements. If <ignore_disabled> is false then disabled
// elements will be searched too. // 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': .., // // basic 'file' path...
// 'a/c': .., // // NOTE: this path is non-traversable by default, but if a
// 'd': .., // // 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: // The above definition will be interpreted into the following tree:
// a/
// b
// c
// d
// //
// /
// 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) var PathListPrototype = Object.create(BrowserPrototype)
PathListPrototype.options = { PathListPrototype.options = {
@ -1670,48 +1724,71 @@ PathListPrototype.options = {
var visited = [] var visited = []
return keys // get the '*' listers...
.map(function(k){ var lister = keys
var kp = k.split(/[\\\/]+/g) .filter(function(k){ return k.trim().slice(-1) == '*' })
kp[0] == '' && kp.shift() .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... // use the custom lister (defined by trailing '*')...
var p = kp.splice(0, path.length) if(data !== keys && lister){
if(kp.length == 0 return data[lister].call(this, '/' + path.join('/'), make)
|| p.length < path.length
|| p.filter(function(e, i){ return e != path[i] }).length > 0){
return false
}
// 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... // see if we have a star...
cur = kp.shift() var star = kp.slice(-1)[0] == '*'
if(cur == undefined){ star && kp.pop()
return false
}
if(visited.indexOf(cur) >= 0){ // get and check current path, continue if relevant...
// set element to traversable... var p = kp.splice(0, path.length)
if(kp.length > 0){ if(kp.length == 0
that.filter(cur).removeClass('not-traversable') || 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.... // get current path element if one exists and we did not create it already...
var e = make(cur, kp.length > 0) cur = kp.shift()
if(cur == undefined){
return false
}
// setup handlers... if(visited.indexOf(cur) >= 0){
if(data !== keys && kp.length == 0){ // set element to traversable...
e.on('open', function(){ if(kp.length > 0){
return that.options.data[k].apply(this, arguments) that.filter(cur).removeClass('not-traversable')
}) }
} return false
}
visited.push(cur)
return cur // build the element....
}) var e = make(cur, star || kp.length > 0)
.filter(function(e){ return e !== false })
// 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 PathListPrototype.options.__proto__ = BrowserPrototype.options

View File

@ -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 : */ * vim:set ts=4 sw=4 : */