experimenting with alternative history dialog...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2017-02-05 08:22:39 +03:00
parent e88a84bfda
commit d758dbc8d4
2 changed files with 196 additions and 43 deletions

View File

@ -419,6 +419,8 @@ var URLHistoryUIActions = actions.Actions({
// - true | undefined - always remove // - true | undefined - always remove
// - flase - never remove // - flase - never remove
// - [ 'open', 'close' ] - explicitly select event // - [ 'open', 'close' ] - explicitly select event
//
// XXX do we need this???
'url-history-list-clear': ['open', 'close'], 'url-history-list-clear': ['open', 'close'],
// If true pushing the pin item button will also focus the item // If true pushing the pin item button will also focus the item
@ -636,6 +638,127 @@ var URLHistoryUIActions = actions.Actions({
return o return o
})], })],
// XXX need to sort pins...
// XXX need to save pins...
// XXX 'to top' button???
listURLHistory2: ['History|File/Location history (new)...',
widgets.makeUIDialog(function(){
var that = this
var data
var cur = this.location.path
var to_remove = []
// save state:
// - save pins and pin order... (XXX)
// - remove stirked out elements...
var save = function(){
// XXX save pins/order...
data.pins.forEach(function(p){
//that.toggleURLPinned('on')
})
// remove items...
to_remove.forEach(function(e){
that.dropURLFromHistory(e)
})
to_remove = []
}
var makeHistoryList = function(fs_state){
fs_state = fs_state || {}
var history = Object.keys(that.url_history).reverse()
// XXX need pin order...
var pinned = []
var list = history
// NOTE: this might get a little slow for
// very large sets...
.map(function(p){
// pinned items...
// NOTE: yes direct access is faster, but
// calling the toggler (common API) here
// will isolate the level knowledge to a
// single point which will simplify things
// if anything changes...
//that.url_history[p].pinned ?
// XXX need pin order...
that.toggleURLPinned(p, '?') == 'on' ?
// XXX
pinned.push(p)
: null
return p
})
return {
paths: list,
pins: pinned,
}
}
var makeDisabledChecker = function(fs_state){
return function(url){
// see of we need a full refresh or use the
// last fs_state...
if(url in fs_state){
var d = fs_state[url]
} else {
var d = !that.checkURLFromHistory(url)
fs_state[url] = d
}
return d
}
}
// persistent state...
var fs_state = {}
var dialog = browse.makeLister(null, function(path, make){
// live update...
data = data == null ? makeHistoryList(fs_state) : data
// empty list...
if(data.paths.length == 0){
make.Action('No history...', {disabled: true})
} else {
make.EditablePinnedList(data.paths, data.pins, {
list_id: 'history',
new_item: false,
pins_sortable: true,
isItemDisabled: makeDisabledChecker(fs_state),
to_remove: to_remove,
})
}
make
.done()
// highlight the current item...
.then(function(){
dialog
.filter(`"${cur}"`)
.addClass('highlighted') })
},
{
selected: cur,
})
.open(function(evt, path){
save()
dialog.close()
that.openURLFromHistory(path)
})
.on('close', function(){
save()
})
return dialog
})],
}) })
var URLHistoryUI = var URLHistoryUI =

View File

