some basic theaming and some refactoring...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2015-06-20 20:51:43 +03:00
parent 235b51727e
commit 2b076e499c
3 changed files with 178 additions and 81 deletions

View File

@ -1,12 +1,15 @@
/********************************************************** Widget ***/
.browse { .browse {
display: inline-block; display: inline-block;
min-width: 300px; min-width: 300px;
width: initial; width: initial;
background: gray;
color: rgba(255,255,255,0.8);
padding: 5px; padding: 5px;
font-family: sans-serif; font-family: sans-serif;
background: gray;
/*color: rgba(255,255,255,0.8);*/
color: white;
} }
/* /*
.browse:not(:focus) { .browse:not(:focus) {
@ -18,11 +21,9 @@
height: auto; height: auto;
box-sizing: border-box; box-sizing: border-box;
border-top: 1px solid rgba(255,255,255, 0.3);
} }
.browse .v-block:first-of-type { .browse .v-block:not(:first-of-type) {
border-top: none; border-top: 1px solid rgba(255, 255, 255, 0.3);
} }
.browse .v-block:empty { .browse .v-block:empty {
display: none; display: none;
@ -30,21 +31,18 @@
.browse .title { /************************************************************ Path ***/
font-weight: bold;
color: rgba(255,255,255,0.9);
padding: 5px;
padding-left: 10px;
padding-right: 10px;
}
.browse .path { .browse .path {
padding: 5px; padding: 5px;
padding-left: 10px; padding-left: 10px;
padding-right: 10px; padding-right: 10px;
white-space: nowrap; white-space: nowrap;
opacity: 0.8;
}
.browse .path:hover {
opacity: 1;
} }
.browse .path:empty { .browse .path:empty {
display: block; display: block;
@ -90,6 +88,8 @@
/************************************************************ List ***/
/* XXX need to make this resizable up but only to a certain size (~80vh) */ /* XXX need to make this resizable up but only to a certain size (~80vh) */
.browse .list { .browse .list {
/* XXX need a way to make this automatic and depend on .browser /* XXX need a way to make this automatic and depend on .browser
@ -112,13 +112,25 @@
padding-left: 10px; padding-left: 10px;
padding-right: 10px; padding-right: 10px;
cursor: pointer; cursor: pointer;
opacity: 0.7;
} }
.browse:focus .list div.selected, .browse:focus .list div.selected,
.browse .path .dir:hover, .browse .path .dir:hover,
.browse .list div:hover { .browse .list div:hover {
color: white; background: rgba(0, 0, 0, 0.05);
background: rgba(0,0,0, 0.05);
opacity: 0.9;
}
.browse .list div.selected {
background: rgba(0, 0, 0, 0.08);
}
.browse:focus .list div.selected {
background: rgba(0, 0, 0, 0.08);
box-shadow: rgba(0, 0, 0, 0.2) 0.1em 0.1em 0.2em;
opacity: 1;
} }
/* XXX need to make the next two different... */ /* XXX need to make the next two different... */
@ -132,11 +144,39 @@
opacity: 0.3; opacity: 0.3;
} }
.browse:focus .list div.selected {
background: rgba(0,0,0, 0.1);
box-shadow: rgba(0,0,0,0.2) 0.1em 0.1em 0.2em; /******************************************************** Theaming ***/
/* Light */
.light .browse {
background: white;
color: rgba(0, 0, 0, 0.8);
}
.light .browse .v-block:not(:first-of-type) {
border-top: 1px solid rgba(0, 0, 0, 0.2);
} }
.browse .list div.selected {
background: rgba(0,0,0, 0.08);
/* Dark */
.dark .browse {
background: #0a0a0a;
color: rgba(255, 255, 255, 0.8);
} }
/* XXX can we make this simpler??? */
.dark .browse:focus .list div.selected,
.dark .browse .path .dir:hover,
.dark .browse .list div:hover {
background: rgba(255, 255, 255, 0.08);
}
.dark .browse .list div.selected {
background: rgba(255, 255, 255, 0.1);
}
.dark .browse:focus .list div.selected {
background: rgba(255, 255, 255, 0.1);
}
/*********************************************************************/

View File

@ -3,6 +3,56 @@
<link rel="stylesheet" href="browse-dialog.css"> <link rel="stylesheet" href="browse-dialog.css">
<style> <style>
/* scrollbar setup... */
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-button {
display: none;
}
::-webkit-scrollbar-track {
}
::-webkit-scrollbar-track-piece {
background: transparent;
}
::-webkit-scrollbar-track-piece {
background: rgba(0, 0, 0, 0.05);
}
::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0.15);
}
::-webkit-scrollbar-thumb:hover {
background: rgba(0, 0, 0, 0.3);
}
::-webkit-scrollbar-corner {
}
::-webkit-resizer {
}
/* theaming... */
body.dark {
background: black;
color: white;
}
.dark ::-webkit-scrollbar-track-piece {
background: rgba(255, 255, 255, 0.05);
}
.dark ::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.15);
}
.dark ::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.3);
}
/* testbed... */
.container { .container {
display: inline-block; display: inline-block;
position: absolute; position: absolute;
@ -30,39 +80,13 @@
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
::-webkit-scrollbar-button {
display: none;
}
::-webkit-scrollbar-track {
}
::-webkit-scrollbar-track-piece {
background: transparent;
}
::-webkit-scrollbar-track-piece {
background: rgba(0, 0, 0, 0.05);
}
::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0.15);
}
::-webkit-scrollbar-thumb:hover {
background: rgba(0, 0, 0, 0.3);
}
::-webkit-scrollbar-corner {
}
::-webkit-resizer {
}
</style> </style>
<script src="../ext-lib/jquery.js"></script> <script src="../ext-lib/jquery.js"></script>
<script src="../ext-lib/jquery-ui.js"></script> <script src="../ext-lib/jquery-ui.js"></script>
<script src="../lib/jli.js"></script> <script src="../lib/jli.js"></script>
<script src="../lib/toggler.js"></script>
<script src="../ext-lib/require.js"></script> <script src="../ext-lib/require.js"></script>
@ -135,6 +159,8 @@ requirejs(['../lib/keyboard', '../object', './browse-dialog'], function(k, o, br
}, },
}) })
.focus() .focus()
b.path = '/dir_a/tree/dir_c'
}) })
$(function(){ $(function(){
@ -148,6 +174,16 @@ $(function(){
//browser.focus() //browser.focus()
}) })
var themeToggler = CSSClassToggler('body',
[
'none',
'light',
'dark',
],
function(state){
$('#theme').text(state)
})
</script> </script>
<body> <body>
@ -157,6 +193,11 @@ $(function(){
<button onclick="b.prev()">^</button> <button onclick="b.prev()">^</button>
<button onclick="b.next()">v</button> <button onclick="b.next()">v</button>
<br>
<br>
Theme: <button id="theme" onclick="themeToggler()">none</button>
<div class="container"> <div class="container">
<div class="browse"> <div class="browse">

View File

@ -14,8 +14,7 @@ var object = require('../object')
/*********************************************************************/ /*********************************************************************/
// XXX add a hook to render the content of an element... // NOTE: the widget itself does not need a title, that's the job for
// XXX NOTE: the widget itself does not need a title, that's the job for
// a container widget (dialog, field, ...) // a container widget (dialog, field, ...)
// ...it can be implemented trivially via an attribute and a :before // ...it can be implemented trivially via an attribute and a :before
// CSS class... // CSS class...
@ -49,33 +48,32 @@ var BrowserClassPrototype = {
}, },
} }
// XXX need to scroll only the list, keeping the path always in view...
// XXX need to handle long paths -- smart shortening or auto scroll... // XXX need to handle long paths -- smart shortening or auto scroll...
// XXX Q: should we make a base list dialog and build this on that or // XXX Q: should we make a base list dialog and build this on that or
// simplify this to implement a list (removing the path and disbling // simplify this to implement a list (removing the path and disabling
// traversal)?? // traversal)??
// XXX need base events: // XXX need base events:
// - open // - open
// - update // - update
// - select (???) // - select (???)
// XXX add "current selection" to the path...
var BrowserPrototype = { var BrowserPrototype = {
dom: null, dom: null,
// option defaults and doc... // option defaults and doc...
//
// XXX add enable/disable filter option...
options: { options: {
//path: null, //path: null,
//show_path: null, //show_path: null,
// enable/disable user selection filtering...
// NOTE: this only affects .stopFilter(..)
filter: true,
// handle keys that are not bound... // handle keys that are not bound...
//
// NOTE: to disable, set ot undefined. // NOTE: to disable, set ot undefined.
logKeys: function(k){ window.DEBUG && console.log(k) }, logKeys: function(k){ window.DEBUG && console.log(k) },
}, },
// XXX this should prevent event handler deligation... // XXX this should prevent event handler delegation...
keyboard: { keyboard: {
// filter mappings... // filter mappings...
Filter: { Filter: {
@ -124,7 +122,8 @@ var BrowserPrototype = {
// base api... // base api...
// NOTE: to avoid duplicating and syncing data, the actual path is // NOTE: to avoid duplicating and syncing data, the actual path is
// stored in DOM... // stored in DOM...
// XXX does the path includes the currently selected element? // NOTE: path does not include the currently selected list element,
// just the path to the current list...
get path(){ get path(){
var skip = false var skip = false
return this.dom.find('.path .dir:not(.cur)') return this.dom.find('.path .dir:not(.cur)')
@ -132,7 +131,6 @@ var BrowserPrototype = {
.toArray() .toArray()
}, },
set path(value){ set path(value){
// XXX normalize path...
return this.update(value) return this.update(value)
}, },
@ -141,11 +139,26 @@ var BrowserPrototype = {
// - build the element list // - build the element list
// //
// XXX trigger an "update" event... // XXX trigger an "update" event...
// XXX do we normalize path here???
// XXX need a way to handle path errors in the extension API...
// ...for example, if .list(..) can't list or lists a different
// path due to an error, we need to be able to render the new
// path both in the path and list sections...
// NOTE: current behaviour is not wrong, it just not too flexible...
update: function(path){ update: function(path){
path = path || this.path path = path || this.path
var browser = this.dom var browser = this.dom
var that = this var that = this
// normalize path...
// XXX is it correct to ignore empty path elements, e.g. 'aa//cc'?
var splitter = /[\\\/]/
if(typeof(path) == typeof('str') && splitter.test(path)){
path = path
.split(splitter)
.filter(function(e){ return e != '' })
}
var p = browser.find('.path').empty() var p = browser.find('.path').empty()
var l = browser.find('.list').empty() var l = browser.find('.list').empty()
@ -164,14 +177,14 @@ var BrowserPrototype = {
.text(e)) .text(e))
}) })
// add current selction indicator... // add current selection indicator...
p.append($('<div>') p.append($('<div>')
.addClass('dir cur') .addClass('dir cur')
.click(function(){ .click(function(){
that.startFilter() that.startFilter()
//that.update(path.concat($(this).text())) //that.update(path.concat($(this).text()))
// XXX HACK: prevents the field from bluring when clicked... // XXX HACK: prevents the field from blurring when clicked...
// ...need to find a better way... // ...need to find a better way...
that._hold_blur = true that._hold_blur = true
setTimeout(function(){ delete that._hold_blur }, 20) setTimeout(function(){ delete that._hold_blur }, 20)
@ -240,15 +253,17 @@ var BrowserPrototype = {
// elements will be searched too. // elements will be searched too.
// //
// //
// XXX pattern modes: // TODO pattern modes:
// - lazy match // - lazy match
// abc -> *abc* -> ^.*abc.*$ // abc -> *abc* -> ^.*abc.*$
// ab cd -> *ab*cd* -> ^.*ab.*cd.*$ // ab cd -> *ab*cd* -> ^.*ab.*cd.*$
// - glob // - glob
// XXX need to support glob / nested patterns... // TODO need to support glob / nested patterns...
// ..things like /**/a*/*moo/ // ..things like /**/a*/*moo/
// XXX should we unwrap the elements to be more compatible with //
// XXX Q: should we unwrap the elements to be more compatible with
// jQuery .filter(..)? // jQuery .filter(..)?
// ...currently I don't think so...
filter: function(pattern, a, b){ filter: function(pattern, a, b){
pattern = pattern || '*' pattern = pattern || '*'
var ignore_disabled = typeof(a) == typeof(true) ? a : b var ignore_disabled = typeof(a) == typeof(true) ? a : b
@ -347,21 +362,22 @@ var BrowserPrototype = {
}, },
// XXX make this a toggler... (???) // XXX make this a toggler... (???)
startFilter: function(){ startFilter: function(){
var range = document.createRange() if(this.options.filter){
var selection = window.getSelection() var range = document.createRange()
var selection = window.getSelection()
var that = this var that = this
var e = this.dom.find('.path .dir.cur') var e = this.dom.find('.path .dir.cur')
.text('') .text('')
.attr('contenteditable', true) .attr('contenteditable', true)
.focus() .focus()
// place the cursor...
range.setStart(e[0], 0)
range.collapse(true)
selection.removeAllRanges()
selection.addRange(range)
// place the cursor...
range.setStart(e[0], 0)
range.collapse(true)
selection.removeAllRanges()
selection.addRange(range)
}
return this return this
}, },
stopFilter: function(){ stopFilter: function(){
@ -442,6 +458,9 @@ var BrowserPrototype = {
// //
// XXX Q: should this trigger a "select" event??? // XXX Q: should this trigger a "select" event???
// XXX the scroll handling might be a bit inaccurate... // XXX the scroll handling might be a bit inaccurate...
// XXX Q: should this have a version that will just return the
// selected element without affecting the ui?
// ...something like .filter(..) vs. .showFiltered(..)
select: function(elem, filtering){ select: function(elem, filtering){
var pattern = '.list div:not(.disabled):not(.filtered-out)' var pattern = '.list div:not(.disabled):not(.filtered-out)'
var browser = this.dom var browser = this.dom
@ -680,9 +699,6 @@ object.makeConstructor('Browser',
/********************************************************************** /**********************************************************************
* vim:set ts=4 sw=4 : */ * vim:set ts=4 sw=4 : */
return module }) return module })