diff --git a/ui (gen4)/lib/widget/browse2.html b/ui (gen4)/lib/widget/browse2.html
index 6de71785..58a17f5f 100755
--- a/ui (gen4)/lib/widget/browse2.html
+++ b/ui (gen4)/lib/widget/browse2.html
@@ -172,7 +172,7 @@ requirejs([
// XXX split this into several dialogues, show each and then combine...
dialog = browser.Browser(
- browser.Browser.PATH_DISPLAY,
+ //browser.items.DisplayFocusedPath,
function(make){
make(['list', 'of', 'text'])
make.group(
@@ -181,6 +181,8 @@ requirejs([
'group item 1 (bare)')
// XXX Q: should we show only one if multiple lines are in sequence???
make('---')
+ make.DisplayFocusedPath({id: 'inline_item_path_display'})
+ make('---')
// embeded browser...
make(browser.Browser(function(make){
make('inlined browser item 0 (open/menu events)', {
@@ -242,7 +244,7 @@ requirejs([
return make(i) }))
},
- browser.Browser.INFO_DISPLAY,
+ //browser.items.DisplayItemInfo,
{
itemButtons: [
['–',
diff --git a/ui (gen4)/lib/widget/browse2.js b/ui (gen4)/lib/widget/browse2.js
index f110d274..649c30c9 100755
--- a/ui (gen4)/lib/widget/browse2.js
+++ b/ui (gen4)/lib/widget/browse2.js
@@ -75,6 +75,8 @@ var collectItems = function(make, items){
//---------------------------------------------------------------------
+// Items...
+//
// XXX general design:
// - each of these can take either a value or a function (constructor)
// - the function has access to Items.* and context
@@ -144,17 +146,6 @@ Items.group = function(...items){
return this
}
-// XXX
-Items.Header = function(...items){
- var that = this
- items = items.length == 1 && items[0] instanceof Array ?
- items[0]
- : items
- // replace the items with the group...
- // XXX
- //this.items.splice(this.items.length, 0, collectItems(this, items))
- return this
-}
// Place list in a sub-list of item...
//
@@ -171,7 +162,7 @@ Items.nest = function(item, list, options){
-//---------------------------------------------------------------------
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Buttons...
var buttons = Items.buttons = {}
@@ -247,8 +238,8 @@ buttons.Delete = [
-//---------------------------------------------------------------------
-// wrappers...
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// Wrappers...
// this is here for uniformity...
Items.Item = function(value, options){ return this(...arguments) }
@@ -273,6 +264,93 @@ Items.EditablePinnedList = function(values){}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// Generators...
+//
+// A generator is a function that creates 1 or more elements and sets up
+// the appropriate interactions...
+//
+// NOTE: these can work both as item generators called from inside
+// .make(..), i.e. as methods of the make constructor, or as
+// generators assigned to .__header__ / .__items__ / .__footer__
+// attributes...
+// NOTE: when re-using these options.id needs to be set so as not to
+// overwrite existing instances data and handlers...
+
+// Focused item path...
+//
+// XXX add search/filter field...
+// XXX add path navigation...
+Items.DisplayFocusedPath = function(make, options){
+ options = make instanceof Function ?
+ options
+ : make
+ options = options || {}
+ make = make instanceof Function ?
+ make
+ : this
+ var dialog = this.dialog || this
+ var tag = options.id || 'item_path_display'
+ // indicator...
+ var e = make('CURRENT_PATH', {
+ id: tag,
+ cls: 'path',
+ buttons: options.headerButtons
+ || (dialog.options || {}).headerButtons
+ || [], })
+ .last()
+ // event handlers...
+ dialog
+ .off('*', tag)
+ .on('focus',
+ function(){
+ e.value = this.pathArray
+ this.renderItem(e) },
+ tag) }
+
+// Item info...
+//
+// Show item .info or .alt text.
+//
+// This will show info for items that are:
+// - focused
+// - hovered (not yet implemented)
+//
+// XXX use focused elements and not just item...
+// XXX add on mouse over...
+Items.DisplayItemInfo = function(make, options){
+ options = make instanceof Function ?
+ options
+ : make
+ options = options || {}
+ make = make instanceof Function ?
+ make
+ : this
+ var dialog = this.dialog || this
+ var tag = options.id || 'item_info_display'
+
+ // indicator...
+ var e = make('INFO', {
+ id: tag,
+ cls: 'info',
+ buttons: options.footerButtons
+ || (dialog.options || {}).footerButtons
+ || [], })
+ .last()
+ // event handlers...
+ dialog
+ .off('*', tag)
+ .on('focus',
+ function(){
+ var focused = this.focused
+ e.value = focused.info
+ || focused.alt
+ || ' '
+ this.renderItem(e) },
+ tag) }
+
+
+
//---------------------------------------------------------------------
// Item...
@@ -792,7 +870,6 @@ var BaseBrowserClassPrototype = {
// sense at this time -- need to think about this more
// carefully + strictly document the result...
var BaseBrowserPrototype = {
- // XXX should we mix item/list options or separate them into sub-objects???
options: {
sections: [
'header',
@@ -834,6 +911,12 @@ var BaseBrowserPrototype = {
// certain context...
// No, currently this is not needed.
itemTemplate: {},
+
+ // If not null these indicate the name of the generator to use,
+ // when the client does not supply the corresponding function
+ // (i.e. Items[name])
+ defaultHeader: null,
+ defaultFooter: null,
},
@@ -865,7 +948,8 @@ var BaseBrowserPrototype = {
__header: null,
get header(){
this.__header
- || (this.__header__
+ || ((this.__header__
+ || Items[this.options.defaultHeader])
&& this.make({section: 'header'}))
return this.__header || [] },
set header(value){
@@ -880,7 +964,8 @@ var BaseBrowserPrototype = {
__footer: null,
get footer(){
this.__footer
- || (this.__footer__
+ || ((this.__footer__
+ || Items[this.options.defaultFooter])
&& this.make({section: 'footer'}))
return this.__footer || [] },
set footer(value){
@@ -1204,9 +1289,15 @@ var BaseBrowserPrototype = {
sections = (sections instanceof Array ?
sections
: [sections])
+ .map(function(name){
+ return [
+ name,
+ that[`__${name}__`]
+ || Items[options[`default${name.capitalize()}`]],
+ ] })
// keep only sections we know how to make...
- .filter(function(name){
- return that[`__${name}__`] instanceof Function })
+ .filter(function([_, handler]){
+ return !!handler })
// item constructor...
//
@@ -1320,7 +1411,7 @@ var BaseBrowserPrototype = {
// build the sections...
sections
- .forEach(function(name){
+ .forEach(function([name, handler]){
// setup closure for make(..)...
section = name
make_called = false
@@ -1328,7 +1419,8 @@ var BaseBrowserPrototype = {
list = make.items = that[name] = []
// build list...
- var res = that[`__${name}__`](make,
+ var res = handler.call(that,
+ make,
// XXX not sure about this -- revise options handling...
options ?
Object.assign(
@@ -2474,12 +2566,6 @@ var BaseBrowserPrototype = {
&& that.expand([...nodes]) }) },
- // XXX do we need edit ability here?
- // i.e. .set(..), .remove(..), .sort(..), ...
- // ...if we are going to implement editing then we'll need to
- // callback the user code or update the user state...
-
-
// Renderers...
//
// .renderFinalize(header, items, footer, context)
@@ -3140,17 +3226,51 @@ var BaseBrowserPrototype = {
close: makeEventMethod('close', function(evt, reason){}),
- // XXX should we update on init....
+ // Constructor...
+ //
+ // BaseBrowser(items(make, options)[, options])
+ // -> browser
+ //
+ // Set header and items generators...
+ // BaseBrowser(
+ // header(make, options) | null,
+ // items(make, options)[, options])
+ // -> browser
+ //
+ // Set both header and footer...
+ // BaseBrowser(
+ // header(make, options) | null,
+ // items(make, options),
+ // footer(make, options) | null[, options])
+ // -> browser
+ //
+ //
+ // NOTE: of either header or footer are set to null and
+ // options.defaultHeader / options.defaultFooter are set then
+ // they will be used. To disable header footer completely set
+ // the corresponding default option to null too.
+ // NOTE: for options.defaultHeader / options.defaultFooter the docs
+ // are in the options section.
+ //
+ // XXX should we .update(..) on init....
__init__: function(func, options){
var args = [...arguments]
+
// header (optional)...
- args[1] instanceof Function
- && (this.__header__ = args.shift())
+ args[1] instanceof Function ?
+ (this.__header__ = args.shift())
+ : args[0] == null
+ && args.shift()
+
// items...
this.__items__ = args.shift()
+
// footer (optional)..
- args[0] instanceof Function
- && (this.__footer__ = args.shift())
+ args[0] instanceof Function ?
+ (this.__footer__ = args.shift())
+ : args[0] == null
+ && args.shift()
+
// options (optional)...
this.options = Object.assign(
Object.create(this.options || {}),
@@ -3422,55 +3542,6 @@ var updateElemClass = function(action, cls, handler){
var HTMLBrowserClassPrototype = {
__proto__: BaseBrowser,
-
- // Headers...
- //
- // Item path...
- // XXX add search/filter field...
- // XXX add path navigation...
- PATH_DISPLAY: function(make, options){
- // indicator...
- var e = make('CURRENT_PATH', {
- id: 'item_path_display',
- cls: 'path',
- buttons: (options || {}).headerButtons
- || (this.options || {}).headerButtons
- || [], })
- .last()
- // event handlers...
- this
- .off('*', 'item_path_display')
- .on('focus',
- function(){
- e.value = this.pathArray
- this.renderItem(e) },
- 'item_path_display') },
-
- // Footers...
- //
- // Item info...
- // XXX use focused element...
- // XXX add on mouse over...
- INFO_DISPLAY: function(make, options){
- // indicator...
- var e = make('INFO', {
- id: 'item_info_display',
- cls: 'info',
- buttons: (options || {}).footerButtons
- || (this.options || {}).footerButtons
- || [], })
- .last()
- // event handlers...
- this
- .off('*', 'item_info_display')
- .on('focus',
- function(){
- var focused = this.focused
- e.value = focused.info
- || focused.alt
- || ' '
- this.renderItem(e) },
- 'item_info_display') },
}
// XXX render of nested lists does not affect the parent list(s)...
@@ -3485,9 +3556,8 @@ var HTMLBrowserPrototype = {
options: {
__proto__: BaseBrowser.prototype.options,
- // XXX not used yet...
- //defaultHeader: 'PATH_DISPLAY',
- //defaultFooter: 'INFO_DISPLAY',
+ defaultHeader: 'DisplayFocusedPath',
+ //defaultFooter: 'DisplayItemInfo',
// for more docs see:
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
@@ -4483,18 +4553,6 @@ var HTMLBrowserPrototype = {
// Filtering/search mode...
// XXX
-
- /*/ XXX this should only work on root...
- __init__: function(func, options){
- var args = [...arguments]
- options = args[args.length-1] instanceof Function ?
- {}
- : args[args.length-1]
- ;(args[1] instanceof Function)
- && this.constructor[options.defaultHeader]
- && args.unshift(this.constructor[options.defaultHeader])
- return object.parent(HTMLBrowserPrototype.__init__, this).call(this, ...args) },
- //*/
}