@ -395,15 +395,17 @@ function(list){
// //
// options format: // options format:
// { // {
// // test if item is disabled... // // test if item is disabled/hidden...
// // // //
// // NOTE: if this is a string or regexp, this is used via // // NOTE: if this is a string or regexp, this is used via
// // .replace(..) so the match will get removed from the item // // .replace(..) so the match will get removed from the item
// // text, unless prevented via regexp. // // text, unless prevented via regexp.
// isItemDisabled: <pattern> | <function>, // isItemDisabled: <pattern> | <function>,
// isItemHidden: <pattern> | <function>,
// //
// // if true, disabled items will not get created... // // if true, disabled/hidden items will not get created...
// skipDisabledItems: false, // skipDisabledItems: false,
// skipHiddenItems: false,
// //
// // if true, group the items into a <span> element... // // if true, group the items into a <span> element...
// groupList: false, // groupList: false,
@ -418,48 +420,56 @@ function(data, options){
var res = [] var res = []
var keys = data instanceof Array ? data : Object.keys(data) var keys = data instanceof Array ? data : Object.keys(data)
options = options || {} options = options || {}
var test = typeof(options.isItemDisabled) == typeof('str') ?
RegExp(options.isItemDisabled) var predicates = {
: options.isItemDisabled disabled: typeof(options.isItemDisabled) == typeof('str') ?
RegExp(options.isItemDisabled)
: options.isItemDisabled,
hidden: typeof(options.isItemHidden) == typeof('str') ?
RegExp(options.isItemHidden)
: options.isItemHidden,
}
keys.forEach(function(k){ keys.forEach(function(k){
var txt = k var txt
var opts = Object.create(options) var opts = Object.create(options)
if(test){ Object.keys(predicates).forEach(function(p){
txt = k instanceof Array ? k[0] : k var test = predicates[p]
// item passes disabled predicate... if(test){
if(test instanceof Function // check only the first item...
&& test(txt)){ txt = txt || (k instanceof Array ? k[0] : k)
opts.disabled = true
if(options.skipDisabledItems){ // item passes disabled predicate...
return if(test instanceof Function
&& test(txt)){
opts[p] = true
// item matches disabled test...
} else if(test instanceof RegExp
&& test.test(txt)){
var t = txt.replace(test, '')
opts.disabled = true
txt = k instanceof Array ?
[t].concat(k.slice(1))
: t
// no match -- restore text...
} else {
txt = k
} }
// item matches disabled test...
} else if(test instanceof RegExp
&& test.test(txt)){
var t = txt.replace(test, '')
opts.disabled = true
txt = k instanceof Array ?
[t].concat(k.slice(1))
: t
if(options.skipDisabledItems){
return
}
// no match -- restore text...
} else {
txt = k
} }
})
if((opts.disabled && opts.skipDisabledItems)
|| (opts.hidden && opts.skipHiddenItems)){
return
} }
var elem = make(txt, opts) var elem = make(txt || k, opts)
keys !== data && data[k] keys !== data && data[k]
&& elem.on('open', data[k]) && elem.on('open', data[k])
@ -555,6 +565,10 @@ function(data, options){
// // list length limit is reached... // // list length limit is reached...
// overflow: function(selected){ ... }, // overflow: function(selected){ ... },
// //
// // list if items to remove, if not given this will be maintained
// // internally
// to_remove: null | <list>,
//
// // Special buttons... // // Special buttons...
// // // //
// // NOTE: these can be used only if .sort if not set. // // NOTE: these can be used only if .sort if not set.
@ -644,7 +658,10 @@ function(list, options){
options = options || {} options = options || {}
var id = options.list_id || 'default' var id = options.list_id || 'default'
var to_remove = dialog.__to_remove[id] = dialog.__to_remove[id] || [] var to_remove = dialog.__to_remove[id] =
options.to_remove
|| dialog.__to_remove[id]
|| []
// make a copy of options, to keep it safe from changes we are going // make a copy of options, to keep it safe from changes we are going
// to make... // to make...
@ -893,7 +910,9 @@ function(list, options){
// remove items... // remove items...
to_remove.forEach(function(e){ to_remove.forEach(function(e){
lst.splice(lst.indexOf(e), 1) var i = lst.indexOf(e)
i >= 0
&& lst.splice(i, 1)
}) })
// sort... // sort...
@ -992,8 +1011,8 @@ function(list, pins, options){
i < 0 ? i < 0 ?
buttons.push(pin) buttons.push(pin)
: (buttons[i] = pin) : (buttons[i] = pin)
options.isItemDisabled = function(e){ return pins.indexOf(e) >= 0 } options.isItemHidden = function(e){ return pins.indexOf(e) >= 0 }
options.skipDisabledItems = options.skipDisabledItems !== false ? true : false options.skipHiddenItems = options.skipHiddenItems !== false ? true : false
//----------------------------------------- setup options: pins --- //----------------------------------------- setup options: pins ---
var pins_options = { var pins_options = {
@ -1001,7 +1020,7 @@ function(list, pins, options){
new_item: false, new_item: false,
length_limit: options.pins_length_limit || 10, length_limit: options.pins_length_limit || 10,
isItemDisabled: null, isItemHidden: null,
} }
pins_options.__proto__ = options pins_options.__proto__ = options
var sortable = pins_options.sortable = var sortable = pins_options.sortable =
@ -1217,6 +1236,7 @@ var BrowserPrototype = {
// NOTE: this can be a number indicating the item to select when // NOTE: this can be a number indicating the item to select when
// load is done. // load is done.
//path: null, //path: null,
//selected: null,
//show_path: true, //show_path: true,
@ -1935,7 +1955,8 @@ var BrowserPrototype = {
//-------------------------- prepare the path and selection --- //-------------------------- prepare the path and selection ---
// 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))){
path = this.path2list(path) path = this.path2list(path)
var selection = path.pop() var selection = path.pop()
@ -2341,6 +2362,7 @@ var BrowserPrototype = {
make.done = function(){ make.done = function(){
var s = l.find('.selected') var s = l.find('.selected')
s.length > 0 && that.select(s) s.length > 0 && that.select(s)
return deferred
} }
make.dialog = this make.dialog = this
@ -3586,6 +3608,7 @@ var BrowserPrototype = {
// load the initial state... // load the initial state...
// NOTE: path can be a number so simply or-ing here is a bad idea... // NOTE: path can be a number so simply or-ing here is a bad idea...
var path = options.path != null ? options.path : that.path var path = options.path != null ? options.path : that.path
var selected = options.selected
typeof(path) == typeof(123) ? typeof(path) == typeof(123) ?
// select item number... // select item number...
that that
@ -3597,9 +3620,16 @@ var BrowserPrototype = {
.update(path || '/') .update(path || '/')
// Select the default path... // Select the default path...
.then(function(){ .then(function(){
// in case we have a manually selected item but that was // explicit config selection...
// not aligned... // NOTE: this takes precedence over the path syntax...
that.selected && that.select() }) // XXX not sure if we need this...
// ...currently this is used only when path is
// a list and we need to also select an item...
selected ? that.select(selected)
// we have a manually selected item but that was
// not aligned...
: that.selected ? that.select()
: null })
}, },
} }