mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-28 18:00:09 +00:00
refactored .make(..) and Items (Make(..))
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
4fac28a8a9
commit
b7121808cb
@ -81,348 +81,349 @@ var collectItems = function(make, items){
|
|||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
// Item constructors...
|
// Item constructors...
|
||||||
//
|
|
||||||
// XXX general design:
|
|
||||||
// - each of these can take either a value or a function (constructor)
|
|
||||||
// - the function has access to Items.* and context
|
|
||||||
// - the constructor can be called from two contexts:
|
|
||||||
// - external
|
|
||||||
// called from the module or as a function...
|
|
||||||
// calls the passed constructor (passing context)
|
|
||||||
// builds the container
|
|
||||||
// - nested
|
|
||||||
// called from constructor function...
|
|
||||||
// calls constructor (if applicable)
|
|
||||||
// builds item(s)
|
|
||||||
// XXX need a way to pass container constructors (a-la ui-widgets dialog containers)
|
|
||||||
// - passing through the context (this) makes this more flexible...
|
|
||||||
// - passing via args fixes the signature which is a good thing...
|
|
||||||
//
|
|
||||||
//
|
|
||||||
|
|
||||||
// XXX
|
var Items =
|
||||||
// XXX can't use Object.assign(..) here as it will not copy props...
|
object.mixinFlat(function(){}, {
|
||||||
var Items = module.items = function(){}
|
dialog: null,
|
||||||
|
called: false,
|
||||||
|
|
||||||
|
|
||||||
// placeholders...
|
// Props...
|
||||||
Items.dialog = null
|
//
|
||||||
Items.items = null
|
// NOTE: writing to .items will reset .called to false...
|
||||||
|
__items: undefined,
|
||||||
|
get items(){
|
||||||
|
return this.__items },
|
||||||
|
set items(value){
|
||||||
|
this.called = false
|
||||||
|
this.__items = value },
|
||||||
|
|
||||||
|
|
||||||
|
buttons: {
|
||||||
|
//
|
||||||
|
// Draw checked checkboz is <attr> is true...
|
||||||
|
// Checkbox('attr')
|
||||||
|
//
|
||||||
|
// Draw checked checkboz is <attr> is false...
|
||||||
|
// Checkbox('!attr')
|
||||||
|
//
|
||||||
|
// XXX rename -- distinguish from actual button...
|
||||||
|
Checkbox: function(item, attr){
|
||||||
|
return (attr[0] == '!'
|
||||||
|
&& !item[attr.slice(1)])
|
||||||
|
|| item[attr] ?
|
||||||
|
'☐'
|
||||||
|
: '☑' },
|
||||||
|
// XXX can we make these not use the same icon...
|
||||||
|
ToggleDisabled: [
|
||||||
|
'Checkbox: "disabled"',
|
||||||
|
'toggleDisabled: item',
|
||||||
|
true,
|
||||||
|
{
|
||||||
|
alt: 'Disable/enable item',
|
||||||
|
cls: 'toggle-disabled',
|
||||||
|
}],
|
||||||
|
ToggleHidden: [
|
||||||
|
'Checkbox: "hidden"',
|
||||||
|
'toggleHidden: item',
|
||||||
|
{
|
||||||
|
alt: 'Show/hide item',
|
||||||
|
cls: 'toggle-hidden',
|
||||||
|
}],
|
||||||
|
ToggleSelected: [
|
||||||
|
'Checkbox: "selected"',
|
||||||
|
'toggleSelect: item',
|
||||||
|
{
|
||||||
|
alt: 'Select/deselect item',
|
||||||
|
cls: 'toggle-select',
|
||||||
|
}],
|
||||||
|
// NOTE: this button is disabled for all items but the ones with .children...
|
||||||
|
ToggleCollapse: [
|
||||||
|
function(item){
|
||||||
|
return !item.children ?
|
||||||
|
// placeholder...
|
||||||
|
' '
|
||||||
|
: item.collapsed ?
|
||||||
|
'+'
|
||||||
|
: '-' },
|
||||||
|
'toggleCollapse: item',
|
||||||
|
// disable button for all items that do not have children...
|
||||||
|
function(item){
|
||||||
|
return 'children' in item },
|
||||||
|
{
|
||||||
|
alt: 'Collapse/expand item',
|
||||||
|
cls: function(item){
|
||||||
|
return 'children' in item ?
|
||||||
|
'toggle-collapse'
|
||||||
|
: ['toggle-collapse', 'blank'] },
|
||||||
|
}],
|
||||||
|
// XXX delete button -- requires .markDelete(..) action...
|
||||||
|
Delete: [
|
||||||
|
'×',
|
||||||
|
'markDelete: item',
|
||||||
|
{
|
||||||
|
alt: 'Mark item for deletion',
|
||||||
|
cls: 'toggle-delete',
|
||||||
|
//keys: ['Delete', 'd'],
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
// Last item created...
|
// Getters...
|
||||||
// XXX not sure about this...
|
|
||||||
// XXX should this be a prop???
|
// Last item created...
|
||||||
Items.last = function(){
|
// XXX not sure about this...
|
||||||
return (this.items || [])[this.items.length - 1] }
|
// XXX should this be a prop???
|
||||||
|
last: function(){
|
||||||
|
return (this.items || [])[this.items.length - 1] },
|
||||||
|
|
||||||
|
|
||||||
// Group a set of items...
|
// Constructors/modifiers...
|
||||||
//
|
|
||||||
// .group(make(..), ..)
|
// Group a set of items...
|
||||||
// .group([make(..), ..])
|
//
|
||||||
// -> make
|
// .group(make(..), ..)
|
||||||
//
|
// .group([make(..), ..])
|
||||||
//
|
// -> make
|
||||||
// Example:
|
//
|
||||||
// make.group(
|
//
|
||||||
// make('made item'),
|
// Example:
|
||||||
// 'literal item',
|
// make.group(
|
||||||
// ...)
|
// make('made item'),
|
||||||
//
|
// 'literal item',
|
||||||
//
|
// ...)
|
||||||
// NOTE: see notes to collectItems(..) for more info...
|
//
|
||||||
//
|
//
|
||||||
// XXX do we need to pass options to groups???
|
// NOTE: see notes to collectItems(..) for more info...
|
||||||
Items.group = function(...items){
|
//
|
||||||
var that = this
|
// XXX do we need to pass options to groups???
|
||||||
items = items.length == 1 && items[0] instanceof Array ?
|
group: function(...items){
|
||||||
items[0]
|
var that = this
|
||||||
: items
|
items = items.length == 1 && items[0] instanceof Array ?
|
||||||
// replace the items with the group...
|
items[0]
|
||||||
this.items.splice(this.items.length, 0, collectItems(this, items))
|
: items
|
||||||
return this
|
// replace the items with the group...
|
||||||
}
|
this.items.splice(this.items.length, 0, collectItems(this, items))
|
||||||
|
return this },
|
||||||
|
|
||||||
|
// Place list in a sub-list of item...
|
||||||
|
//
|
||||||
|
// Examples:
|
||||||
|
// make.nest('literal header', [
|
||||||
|
// 'literal item',
|
||||||
|
// make('item'),
|
||||||
|
// ...
|
||||||
|
// ])
|
||||||
|
//
|
||||||
|
// make.nest(make('header'), [
|
||||||
|
// 'literal item',
|
||||||
|
// make('item'),
|
||||||
|
// ...
|
||||||
|
// ])
|
||||||
|
//
|
||||||
|
nest: function(item, list, options){
|
||||||
|
options = options || {}
|
||||||
|
//options = Object.assign(Object.create(this.options || {}), options || {})
|
||||||
|
options = Object.assign({},
|
||||||
|
{ children: list instanceof Array ?
|
||||||
|
collectItems(this, list)
|
||||||
|
: list },
|
||||||
|
options)
|
||||||
|
return item === this ?
|
||||||
|
((this.last().children = options.children), this)
|
||||||
|
: this(item, options) },
|
||||||
|
|
||||||
|
|
||||||
// Place list in a sub-list of item...
|
// Wrappers...
|
||||||
//
|
|
||||||
// Examples:
|
// this is here for uniformity...
|
||||||
// make.nest('literal header', [
|
Item: function(value, options){
|
||||||
// 'literal item',
|
return this(...arguments) },
|
||||||
// make('item'),
|
|
||||||
// ...
|
Empty: function(value){},
|
||||||
// ])
|
|
||||||
//
|
Separator: function(){
|
||||||
// make.nest(make('header'), [
|
return this('---') },
|
||||||
// 'literal item',
|
Spinner: function(){
|
||||||
// make('item'),
|
return this('...') },
|
||||||
// ...
|
|
||||||
// ])
|
Heading: function(value, options){
|
||||||
//
|
var cls = 'heading'
|
||||||
Items.nest = function(item, list, options){
|
options = options || {}
|
||||||
options = options || {}
|
options.cls = options.cls instanceof Array ?
|
||||||
//options = Object.assign(Object.create(this.options || {}), options || {})
|
options.cls.concat([cls])
|
||||||
options = Object.assign({},
|
: typeof(options.cls) == typeof('str') ?
|
||||||
{ children: list instanceof Array ?
|
options.cls +' '+ cls
|
||||||
collectItems(this, list)
|
: [cls]
|
||||||
: list },
|
options.buttons = options.buttons
|
||||||
options)
|
|| this.dialog.options.headingButtons
|
||||||
return item === this ?
|
return this(value, options) },
|
||||||
((this.last().children = options.children), this)
|
Action: function(value, options){},
|
||||||
: this(item, options)
|
ConfirmAction: function(value){},
|
||||||
}
|
Editable: function(value){},
|
||||||
|
|
||||||
|
// lists...
|
||||||
|
List: function(values){},
|
||||||
|
EditableList: function(values){},
|
||||||
|
EditablePinnedList: function(values){},
|
||||||
|
|
||||||
|
// Special list components...
|
||||||
|
//Items.ListPath = function(){},
|
||||||
|
//Items.ListTitle = function(){},
|
||||||
|
|
||||||
|
// XXX EXPERIMENTAL...
|
||||||
|
//
|
||||||
|
// options:
|
||||||
|
// {
|
||||||
|
// showOKButton: <bool>,
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
Confirm: function(message, accept, reject, options){
|
||||||
|
return this(message,
|
||||||
|
Object.assign({
|
||||||
|
// XXX should the user be able to merge buttons from options???
|
||||||
|
buttons: [
|
||||||
|
...(reject instanceof Function ?
|
||||||
|
[['$Cancel', reject]]
|
||||||
|
: []),
|
||||||
|
...(accept instanceof Function
|
||||||
|
&& (options || {}).showOKButton ?
|
||||||
|
[['$OK', accept]]
|
||||||
|
: []), ],
|
||||||
|
},
|
||||||
|
accept ?
|
||||||
|
{open: accept}
|
||||||
|
: {},
|
||||||
|
options || {})) },
|
||||||
|
|
||||||
|
|
||||||
|
// 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...
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// Make item generator...
|
||||||
// Buttons...
|
//
|
||||||
var buttons = Items.buttons = {}
|
makeDisplayItem: function(text, options){
|
||||||
|
var args = [...arguments]
|
||||||
|
return function(make, options){
|
||||||
|
make(...args) } },
|
||||||
|
|
||||||
//
|
// Make confirm item generator...
|
||||||
// Draw checked checkboz is <attr> is true...
|
//
|
||||||
// Checkbox('attr')
|
// XXX move this to Item.Confirm(..) and reuse that...
|
||||||
//
|
makeDisplayConfirm: function(message, accept, reject){
|
||||||
// Draw checked checkboz is <attr> is false...
|
return this.makeDisplayItem(message, {
|
||||||
// Checkbox('!attr')
|
|
||||||
//
|
|
||||||
// XXX rename -- distinguish from actual button...
|
|
||||||
buttons.Checkbox = function(item, attr){
|
|
||||||
return (attr[0] == '!'
|
|
||||||
&& !item[attr.slice(1)])
|
|
||||||
|| item[attr] ?
|
|
||||||
'☐'
|
|
||||||
: '☑' }
|
|
||||||
|
|
||||||
|
|
||||||
// XXX can we make these not use the same icon...
|
|
||||||
buttons.ToggleDisabled = [
|
|
||||||
'Checkbox: "disabled"',
|
|
||||||
'toggleDisabled: item',
|
|
||||||
true,
|
|
||||||
{
|
|
||||||
alt: 'Disable/enable item',
|
|
||||||
cls: 'toggle-disabled',
|
|
||||||
}]
|
|
||||||
buttons.ToggleHidden = [
|
|
||||||
'Checkbox: "hidden"',
|
|
||||||
'toggleHidden: item',
|
|
||||||
{
|
|
||||||
alt: 'Show/hide item',
|
|
||||||
cls: 'toggle-hidden',
|
|
||||||
}]
|
|
||||||
buttons.ToggleSelected = [
|
|
||||||
'Checkbox: "selected"',
|
|
||||||
'toggleSelect: item',
|
|
||||||
{
|
|
||||||
alt: 'Select/deselect item',
|
|
||||||
cls: 'toggle-select',
|
|
||||||
}]
|
|
||||||
// NOTE: this button is disabled for all items but the ones with .children...
|
|
||||||
buttons.ToggleCollapse = [
|
|
||||||
function(item){
|
|
||||||
return !item.children ?
|
|
||||||
// placeholder...
|
|
||||||
' '
|
|
||||||
: item.collapsed ?
|
|
||||||
'+'
|
|
||||||
: '-' },
|
|
||||||
'toggleCollapse: item',
|
|
||||||
// disable button for all items that do not have children...
|
|
||||||
function(item){
|
|
||||||
return 'children' in item },
|
|
||||||
{
|
|
||||||
alt: 'Collapse/expand item',
|
|
||||||
cls: function(item){
|
|
||||||
return 'children' in item ?
|
|
||||||
'toggle-collapse'
|
|
||||||
: ['toggle-collapse', 'blank'] },
|
|
||||||
}]
|
|
||||||
|
|
||||||
// XXX delete button -- requires .markDelete(..) action...
|
|
||||||
buttons.Delete = [
|
|
||||||
'×',
|
|
||||||
'markDelete: item',
|
|
||||||
{
|
|
||||||
alt: 'Mark item for deletion',
|
|
||||||
cls: 'toggle-delete',
|
|
||||||
//keys: ['Delete', 'd'],
|
|
||||||
}]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
// Wrappers...
|
|
||||||
|
|
||||||
// this is here for uniformity...
|
|
||||||
Items.Item = function(value, options){ return this(...arguments) }
|
|
||||||
|
|
||||||
Items.Empty = function(value){}
|
|
||||||
|
|
||||||
Items.Separator = function(){ return this('---') }
|
|
||||||
Items.Spinner = function(){ return this('...') }
|
|
||||||
|
|
||||||
Items.Heading = function(value, options){
|
|
||||||
var cls = 'heading'
|
|
||||||
options = options || {}
|
|
||||||
options.cls = options.cls instanceof Array ?
|
|
||||||
options.cls.concat([cls])
|
|
||||||
: typeof(options.cls) == typeof('str') ?
|
|
||||||
options.cls +' '+ cls
|
|
||||||
: [cls]
|
|
||||||
options.buttons = options.buttons
|
|
||||||
|| this.dialog.options.headingButtons
|
|
||||||
return this(value, options) }
|
|
||||||
Items.Action = function(value, options){}
|
|
||||||
Items.ConfirmAction = function(value){}
|
|
||||||
Items.Editable = function(value){}
|
|
||||||
|
|
||||||
// lists...
|
|
||||||
Items.List = function(values){}
|
|
||||||
Items.EditableList = function(values){}
|
|
||||||
Items.EditablePinnedList = function(values){}
|
|
||||||
|
|
||||||
// Special list components...
|
|
||||||
//Items.ListPath = function(){}
|
|
||||||
//Items.ListTitle = function(){}
|
|
||||||
|
|
||||||
|
|
||||||
// XXX EXPERIMENTAL...
|
|
||||||
//
|
|
||||||
// options:
|
|
||||||
// {
|
|
||||||
// showOKButton: <bool>,
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
Items.Confirm = function(message, accept, reject, options){
|
|
||||||
return this(message,
|
|
||||||
Object.assign({
|
|
||||||
// XXX should the user be able to merge buttons from options???
|
|
||||||
buttons: [
|
buttons: [
|
||||||
...(reject instanceof Function ?
|
...[reject instanceof Function ?
|
||||||
[['$Cancel', reject]]
|
['Cancel', reject]
|
||||||
: []),
|
: []],
|
||||||
...(accept instanceof Function
|
...[accept instanceof Function ?
|
||||||
&& (options || {}).showOKButton ?
|
['OK', accept]
|
||||||
[['$OK', accept]]
|
: []], ], }) },
|
||||||
: []), ],
|
|
||||||
},
|
|
||||||
accept ?
|
|
||||||
{open: accept}
|
|
||||||
: {},
|
|
||||||
options || {})) }
|
|
||||||
|
|
||||||
|
// Focused item path...
|
||||||
|
//
|
||||||
|
// XXX add search/filter field...
|
||||||
|
// XXX add path navigation...
|
||||||
|
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',
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
|
id: tag,
|
||||||
|
cls: 'path',
|
||||||
|
},
|
||||||
|
options))
|
||||||
|
.last()
|
||||||
|
// event handlers...
|
||||||
|
dialog
|
||||||
|
.off('*', tag)
|
||||||
|
.on('focus',
|
||||||
|
function(){
|
||||||
|
e.value = this.pathArray
|
||||||
|
this.renderItem(e) },
|
||||||
|
tag)
|
||||||
|
return make },
|
||||||
|
|
||||||
|
// 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...
|
||||||
|
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...
|
||||||
// Generators...
|
var e = make('INFO',
|
||||||
//
|
Object.assign(
|
||||||
// A generator is a function that creates 1 or more elements and sets up
|
{
|
||||||
// the appropriate interactions...
|
id: tag,
|
||||||
//
|
cls: 'info',
|
||||||
// NOTE: these can work both as item generators called from inside
|
},
|
||||||
// .make(..), i.e. as methods of the make constructor, or as
|
options))
|
||||||
// generators assigned to .__header__ / .__items__ / .__footer__
|
.last()
|
||||||
// attributes...
|
// event handlers...
|
||||||
// NOTE: when re-using these options.id needs to be set so as not to
|
dialog
|
||||||
// overwrite existing instances data and handlers...
|
.off('*', tag)
|
||||||
|
.on('focus',
|
||||||
// Make item generator...
|
function(){
|
||||||
//
|
var focused = this.focused
|
||||||
Items.makeDisplayItem = function(text, options){
|
e.value = focused.doc
|
||||||
var args = [...arguments]
|
|| focused.alt
|
||||||
return function(make, options){
|
|| ' '
|
||||||
make(...args) } }
|
this.renderItem(e) },
|
||||||
|
|
||||||
// Make confirm item generator...
|
|
||||||
//
|
|
||||||
// XXX move this to Item.Confirm(..) and reuse that...
|
|
||||||
Items.makeDisplayConfirm = function(message, accept, reject){
|
|
||||||
return this.makeDisplayItem(message, {
|
|
||||||
buttons: [
|
|
||||||
...[reject instanceof Function ?
|
|
||||||
['Cancel', reject]
|
|
||||||
: []],
|
|
||||||
...[accept instanceof Function ?
|
|
||||||
['OK', accept]
|
|
||||||
: []], ], }) }
|
|
||||||
|
|
||||||
// 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',
|
|
||||||
Object.assign(
|
|
||||||
{
|
|
||||||
id: tag,
|
|
||||||
cls: 'path',
|
|
||||||
},
|
|
||||||
options))
|
|
||||||
.last()
|
|
||||||
// event handlers...
|
|
||||||
dialog
|
|
||||||
.off('*', tag)
|
|
||||||
.on('focus',
|
|
||||||
function(){
|
|
||||||
e.value = this.pathArray
|
|
||||||
this.renderItem(e) },
|
|
||||||
tag)
|
tag)
|
||||||
return make}
|
return make },
|
||||||
|
|
||||||
// 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...
|
// Constructors...
|
||||||
var e = make('INFO',
|
//
|
||||||
Object.assign(
|
__new__: function(_, dialog, constructor){
|
||||||
{
|
var that = function(){
|
||||||
id: tag,
|
that.called = true
|
||||||
cls: 'info',
|
constructor.call(that, ...arguments)
|
||||||
},
|
return that }
|
||||||
options))
|
return that },
|
||||||
.last()
|
__init__: function(dialog){
|
||||||
// event handlers...
|
this.items = []
|
||||||
dialog
|
this.dialog = dialog },
|
||||||
.off('*', tag)
|
})
|
||||||
.on('focus',
|
|
||||||
function(){
|
|
||||||
var focused = this.focused
|
var Make =
|
||||||
e.value = focused.doc
|
module.Make =
|
||||||
|| focused.alt
|
object.makeConstructor('Make', Items)
|
||||||
|| ' '
|
|
||||||
this.renderItem(e) },
|
|
||||||
tag)
|
|
||||||
return make }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1644,7 +1645,7 @@ var BaseBrowserPrototype = {
|
|||||||
// XXX revise options handling for .__items__(..)
|
// XXX revise options handling for .__items__(..)
|
||||||
// XXX might be a good idea to enable the user to merge the state
|
// XXX might be a good idea to enable the user to merge the state
|
||||||
// manually...
|
// manually...
|
||||||
// one way to do:
|
// one way to go:
|
||||||
// - get the previous item via an index,
|
// - get the previous item via an index,
|
||||||
// - update it
|
// - update it
|
||||||
// - pass it to make(..)
|
// - pass it to make(..)
|
||||||
@ -1703,106 +1704,100 @@ var BaseBrowserPrototype = {
|
|||||||
// ...would be more logical to store the object (i.e. browser/list)
|
// ...would be more logical to store the object (i.e. browser/list)
|
||||||
// directly as the element...
|
// directly as the element...
|
||||||
var section
|
var section
|
||||||
var make_called = false
|
|
||||||
var ids = new Set()
|
var ids = new Set()
|
||||||
var list = []
|
|
||||||
var keys = options.uniqueKeys ?
|
var keys = options.uniqueKeys ?
|
||||||
new Set()
|
new Set()
|
||||||
: null
|
: null
|
||||||
var make = function(value, opts){
|
var make = new Make(this,
|
||||||
make_called = true
|
function(value, opts){
|
||||||
|
var dialog = this.dialog
|
||||||
|
|
||||||
// special-case: inlined browser...
|
// special-case: inlined browser...
|
||||||
//
|
//
|
||||||
// NOTE: we ignore opts here...
|
// NOTE: we ignore opts here...
|
||||||
// XXX not sure if this is the right way to go...
|
// XXX not sure if this is the right way to go...
|
||||||
// ...for removal just remove the if statement and its
|
// ...for removal just remove the if statement and its
|
||||||
// first branch...
|
// first branch...
|
||||||
if(value instanceof BaseBrowser){
|
if(value instanceof BaseBrowser){
|
||||||
var item = value
|
var item = value
|
||||||
item.parent = this
|
item.parent = dialog
|
||||||
item.section = section
|
item.section = section
|
||||||
|
|
||||||
// normal item...
|
// normal item...
|
||||||
} else {
|
} else {
|
||||||
var args = [...arguments]
|
var args = [...arguments]
|
||||||
opts = opts || {}
|
opts = opts || {}
|
||||||
// handle: make(.., func, ..)
|
// handle: make(.., func, ..)
|
||||||
opts = opts instanceof Function ?
|
opts = opts instanceof Function ?
|
||||||
{open: opts}
|
{open: opts}
|
||||||
: opts
|
: opts
|
||||||
// handle trailing options...
|
// handle trailing options...
|
||||||
opts = args.length > 2 ?
|
opts = args.length > 2 ?
|
||||||
Object.assign({},
|
Object.assign({},
|
||||||
args.pop(),
|
args.pop(),
|
||||||
opts)
|
opts)
|
||||||
: opts
|
: opts
|
||||||
opts = Object.assign(
|
opts = Object.assign(
|
||||||
{},
|
{},
|
||||||
opts,
|
opts,
|
||||||
{value: value})
|
{value: value})
|
||||||
|
|
||||||
// item id...
|
// item id...
|
||||||
var key = this.__key__(opts)
|
var key = dialog.__key__(opts)
|
||||||
|
|
||||||
// duplicate keys (if .options.uniqueKeys is set)...
|
// duplicate keys (if .options.uniqueKeys is set)...
|
||||||
if(keys){
|
if(keys){
|
||||||
if(keys.has(key)){
|
if(keys.has(key)){
|
||||||
throw new Error(`make(..): duplicate key "${key}": `
|
throw new Error(`make(..): duplicate key "${key}": `
|
||||||
+`can't create multiple items with the same key `
|
+`can't create multiple items with the same key `
|
||||||
+`when .options.uniqueKeys is set.`)
|
+`when .options.uniqueKeys is set.`)
|
||||||
|
}
|
||||||
|
keys.add(key)
|
||||||
}
|
}
|
||||||
keys.add(key)
|
// duplicate ids...
|
||||||
|
if(opts.id && ids.has(opts.id)){
|
||||||
|
throw new Error(`make(..): duplicate id "${opts.id}": `
|
||||||
|
+`can't create multiple items with the same id.`) }
|
||||||
|
|
||||||
|
// build the item...
|
||||||
|
// NOTE: we intentionally isolate the item object from
|
||||||
|
// the input opts here, yes, having a ref to a mutable
|
||||||
|
// object may be convenient in some cases but in this
|
||||||
|
// case it would promote going around the main API...
|
||||||
|
var item = new dialog.__item__(
|
||||||
|
// default item template...
|
||||||
|
(options.itemTemplate || {})['*'] || {},
|
||||||
|
// item template...
|
||||||
|
(options.itemTemplate || {})[opts.value] || {},
|
||||||
|
opts,
|
||||||
|
{
|
||||||
|
parent: dialog,
|
||||||
|
section,
|
||||||
|
})
|
||||||
|
|
||||||
|
// XXX do we need both this and the above ref???
|
||||||
|
item.children instanceof BaseBrowser
|
||||||
|
&& (item.children.parent = dialog)
|
||||||
}
|
}
|
||||||
// duplicate ids...
|
|
||||||
if(opts.id && ids.has(opts.id)){
|
|
||||||
throw new Error(`make(..): duplicate id "${opts.id}": `
|
|
||||||
+`can't create multiple items with the same id.`) }
|
|
||||||
|
|
||||||
// build the item...
|
// user extended make...
|
||||||
// NOTE: we intentionally isolate the item object from
|
// XXX differentiate this for header and list...
|
||||||
// the input opts here, yes, having a ref to a mutable
|
dialog.__make__
|
||||||
// object may be convenient in some cases but in this
|
&& dialog.__make__(section, item)
|
||||||
// case it would promote going around the main API...
|
|
||||||
var item = new this.__item__(
|
|
||||||
// default item template...
|
|
||||||
(options.itemTemplate || {})['*'] || {},
|
|
||||||
// item template...
|
|
||||||
(options.itemTemplate || {})[opts.value] || {},
|
|
||||||
opts,
|
|
||||||
{
|
|
||||||
parent: this,
|
|
||||||
section,
|
|
||||||
})
|
|
||||||
|
|
||||||
// XXX do we need both this and the above ref???
|
// store the item...
|
||||||
item.children instanceof BaseBrowser
|
this.items.push(item)
|
||||||
&& (item.children.parent = this)
|
ids.add(key)
|
||||||
}
|
})
|
||||||
|
|
||||||
// user extended make...
|
|
||||||
// XXX differentiate this for header and list...
|
|
||||||
this.__make__
|
|
||||||
&& this.__make__(section, item)
|
|
||||||
|
|
||||||
// store the item...
|
|
||||||
list.push(item)
|
|
||||||
ids.add(key)
|
|
||||||
|
|
||||||
return make
|
|
||||||
}.bind(this)
|
|
||||||
make.__proto__ = Items
|
|
||||||
make.dialog = this
|
|
||||||
|
|
||||||
// build the sections...
|
// build the sections...
|
||||||
var reset_index = false
|
var reset_index = false
|
||||||
sections
|
sections
|
||||||
.forEach(function([name, handler]){
|
.forEach(function([name, handler]){
|
||||||
// setup closure for make(..)...
|
// setup state/closure for make(..)...
|
||||||
section = name
|
|
||||||
make_called = false
|
|
||||||
ids = new Set()
|
ids = new Set()
|
||||||
list = make.items = that[name] = []
|
section = name
|
||||||
|
make.items = that[name] = []
|
||||||
|
|
||||||
// prepare for index reset...
|
// prepare for index reset...
|
||||||
reset_index = reset_index || name == 'items'
|
reset_index = reset_index || name == 'items'
|
||||||
@ -1818,7 +1813,7 @@ var BaseBrowserPrototype = {
|
|||||||
: null)
|
: null)
|
||||||
|
|
||||||
// if make was not called use the .__items__(..) return value...
|
// if make was not called use the .__items__(..) return value...
|
||||||
that[name] = make_called ?
|
that[name] = make.called ?
|
||||||
that[name]
|
that[name]
|
||||||
: res })
|
: res })
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user