started refactoring the browser widget...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2015-03-16 20:40:08 +03:00
parent 6779afeaa1
commit 9ff081da7f

View File

@ -399,9 +399,289 @@ var KB = {
}
//---
requirejs(['../lib/keyboard'], function(m){
keyboard = m
var BrowserClassPrototype = {
// construct the dom...
make: function(){
var browser = $('<div>')
.addClass('browse')
// make thie widget focusable...
// NOTE: tabindex 0 means automatic tab indexing and -1 means
// focusable bot not tabable...
//.attr('tabindex', -1)
.attr('tabindex', 0)
// focus the widget if something inside is clicked...
.click(function(){
$(this).focus()
})
.append($('<div>')
.addClass('v-block title')
.text(title))
.append($('<div>')
.addClass('v-block path'))
.append($('<div>')
.addClass('v-block list'))
.append($('<div>')
.addClass('v-block info'))
.append($('<div>')
.addClass('v-block actions'))
return browser
},
}
var BrowserPrototype = {
dom: null,
keyboard: {
'.browse':{
Up: 'prev',
Backspace: 'Up',
Down: 'next',
Left: 'pop',
Right: 'push',
Enter: 'action',
Esc: 'close',
},
},
// base api...
// NOTE: to avoid duplicating and syncing data, the actual path is
// stored in DOM...
get path(){
var skip = false
return this.dom.find('.path .dir')
.map(function(i, e){ return $(e).text() })
.toArray()
},
set path(value){
// XXX normalize path...
return this.update(path)
},
// update path...
update: function(path){
var browser = this.dom
var p = browser.find('.path').empty()
var l = browser.find('.list').empty()
// fill the path field...
path.forEach(function(e){
p.append($('<div>')
.addClass('dir')
.click(popDir)
.text(e))
})
// fill the children list...
this.list(path)
.forEach(function(e){
l.append($('<div>')
.click(pushDir)
.text(e))
})
return this
},
// internal actions...
//
// Select first/last child
// .select('first')
// .select('last')
// -> elem
//
// Select previous/lext child
// .select('prev')
// .select('next')
// -> elem
//
// Deselect
// .select('none')
// -> elem
//
// Get selected element if it exists, null otherwise...
// .select('!')
// -> elem
// -> $()
//
// Select element by sequence number
// .select(<number>)
// -> elem
//
// Select element by its text...
// .select('"<text>"')
// -> elem
//
// .select(<elem>)
// -> elem
//
// This will return a jQuery object.
//
//
// XXX revise return values...
select: function(elem){
var browser = this.dom
var elems = browser.find('.list div')
if(elems.length == 0){
return $()
}
elem = elem || this.select('!')
// if none selected get the first...
elem = elem.length == 0 ? 'first' : elem
// first/last...
if(elem == 'first' || elem == 'last'){
return this.select(elems[elem]())
// prev/next...
} else if(elem == 'prev' || elem == 'next'){
var to = this.select('!', browser)[elem]('.list div')
if(to.length == 0){
return this.select(elem == 'prev' ? 'last' : 'first', browser)
}
this.select('none')
return this.select(to)
// deselect...
} else if(elem == 'none'){
return elems
.filter('.selected')
.removeClass('selected')
// strict...
} else if(elem == '!'){
return elems.filter('.selected')
// number...
} else if(typeof(elem) == typeof(123)){
return this.select($(elems[elem]))
// string...
} else if(typeof(elem) == typeof('str')
&& /^'.*'$|^".*"$/.test(elem.trim())){
elem = elem.trim().slice(1, -1)
return this.select(browser.find('.list div')
.filter(function(i, e){
return $(e).text() == elem
}))
// element...
} else {
this.select('none')
return elem.addClass('selected')
}
},
// XXX check if we need to do the ,action when the element id not traversable...
push: function(elem){
var browser = this.dom
var elem = this.select(elem || '!')
// nothing selected, select first and exit...
if(elem.length == 0){
this.select()
return this
}
this
.update(this.path.push(elem.text()))
.select()
return this
},
// pop an element off the path / go up one level...
pop: function(){
var browser = this.dom
var path = this.path
var dir = path.pop()
this.update(path)
this.select('"'+dir+'"')
return this
},
next: function(elem){
if(elem != null){
this.select(elem)
}
this.select('next')
return this
},
prev: function(elem){
if(elem != null){
this.select(elem)
}
this.select('prev')
return this
},
// XXX think about the API...
action: function(){
var res = this.open(this.path)
// XXX close the dialog if everything is OK...
// XXX
return res
},
// close the dialog...
// XXX
close: function(){
},
// extension methods...
// XXX think about the API...
// needs to control closing of the dialog
open: function(){
},
list: function(){
},
isTraversable: null,
// XXX
__init__: function(parent){
// build the dom...
var dom = this.dom = this.constructor.make()
// add keyboard handler...
dom.keydown(
keyboard.makeKeyboardHandler(
this.keyboard,
function(k){ window.DEBUG && console.log(k) },
this))
// attach to parent...
if(parent != null){
parent.append(dom)
}
},
}
/*
var Browser =
//module.Browser =
object.makeConstructor('Browser',
BrowserClassPrototype,
BrowserPrototype)
*/
//---
requirejs(['../lib/keyboard', '../object'], function(k, o){
keyboard = k
object = o
// setup base keyboard for devel, in case something breaks...
//$(document)