mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 10:20:08 +00:00
started work on the DOM render...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
0d997f451c
commit
50f7c6f6e8
@ -17,16 +17,48 @@ var widget = require('./widget')
|
|||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
// Helpers...
|
// Helpers...
|
||||||
|
|
||||||
//
|
// Collect a list of literal values and "make(..) calls" into an array...
|
||||||
|
//
|
||||||
|
// collectItems(context, items)
|
||||||
|
// -> values
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// items format:
|
||||||
|
// [
|
||||||
|
// // explicit value...
|
||||||
|
// value,
|
||||||
|
//
|
||||||
|
// // literal make call...
|
||||||
|
// make(..),
|
||||||
|
//
|
||||||
|
// ...
|
||||||
|
// ]
|
||||||
|
//
|
||||||
// NOTE: this will remove the made via make(..) items from .items thus the
|
// NOTE: this will remove the made via make(..) items from .items thus the
|
||||||
// caller is responsible for adding them back...
|
// caller is responsible for adding them back...
|
||||||
var normalizeItems = function(context, items){
|
// NOTE: this uses the make(..) return value to implicitly infer the items
|
||||||
|
// to collect, thus the items must already be constructed and in
|
||||||
|
// the same order as they are present in .items
|
||||||
|
// ...also, considering that this implicitly identifies the items
|
||||||
|
// passing the make function without calling it can trick the system
|
||||||
|
// and lead to unexpected results.
|
||||||
|
//
|
||||||
|
// XXX would be nice to have a better check/test...
|
||||||
|
// ...this could be done by chaining instances of make instead of
|
||||||
|
// returning an actual function, i.e. each make call would return
|
||||||
|
// a "new" function that would reference the actual item (.item())
|
||||||
|
// and the previous item created (.prevItem()), ... etc.
|
||||||
|
// ...this would enable us to uniquely identify the actual items
|
||||||
|
// and prevent allot of specific errors...
|
||||||
|
var collectItems = function(context, items){
|
||||||
var made = items
|
var made = items
|
||||||
.filter(function(e){
|
.filter(function(e){
|
||||||
return e === context })
|
return e === context })
|
||||||
var l = context.items.length - made.length
|
|
||||||
// constructed item list...
|
// constructed item list...
|
||||||
made = context.items.splice(l, made.length)
|
// ...remove each instance from .items
|
||||||
|
made = context.items.splice(
|
||||||
|
context.items.length - made.length,
|
||||||
|
made.length)
|
||||||
// get the actual item values...
|
// get the actual item values...
|
||||||
return items
|
return items
|
||||||
.map(function(e){
|
.map(function(e){
|
||||||
@ -59,6 +91,7 @@ var normalizeItems = function(context, items){
|
|||||||
var Items = module.items = function(){}
|
var Items = module.items = function(){}
|
||||||
|
|
||||||
|
|
||||||
|
// placeholders...
|
||||||
Items.dialog = null
|
Items.dialog = null
|
||||||
Items.items = null
|
Items.items = null
|
||||||
|
|
||||||
@ -71,54 +104,55 @@ Items.last = function(){
|
|||||||
|
|
||||||
|
|
||||||
// Focus last created item...
|
// Focus last created item...
|
||||||
// XXX also would be nice to set the last created items to .last or
|
|
||||||
// similar in the context...
|
|
||||||
Items.focus = function(){
|
Items.focus = function(){
|
||||||
this.last.current = true
|
this.last.current = true }
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Group a set of items...
|
||||||
//
|
//
|
||||||
// .group(make(..), ..)
|
// .group(make(..), ..)
|
||||||
|
// .group([make(..), ..])
|
||||||
// -> make
|
// -> make
|
||||||
//
|
//
|
||||||
|
//
|
||||||
// Example:
|
// Example:
|
||||||
// make.group(
|
// make.group(
|
||||||
// make('made item'),
|
// make('made item'),
|
||||||
// 'literal item',
|
// 'literal item',
|
||||||
// ...)
|
// ...)
|
||||||
//
|
//
|
||||||
|
//
|
||||||
|
// NOTE: see notes to collectItems(..) for more info...
|
||||||
|
//
|
||||||
// XXX do we need to pass options to groups???
|
// XXX do we need to pass options to groups???
|
||||||
// XXX would be nice to have a better check/test...
|
|
||||||
// ...this could be done by chaining instances of make instead of
|
|
||||||
// returning an actual function, i.e. each make call would return
|
|
||||||
// a "new" function that would reference the actual item (.item())
|
|
||||||
// and the previous item created (.prevItem()), ... etc.
|
|
||||||
// ...this would enable us to uniquely identify the actual items
|
|
||||||
// and prevent allot of specific errors...
|
|
||||||
Items.group = function(...items){
|
Items.group = function(...items){
|
||||||
var that = this
|
var that = this
|
||||||
items = items.length == 1 && items[0] instanceof Array ?
|
items = items.length == 1 && items[0] instanceof Array ?
|
||||||
items[0]
|
items[0]
|
||||||
: items
|
: items
|
||||||
|
|
||||||
// replace the items with the group...
|
// replace the items with the group...
|
||||||
this.items.splice(this.items.length, 0, ...normalizeItems(this, items))
|
this.items.splice(this.items.length, 0, ...collectItems(this, items))
|
||||||
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Place list in a sub-list of item...
|
||||||
|
//
|
||||||
Items.nest = function(item, list, options){
|
Items.nest = function(item, list, options){
|
||||||
options = options || {}
|
options = options || {}
|
||||||
options.sublist = list instanceof Array ?
|
options.sublist = list instanceof Array ?
|
||||||
normalizeItems(this, list)
|
collectItems(this, list)
|
||||||
: list
|
: list
|
||||||
return this(item, options)
|
return this(item, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// wrappers...
|
||||||
|
|
||||||
Items.Item = function(value, options){}
|
Items.Item = function(value, options){}
|
||||||
Items.Action = function(value, options){}
|
Items.Action = function(value, options){}
|
||||||
Items.Heading = function(value, options){}
|
Items.Heading = function(value, options){}
|
||||||
@ -165,23 +199,14 @@ var BaseBrowserPrototype = {
|
|||||||
// ...
|
// ...
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// XXX format doc...
|
|
||||||
// XXX should this be a list or a Map/Object????
|
// XXX should this be a list or a Map/Object????
|
||||||
// ...we do not need ultra fast traversal but we do need a way
|
// ...we do not need ultra fast traversal but we do need a way
|
||||||
// to identify and select items in a unique way...
|
// to identify and select items in a unique way...
|
||||||
// XXX how do we handler nested lists???
|
|
||||||
// ...feels like a sub-list should be part of an item, i.e.
|
|
||||||
// create an item and place a list "into" it...
|
|
||||||
// the question is whether this item should be:
|
|
||||||
// - first item of sub-list
|
|
||||||
// - connected to the sub-list but part of the parent list
|
|
||||||
// ...I'm leaning to the later...
|
|
||||||
__items: null,
|
__items: null,
|
||||||
get items(){
|
get items(){
|
||||||
this.__items
|
this.__items
|
||||||
|| this.make()
|
|| this.make()
|
||||||
return this.__items
|
return this.__items },
|
||||||
},
|
|
||||||
set items(value){
|
set items(value){
|
||||||
this.__items = value },
|
this.__items = value },
|
||||||
|
|
||||||
@ -223,13 +248,11 @@ var BaseBrowserPrototype = {
|
|||||||
make: function(options){
|
make: function(options){
|
||||||
var items = this.items = []
|
var items = this.items = []
|
||||||
|
|
||||||
// XXX change this to:
|
// item constructor...
|
||||||
// - return a new instance/function for each call
|
//
|
||||||
// - each new instance/function references:
|
// make(..)
|
||||||
// - the item created
|
// -> make
|
||||||
// - next instance/function
|
//
|
||||||
// XXX might also be a good idea to move this out of the method
|
|
||||||
// and into the module scope for clarity...
|
|
||||||
var make_called = false
|
var make_called = false
|
||||||
var make = function(value, opts){
|
var make = function(value, opts){
|
||||||
make_called = true
|
make_called = true
|
||||||
@ -264,10 +287,14 @@ var BaseBrowserPrototype = {
|
|||||||
|
|
||||||
// Renderers...
|
// Renderers...
|
||||||
//
|
//
|
||||||
// Render main list...
|
// .renderList(items, options)
|
||||||
|
// .renderNested(header, sublist, item, options)
|
||||||
|
// .renderItem(item, i, options)
|
||||||
|
// .renderGroup(items, options)
|
||||||
|
//
|
||||||
|
//
|
||||||
renderList: function(items, options){
|
renderList: function(items, options){
|
||||||
return items },
|
return items },
|
||||||
// Render nested list...
|
|
||||||
// NOTE: to skip rendering an item/list return null...
|
// NOTE: to skip rendering an item/list return null...
|
||||||
// XXX should this take an empty sublist???
|
// XXX should this take an empty sublist???
|
||||||
// ...this would make it simpler to expand/collapse without
|
// ...this would make it simpler to expand/collapse without
|
||||||
@ -279,11 +306,9 @@ var BaseBrowserPrototype = {
|
|||||||
sublist,
|
sublist,
|
||||||
])
|
])
|
||||||
: sublist },
|
: sublist },
|
||||||
// Render list item...
|
|
||||||
// NOTE: to skip rendering an item/list return null...
|
// NOTE: to skip rendering an item/list return null...
|
||||||
renderItem: function(item, i, options){
|
renderItem: function(item, i, options){
|
||||||
return item },
|
return item },
|
||||||
// Render group...
|
|
||||||
renderGroup: function(items, options){
|
renderGroup: function(items, options){
|
||||||
return items },
|
return items },
|
||||||
|
|
||||||
@ -295,9 +320,15 @@ var BaseBrowserPrototype = {
|
|||||||
// -> state
|
// -> state
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
// context format:
|
||||||
|
// {
|
||||||
|
// root: <root-browser>,
|
||||||
|
// options: <options>,
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
// NOTE: currently options and context are distinguished only via
|
// NOTE: currently options and context are distinguished only via
|
||||||
// the .options attribute... (XXX)
|
// the .options attribute... (XXX)
|
||||||
//
|
|
||||||
render: function(options){
|
render: function(options){
|
||||||
var that = this
|
var that = this
|
||||||
// XXX revise -- should options and context be distinguished only
|
// XXX revise -- should options and context be distinguished only
|
||||||
@ -329,24 +360,12 @@ var BaseBrowserPrototype = {
|
|||||||
that.renderGroup(
|
that.renderGroup(
|
||||||
item.map(_render), options)
|
item.map(_render), options)
|
||||||
// renderable item...
|
// renderable item...
|
||||||
// XXX should this be nested???
|
|
||||||
: item.render instanceof Function ?
|
: item.render instanceof Function ?
|
||||||
that.renderNested(
|
item.render(context)
|
||||||
null,
|
|
||||||
item.render(context),
|
|
||||||
item,
|
|
||||||
options)
|
|
||||||
// renderable value -- embedded list...
|
// renderable value -- embedded list...
|
||||||
// XXX should this be nested???
|
|
||||||
: (item.value || {}).render instanceof Function ?
|
: (item.value || {}).render instanceof Function ?
|
||||||
that.renderNested(
|
item.value.render(context)
|
||||||
null,
|
|
||||||
item.value.render(context),
|
|
||||||
item,
|
|
||||||
options)
|
|
||||||
// .sublist -- nested list...
|
// .sublist -- nested list...
|
||||||
// XXX should we always render the nested list here,
|
|
||||||
// only rendering it empty if collapsed???
|
|
||||||
: item.sublist ?
|
: item.sublist ?
|
||||||
that.renderNested(
|
that.renderNested(
|
||||||
that.renderItem(item, i, options),
|
that.renderItem(item, i, options),
|
||||||
@ -434,32 +453,96 @@ var BrowserPrototype = {
|
|||||||
__proto__: BaseBrowser.prototype,
|
__proto__: BaseBrowser.prototype,
|
||||||
|
|
||||||
options: {
|
options: {
|
||||||
|
renderHidden: false,
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
dom: null,
|
dom: null,
|
||||||
|
|
||||||
// Render main list...
|
|
||||||
// XXX update dom...
|
|
||||||
renderList: function(items, options){
|
renderList: function(items, options){
|
||||||
// XXX maintain header...
|
var that = this
|
||||||
return items },
|
var e = document.createElement('div')
|
||||||
// Render nested list...
|
|
||||||
// XXX list header
|
e.classList.add('list')
|
||||||
// ...is it the responsibility of sub-list or the parent list???
|
|
||||||
// XXX save link to dom (???)
|
items
|
||||||
|
.forEach(function(item){
|
||||||
|
e.appendChild(item instanceof Array ?
|
||||||
|
that.renderGroup(item)
|
||||||
|
: item) })
|
||||||
|
|
||||||
|
return e },
|
||||||
renderNested: function(header, sublist, item, options){
|
renderNested: function(header, sublist, item, options){
|
||||||
// XXX expand/collapse state???
|
var e = document.createElement('div')
|
||||||
return header ?
|
e.classList.add('list')
|
||||||
[header, sublist]
|
|
||||||
: sublist },
|
// header...
|
||||||
// Render group...
|
if(header){
|
||||||
|
header.classList.add('sub-list-header')
|
||||||
|
item.collapsed
|
||||||
|
&& header.classList.add('collapsed')
|
||||||
|
e.appendChild(header)
|
||||||
|
}
|
||||||
|
|
||||||
|
// items...
|
||||||
|
sublist
|
||||||
|
&& sublist
|
||||||
|
.forEach(function(item){
|
||||||
|
e.appendChild(item) })
|
||||||
|
|
||||||
|
item.dom = e
|
||||||
|
|
||||||
|
return e
|
||||||
|
},
|
||||||
|
// XXX this does not seem to get called by .render(..)...
|
||||||
renderGroup: function(items, options){
|
renderGroup: function(items, options){
|
||||||
return items },
|
var e = document.createElement('div')
|
||||||
// Render list item...
|
e.classList.add('group')
|
||||||
// XXX save link to dom in item.dom (???)
|
items
|
||||||
|
// XXX is this wrong???
|
||||||
|
.flat(Infinity)
|
||||||
|
.forEach(function(item){
|
||||||
|
e.appendChild(item) })
|
||||||
|
return e },
|
||||||
renderItem: function(item, i, options){
|
renderItem: function(item, i, options){
|
||||||
return item },
|
if(options.hidden && !options.renderHidden){
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
var e = document.createElement('div')
|
||||||
|
|
||||||
|
// classes...
|
||||||
|
e.classList.add('item')
|
||||||
|
;(options.cls || [])
|
||||||
|
.forEach(function(cls){
|
||||||
|
e.classList.add(cls) })
|
||||||
|
|
||||||
|
// attrs...
|
||||||
|
Object.entries(options.attrs || {})
|
||||||
|
.forEach(function({key, value}){
|
||||||
|
e.setAttribute(key, value) })
|
||||||
|
|
||||||
|
// values...
|
||||||
|
;(item.value instanceof Array ? item.value : [item.value])
|
||||||
|
.map(function(v){
|
||||||
|
var value = document.createElement('span')
|
||||||
|
value.classList.add('text')
|
||||||
|
value.innerHTML = v || item || ''
|
||||||
|
e.appendChild(value)
|
||||||
|
})
|
||||||
|
|
||||||
|
// XXX buttons...
|
||||||
|
// XXX
|
||||||
|
|
||||||
|
// special stuff...
|
||||||
|
options.focused && e.classList.add('focused')
|
||||||
|
options.selected && e.classList.add('selected')
|
||||||
|
options.disabled && e.classList.add('disabled')
|
||||||
|
options.hidden && e.classList.add('hidden')
|
||||||
|
|
||||||
|
item.dom = e
|
||||||
|
|
||||||
|
return e },
|
||||||
|
|
||||||
// save the rendered state to .dom
|
// save the rendered state to .dom
|
||||||
render: function(context, options){
|
render: function(context, options){
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user