some minor refactoring + added path disabling syntax to browse.List and browse.PathList...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2015-12-11 07:32:46 +03:00
parent 384450d75f
commit cb27807a99
5 changed files with 159 additions and 78 deletions

View File

@ -187,10 +187,10 @@
overflow: hidden; overflow: hidden;
} }
.browse-widget .list>div:after { .browse-widget .list>div[count]:after {
display: inline-block; display: inline-block;
content: attr(count); content: "(" attr(count) ")";
float: right; float: right;
margin-right: 10px; margin-right: 10px;

View File

@ -126,7 +126,7 @@ function(path, make){
// count the number of files... // count the number of files...
// NOTE: we do not care how long it will take // NOTE: we do not care how long it will take
// so we'll not wait... // so we'll not wait...
if(res && dir){ if(res && dir && that.options.fileCountPattern){
var i = 0 var i = 0
glob(path +'/'+ file +'/'+ that.options.fileCountPattern) glob(path +'/'+ file +'/'+ that.options.fileCountPattern)
/* /*
@ -137,7 +137,7 @@ function(path, make){
*/ */
.on('end', function(lst){ .on('end', function(lst){
i += 1 i += 1
elem.attr('count', '('+ lst.length +')') elem.attr('count', lst.length)
}) })
} }
}) })
@ -233,7 +233,8 @@ WalkPrototype.options = {
list: listDir, list: listDir,
fileCountPattern: '*+(jpg|jpeg|png|JPG|JPEG|PNG)', //disableItemPattern: false,
fileCountPattern: '*',
} }
WalkPrototype.options.__proto__ = browse.Browser.prototype.options WalkPrototype.options.__proto__ = browse.Browser.prototype.options

View File

@ -272,7 +272,7 @@ requirejs(['../keyboard', '../object', './browse'], function(k, o, br){
f2 = browser.makeList($('.container.flat2'), { f2 = browser.makeList($('.container.flat2'), {
'option 1': function(_, p){ console.log('option:', p) }, 'option 1': function(_, p){ console.log('option:', p) },
'option 2': function(_, p){ console.log('option:', p) }, 'option 2': function(_, p){ console.log('option:', p) },
'option 3': function(_, p){ console.log('option:', p) }, '- option 3': function(_, p){ console.log('option:', p) },
'option 4': function(_, p){ console.log('option:', p) }, 'option 4': function(_, p){ console.log('option:', p) },
}) })
// another way to handle the opening of items... // another way to handle the opening of items...
@ -284,11 +284,12 @@ requirejs(['../keyboard', '../object', './browse'], function(k, o, br){
f3 = browser.makePathList($('.container.pathlist'), { f3 = browser.makePathList($('.container.pathlist'), {
// build a basic tree... // build a basic tree...
// XXX need a way to trigger open events with touch/mouse... // XXX need a way to trigger open events with touch/mouse...
'- /dir 3': function(_, p){ console.log('dir:', p) },
'/dir 1': function(_, p){ console.log('dir:', p) }, '/dir 1': function(_, p){ console.log('dir:', p) },
'dir 1/option 1': function(_, p){ console.log('option:', p) }, 'dir 1/option 1': function(_, p){ console.log('option:', p) },
// add an element to two paths... // add an element to two paths...
'dir 1|dir 2|dir 3/option 2/': function(_, p){ console.log('option:', p) }, 'dir 1|dir 2|dir 3/option 2/': function(_, p){ console.log('option:', p) },
'dir 2/option 3': function(_, p){ console.log('option:', p) }, '- dir 2/option 3': function(_, p){ console.log('option:', p) },
'option 4': function(_, p){ console.log('option:', p) }, 'option 4': function(_, p){ console.log('option:', p) },
// XXX this is the wrong way to do this, but it shows a bug... // XXX this is the wrong way to do this, but it shows a bug...

View File

@ -35,6 +35,15 @@ var quoteWS = function(str){
} }
// Quote a string and convert to RegExp to match self literally.
function toRegExp(str){
return RegExp('^'
// quote regular expression chars...
+str.replace(/([\.\\\/\(\)\[\]\$\*\+\-\{\}\@\^\&\?\<\>])/g, '\\$1')
+'$')
}
function makeBrowserMaker(constructor){ function makeBrowserMaker(constructor){
return function(elem, list, rest){ return function(elem, list, rest){
if(typeof(rest) == typeof('str')){ if(typeof(rest) == typeof('str')){
@ -527,11 +536,13 @@ var BrowserPrototype = {
// ...will need to account for 1-9 shortcut keys and hints to // ...will need to account for 1-9 shortcut keys and hints to
// still work... // still work...
toggleNonTraversableDrawing: function(){ toggleNonTraversableDrawing: function(){
var cur = this.selected
if(this.options.traversable == false){ if(this.options.traversable == false){
return this return this
} }
this.options.showNonTraversable = !this.options.showNonTraversable this.options.showNonTraversable = !this.options.showNonTraversable
this.update() this.update()
cur && this.select(cur)
return this return this
}, },
// XXX this will not affect elements that were disabled via setting // XXX this will not affect elements that were disabled via setting
@ -542,11 +553,13 @@ var BrowserPrototype = {
// ...will need to account for 1-9 shortcut keys and hints to // ...will need to account for 1-9 shortcut keys and hints to
// still work... // still work...
toggleDisabledDrawing: function(){ toggleDisabledDrawing: function(){
var cur = this.selected
if(this.options.toggleDisabledDrawing == false){ if(this.options.toggleDisabledDrawing == false){
return this return this
} }
this.options.showDisabled = !this.options.showDisabled this.options.showDisabled = !this.options.showDisabled
this.update() this.update()
cur && this.select(cur)
return this return this
}, },
@ -882,6 +895,15 @@ var BrowserPrototype = {
// 'a b c' - three sub patterns: 'a', 'b' and 'c' // 'a b c' - three sub patterns: 'a', 'b' and 'c'
// 'a\ b\ c' - single pattern // 'a\ b\ c' - single pattern
// //
// Get element exactly matching a string...
// .filter(<quoted-string>)
// -> elements
// NOTE: this supports bot single and double quotes, e.g.
// '"abc"' and "'abc'" are equivalent...
// NOTE: only outer quotes are considered, so if there is a
// need to exactly match '"X"', just add a set of quotes
// around it, e.g. '""X""' or '\'"X"\''...
//
// Get all elements matching a regexp... // Get all elements matching a regexp...
// .filter(<regexp>) // .filter(<regexp>)
// -> elements // -> elements
@ -965,7 +987,12 @@ var BrowserPrototype = {
} }
// regexp... // regexp...
} else if(pattern.constructor == RegExp){ } else if(pattern.constructor == RegExp
|| (typeof(pattern) == typeof('str')
&& /^'.*'$|^".*"$/.test(pattern.trim()))){
if(typeof(pattern) == typeof('str')){
pattern = toRegExp(pattern.trim().slice(1, -1))
}
var filter = function(i, e){ var filter = function(i, e){
if(!pattern.test($(e).find('.text').text())){ if(!pattern.test($(e).find('.text').text())){
if(rejected){ if(rejected){
@ -1270,6 +1297,9 @@ var BrowserPrototype = {
// NOTE: if text matches one of the reserved commands above use // NOTE: if text matches one of the reserved commands above use
// quotes to escape it... // quotes to escape it...
// .select('<text>') // .select('<text>')
// -> elem
//
// Select element by its literal full test...
// .select("'<text>'") // .select("'<text>'")
// .select('"<text>"') // .select('"<text>"')
// -> elem // -> elem
@ -1369,11 +1399,6 @@ var BrowserPrototype = {
// string... // string...
} else if(typeof(elem) == typeof('str')){ } else if(typeof(elem) == typeof('str')){
// clear quotes...
// XXX can an item contain '"' or "'"???
if(/^'.*'$|^".*"$/.test(elem.trim())){
elem = elem.trim().slice(1, -1)
}
return this.select(this.filter(elem).first(), filtering) return this.select(this.filter(elem).first(), filtering)
// regexp... // regexp...
@ -1991,6 +2016,10 @@ Browser.prototype.__proto__ = widget.Widget.prototype
// <option-text>, // <option-text>,
// ... // ...
// ] // ]
//
// If <option-test> starts with a '- ' then it will be added disabled,
// to control the pattern use the .disableItemPattern option, and to
// disable this feature set it to false|null.
// //
// NOTE: this essentially a different default configuration of Browser... // NOTE: this essentially a different default configuration of Browser...
var ListPrototype = Object.create(BrowserPrototype) var ListPrototype = Object.create(BrowserPrototype)
@ -2001,13 +2030,34 @@ ListPrototype.options = {
traversable: false, traversable: false,
flat: true, flat: true,
// XXX not sure if we need these...
skipDisabledItems: false,
// NOTE: to disable this set it to false or null
disableItemPattern: '^- ',
list: function(path, make){ list: function(path, make){
var that = this var that = this
var data = this.options.data var data = this.options.data
var keys = data.constructor == Array ? data : Object.keys(data) var keys = data.constructor == Array ? data : Object.keys(data)
var pattern = this.options.disableItemPattern
&& RegExp(this.options.disableItemPattern)
return keys return keys
.map(function(k){ .map(function(k){
var e = make(k) var disable = null
if(pattern){
var n = k.replace(pattern, '')
if(n != k){
disable = true
if(that.options.skipDisabledItems){
return
}
}
}
var e = make(n, null, disable)
if(data !== keys){ if(data !== keys){
e.on('open', function(){ e.on('open', function(){
@ -2105,6 +2155,9 @@ module.makeList = makeBrowserMaker(List)
// NOTE: in the A|B|C pattern, ALL of the alternatives will be created. // NOTE: in the A|B|C pattern, ALL of the alternatives will be created.
// NOTE: there may be multiple matching patterns/listers or a given path // NOTE: there may be multiple matching patterns/listers or a given path
// the one used is the longest match. // the one used is the longest match.
// NOTE: if path is receded with '- ' ('- a|b/c') then the basename of
// that path will be disabled, to control the pattern use
// .disableItemPattern and to disable this feature set it to false.
// //
// //
// Handler format: // Handler format:
@ -2136,10 +2189,21 @@ PathListPrototype.options = {
traversable: true, traversable: true,
flat: false, flat: false,
// XXX not sure if we need these...
skipDisabledItems: false,
// NOTE: to disable this set it to false or null
disableItemPattern: '^- ',
list: function(path, make){ list: function(path, make){
var that = this var that = this
var data = this.options.data var data = this.options.data
var keys = data.constructor == Array ? data : Object.keys(data) var keys = data.constructor == Array ? data : Object.keys(data)
var pattern = this.options.disableItemPattern
&& RegExp(this.options.disableItemPattern)
if(pattern && this.options.skipDisabledItems){
keys = keys.filter(function(k){ return !pattern.test(k) })
}
var visited = [] var visited = []
@ -2182,6 +2246,13 @@ PathListPrototype.options = {
} else { } else {
return keys return keys
.map(function(k){ .map(function(k){
var disable = null
if(pattern){
var n = k.replace(pattern, '')
disable = n != k
k = n
}
var kp = k.split(/[\\\/]+/g) var kp = k.split(/[\\\/]+/g)
kp[0] == '' && kp.shift() kp[0] == '' && kp.shift()
@ -2203,26 +2274,36 @@ PathListPrototype.options = {
return false return false
} }
cur.split('|').forEach(function(cur){ cur.split('|')
if(visited.indexOf(cur) >= 0){ // skip empty path items...
// set element to traversable... // NOTE: this avoids creating empty items in cases
if(kp.length > 0){ // of paths ending with '/' or containing '//'
that.filter(cur).removeClass('not-traversable') .filter(function(e){ return e.trim() != '' })
.forEach(function(cur){
if(visited.indexOf(cur) >= 0){
// set element to traversable if we visit it again...
if(kp.length > 0){
that.filter(cur, false)
.removeClass('not-traversable')
//.removeClass('disabled')
}
return false
} }
return false visited.push(cur)
}
visited.push(cur)
// build the element.... // build the element....
var e = make(cur, star || kp.length > 0) var e = make(cur,
star || kp.length > 0,
// XXX this might still disable a dir...
!star && kp.length == 0 && disable)
// setup handlers... // setup handlers...
if(!star && data !== keys && kp.length == 0 && data[k] != null){ if(!star && data !== keys && kp.length == 0 && data[k] != null){
e.on('open', function(){ e.on('open', function(){
return that.options.data[k].apply(this, arguments) return that.options.data[k].apply(this, arguments)
}) })
} }
}) })
return cur return cur
}) })

View File

@ -35,7 +35,7 @@ var ribbons = require('ribbons')
/*********************************************************************/ /*********************************************************************/
// helpers... // Helpers...
function reloadAfter(force){ function reloadAfter(force){
return function(){ return function(){
@ -250,12 +250,12 @@ actions.Actions({
// basic life-cycle actions... // basic life-cycle actions...
// //
// XXX do we need to call .syncTags(..) here??? // XXX do we need to call .syncTags(..) here???
load: ['File|Interface/', load: ['- File|Interface/',
function(d){ function(d){
this.images = images.Images(d.images) this.images = images.Images(d.images)
this.data = data.Data(d.data) this.data = data.Data(d.data)
}], }],
clear: ['File|Interface/', clear: ['File|Interface/Clear viewer',
function(){ function(){
delete this.data delete this.data
delete this.images delete this.images
@ -263,7 +263,7 @@ actions.Actions({
// NOTE: for complete isolation it is best to completely copy the // NOTE: for complete isolation it is best to completely copy the
// .config... // .config...
clone: ['File/', clone: ['- File/',
function(full){ function(full){
var res = actions.MetaActions.clone.call(this, full) var res = actions.MetaActions.clone.call(this, full)
@ -293,7 +293,7 @@ actions.Actions({
// adding new items to the resulting structure... // adding new items to the resulting structure...
// XXX is this the correct way to go??? // XXX is this the correct way to go???
// ...can we save simple attribute values??? // ...can we save simple attribute values???
json: ['File/Dump state as JSON object', json: ['- File/Dump state as JSON object',
'This will collect JSON data from every available attribute ' 'This will collect JSON data from every available attribute '
+'supporting the .dumpJSON() method.', +'supporting the .dumpJSON() method.',
function(mode){ function(mode){
@ -314,7 +314,7 @@ actions.Actions({
// basic navigation... // basic navigation...
// //
focusImage: ['Navigate/Focus image', focusImage: ['- Navigate/Focus image',
function(img, list){ function(img, list){
this.data.focusImage(img, list) this.data.focusImage(img, list)
}], }],
@ -326,7 +326,7 @@ actions.Actions({
// 'visual' - focus visually closest to current image // 'visual' - focus visually closest to current image
// //
// NOTE: default mode is set in .config.ribbon-focus-mode // NOTE: default mode is set in .config.ribbon-focus-mode
focusRibbon: ['Navigate/Focus Ribbon', focusRibbon: ['- Navigate/Focus Ribbon',
function(target, mode){ function(target, mode){
var data = this.data var data = this.data
var r = data.getRibbon(target) var r = data.getRibbon(target)
@ -464,9 +464,9 @@ actions.Actions({
}], }],
// XXX should these be here??? // XXX should these be here???
prevTagged: ['Navigate/Previous image tagged with tag', prevTagged: ['- Navigate/Previous image tagged with tag',
makeTagWalker('prev')], makeTagWalker('prev')],
nextTagged: ['Navigate/Next image tagged with tag', nextTagged: ['- Navigate/Next image tagged with tag',
makeTagWalker('next')], makeTagWalker('next')],
firstRibbon: ['Navigate/First ribbon', firstRibbon: ['Navigate/First ribbon',
@ -484,7 +484,7 @@ actions.Actions({
// NOTE: for all of these, current/ribbon image is a default... // NOTE: for all of these, current/ribbon image is a default...
// XXX to be used for things like mark/place and dragging... // XXX to be used for things like mark/place and dragging...
shiftImageTo: ['Edit|Sort/', shiftImageTo: ['- Edit|Sort/',
function(target, to){ function(target, to){
// XXX // XXX
}], }],
@ -634,7 +634,7 @@ actions.Actions({
// tags... // tags...
// //
// XXX mark updated... // XXX mark updated...
tag: ['Tag/Tag image(s)', tag: ['- Tag/Tag image(s)',
function(tags, gids){ function(tags, gids){
gids = gids || this.current gids = gids || this.current
gids = gids.constructor !== Array ? [gids] : gids gids = gids.constructor !== Array ? [gids] : gids
@ -660,7 +660,7 @@ actions.Actions({
}) })
}], }],
// XXX mark updated... // XXX mark updated...
untag: ['Tag/Untag image(s)', untag: ['- Tag/Untag image(s)',
function(tags, gids){ function(tags, gids){
gids = gids || this.current gids = gids || this.current
gids = gids.constructor !== Array ? [gids] : gids gids = gids.constructor !== Array ? [gids] : gids
@ -733,7 +733,7 @@ actions.Actions({
// crop... // crop...
// //
crop: ['Crop/Crop image list', crop: ['- Crop/Crop image list',
function(list, flatten){ function(list, flatten){
list = list || this.data.order list = list || this.data.order
if(this.crop_stack == null){ if(this.crop_stack == null){
@ -844,7 +844,7 @@ actions.Actions({
// grouping... // grouping...
// XXX need to tell .images about this... // XXX need to tell .images about this...
group: ['Group|Edit/Group images', group: ['- Group|Edit/Group images',
function(gids, group){ this.data.group(gids, group) }], function(gids, group){ this.data.group(gids, group) }],
ungroup: ['Group|Edit/Ungroup images', ungroup: ['Group|Edit/Ungroup images',
function(gids, group){ this.data.ungroup(gids, group) }], function(gids, group){ this.data.ungroup(gids, group) }],
@ -852,7 +852,7 @@ actions.Actions({
// direction can be: // direction can be:
// 'next' // 'next'
// 'prev' // 'prev'
groupTo: ['Group|Edit/Group to', groupTo: ['- Group|Edit/Group to',
function(target, direction){ function(target, direction){
target = this.data.getImage(target) target = this.data.getImage(target)
var other = this.data.getImage(target, direction == 'next' ? 1 : -1) var other = this.data.getImage(target, direction == 'next' ? 1 : -1)
@ -1065,7 +1065,7 @@ actions.Actions({
// XXX problem: need to either redesign this or distinguish from // XXX problem: need to either redesign this or distinguish from
// other actions as I keep calling it expecting results... // other actions as I keep calling it expecting results...
// XXX hide from user action list... // XXX hide from user action list...
updateImage: ['Interface/Update image (This will do nothing)', updateImage: ['- Interface/Update image (This will do nothing)',
'This will be called by .refresh(..) and intended for use as an ' 'This will be called by .refresh(..) and intended for use as an '
+'trigger for handlers, and not as a callable acation.', +'trigger for handlers, and not as a callable acation.',
function(gid, image){ }], function(gid, image){ }],
@ -1081,7 +1081,7 @@ actions.Actions({
'dark', 'dark',
'light' 'light'
]) ], ]) ],
setEmptyMsg: ['Interface/Set message to be displayed when nothing is loaded.', setEmptyMsg: ['- Interface/Set message to be displayed when nothing is loaded.',
function(msg, help){ this.ribbons.setEmptyMsg(msg, help) }], function(msg, help){ this.ribbons.setEmptyMsg(msg, help) }],
@ -1184,7 +1184,7 @@ actions.Actions({
// NOTE: this will align only a single image... // NOTE: this will align only a single image...
// XXX do we need these low level primitives here??? // XXX do we need these low level primitives here???
centerImage: ['Interface/Center an image in ribbon horizontally', centerImage: ['- Interface/Center an image in ribbon horizontally',
function(target, align){ function(target, align){
target = target instanceof jQuery target = target instanceof jQuery
? this.ribbons.getElemGID(target) ? this.ribbons.getElemGID(target)
@ -1193,7 +1193,7 @@ actions.Actions({
// align current ribbon... // align current ribbon...
this.ribbons.centerImage(target, align) this.ribbons.centerImage(target, align)
}], }],
centerRibbon: ['Interface/Center a ribbon vertically', centerRibbon: ['- Interface/Center a ribbon vertically',
function(target){ function(target){
target = target instanceof jQuery target = target instanceof jQuery
? this.ribbons.getElemGID(target) ? this.ribbons.getElemGID(target)
@ -1493,7 +1493,7 @@ module.Journal = ImageGridFeatures.Feature({
}], }],
// XXX might be good to add some kind of metadata to journal... // XXX might be good to add some kind of metadata to journal...
journalPush: ['Journal/Add an item to journal', journalPush: ['- Journal/Add an item to journal',
function(){ function(){
this.journal = (this.hasOwnProperty('journal') this.journal = (this.hasOwnProperty('journal')
|| this.journal) ? || this.journal) ?
@ -1515,7 +1515,7 @@ module.Journal = ImageGridFeatures.Feature({
this.journal = null this.journal = null
} }
}], }],
runJournal: ['Journal/Run journal', runJournal: ['- Journal/Run journal',
function(journal){ function(journal){
var that = this var that = this
journal.forEach(function(e){ journal.forEach(function(e){
@ -1694,7 +1694,7 @@ var PartialRibbonsActions = actions.Actions({
// XXX coordinate this with .resizeRibbon(..) // XXX coordinate this with .resizeRibbon(..)
// XXX make this support an explicit list of gids.... // XXX make this support an explicit list of gids....
// XXX should this be here??? // XXX should this be here???
preCacheJumpTargets: ['Interface/Pre-cache potential jump target images', preCacheJumpTargets: ['- Interface/Pre-cache potential jump target images',
function(target, sources, radius, size){ function(target, sources, radius, size){
target = target instanceof jQuery target = target instanceof jQuery
? this.ribbons.getElemGID(target) ? this.ribbons.getElemGID(target)
@ -1806,7 +1806,7 @@ var PartialRibbonsActions = actions.Actions({
// - we are less than screen width from the edge // - we are less than screen width from the edge
// - threshold is set to 0 // - threshold is set to 0
// XXX this is not signature compatible with data.updateRibbon(..) // XXX this is not signature compatible with data.updateRibbon(..)
updateRibbon: ['Interface/Update partial ribbon size', updateRibbon: ['- Interface/Update partial ribbon size',
function(target, w, size, threshold){ function(target, w, size, threshold){
target = target instanceof jQuery target = target instanceof jQuery
? this.ribbons.getElemGID(target) ? this.ribbons.getElemGID(target)
@ -1884,7 +1884,7 @@ var PartialRibbonsActions = actions.Actions({
} }
}], }],
// XXX do we handle off-screen ribbons here??? // XXX do we handle off-screen ribbons here???
resizeRibbon: ['Interface/Resize ribbon to n images', resizeRibbon: ['- Interface/Resize ribbon to n images',
function(target, size){ function(target, size){
size = size size = size
|| (this.config['ribbon-size-screens'] * this.screenwidth) || (this.config['ribbon-size-screens'] * this.screenwidth)
@ -2291,7 +2291,7 @@ module.ShiftAnimation = ImageGridFeatures.Feature({
//--------------------------------------------------------------------- //---------------------------------------------------------------------
var BoundsIndicatorsActions = actions.Actions({ var BoundsIndicatorsActions = actions.Actions({
flashIndicator: ['Interface/Flash an indicator', flashIndicator: ['- Interface/Flash an indicator',
function(direction){ function(direction){
if(this.ribbons.getRibbonSet().length == 0){ if(this.ribbons.getRibbonSet().length == 0){
return return
@ -2433,7 +2433,7 @@ var CurrentImageIndicatorActions = actions.Actions({
'current-image-indicator-screen-nav-mode': 'hide', 'current-image-indicator-screen-nav-mode': 'hide',
}, },
updateCurrentImageIndicator: ['Interface/Update current image indicator', updateCurrentImageIndicator: ['- Interface/Update current image indicator',
function(target, update_border){ function(target, update_border){
var ribbon_set = this.ribbons.getRibbonSet() var ribbon_set = this.ribbons.getRibbonSet()
@ -2874,15 +2874,19 @@ var makeActionLister = function(list, filter, pre_order){
var ActionTreeActions = actions.Actions({ var ActionTreeActions = actions.Actions({
config: { config: {
// NOTE: the slashes at the end are significant, of they are not
// present the .toggleNonTraversableDrawing(..) will hide
// these paths before they can get any content...
// XXX not sure if this is a bug or not...
'action-category-order': [ 'action-category-order': [
'File', 'File/',
'Edit', 'Edit/',
'Navigate', 'Navigate/',
], ],
}, },
// XXX move this to a generic modal overlay feature... // XXX move this to a generic modal overlay feature...
getOverlay: ['Interface/Get overlay object', getOverlay: ['- Interface/Get overlay object',
function(o){ function(o){
return overlay.getOverlay(o || this.viewer) return overlay.getOverlay(o || this.viewer)
}], }],
@ -3254,7 +3258,7 @@ var ImageMarkActions = actions.Actions({
// XXX // XXX
}], }],
markTagged: ['Mark/Mark images by tags', markTagged: ['- Mark/Mark images by tags',
function(tags, mode){ function(tags, mode){
var selector = mode == 'any' ? 'getTaggedByAny' : 'getTaggedByAll' var selector = mode == 'any' ? 'getTaggedByAny' : 'getTaggedByAll'
@ -3495,7 +3499,7 @@ var FileSystemLoaderActions = actions.Actions({
// XXX is this a hack??? // XXX is this a hack???
// XXX need a more generic form... // XXX need a more generic form...
checkPath: ['File/', checkPath: ['- File/',
function(path){ return fse.existsSync(path) }], function(path){ return fse.existsSync(path) }],
// NOTE: when passed no path this will not do anything... // NOTE: when passed no path this will not do anything...
@ -3910,7 +3914,7 @@ var URLHistoryActions = actions.Actions({
} }
}], }],
setTopURLHistory: ['History/', setTopURLHistory: ['- History/',
function(url){ function(url){
var data = this.url_history[url] var data = this.url_history[url]
@ -3921,7 +3925,7 @@ var URLHistoryActions = actions.Actions({
delete this.url_history[url] delete this.url_history[url]
this.url_history[url] = data this.url_history[url] = data
}], }],
pushURLToHistory: ['History/', pushURLToHistory: ['- History/',
function(url, open, check){ function(url, open, check){
var l = this.config['url-history-length'] || -1 var l = this.config['url-history-length'] || -1
@ -3954,7 +3958,7 @@ var URLHistoryActions = actions.Actions({
}], }],
// NOTE: url can be an index, 0 being the last url added to history; // NOTE: url can be an index, 0 being the last url added to history;
// negative values are also supported. // negative values are also supported.
dropURLFromHistory: ['History/', dropURLFromHistory: ['- History/',
function(url){ function(url){
this.url_history = this.url_history || {} this.url_history = this.url_history || {}
@ -3966,7 +3970,7 @@ var URLHistoryActions = actions.Actions({
delete this.url_history[url] delete this.url_history[url]
} }
}], }],
checkURLFromHistory: ['History/', checkURLFromHistory: ['- History/',
function(url){ function(url){
this.url_history = this.url_history || {} this.url_history = this.url_history || {}
@ -3990,7 +3994,7 @@ var URLHistoryActions = actions.Actions({
return true return true
} }
}], }],
openURLFromHistory: ['History/', openURLFromHistory: ['- History/',
function(url){ function(url){
this.url_history = this.url_history || {} this.url_history = this.url_history || {}
@ -4096,7 +4100,7 @@ var URLHistoryLocalStorageActions = actions.Actions({
localStorage[loaded] = this.base_path localStorage[loaded] = this.base_path
} }
}], }],
loadLastSavedBasePath: ['History/', loadLastSavedBasePath: ['- History/',
function(){ function(){
var loaded = this.config['url-history-loaded-local-storage-key'] var loaded = this.config['url-history-loaded-local-storage-key']
@ -4187,12 +4191,6 @@ var URLHistoryUIActions = actions.Actions({
}) })
to_remove = [] to_remove = []
} }
var makeRE = function(path){
return RegExp('^'
// quote regular expression chars...
+path.replace(/([\.\\\/\(\)\[\]\$\*\+\-\{\}\@\^\&\?\<\>])/g, '\\$1')
+'$')
}
var o = overlay.Overlay(this.ribbons.viewer, var o = overlay.Overlay(this.ribbons.viewer,
browse.makeList( browse.makeList(
@ -4205,7 +4203,7 @@ var URLHistoryUIActions = actions.Actions({
['&diams;', ['&diams;',
function(p){ function(p){
var top = this.filter().first() var top = this.filter().first()
var cur = this.filter(makeRE(p)) var cur = this.filter('"'+p+'"')
if(!top.is(cur)){ if(!top.is(cur)){
top.before(cur) top.before(cur)
@ -4215,7 +4213,7 @@ var URLHistoryUIActions = actions.Actions({
// mark for removal... // mark for removal...
['&times;', ['&times;',
function(p){ function(p){
var e = this.filter(makeRE(p)) var e = this.filter('"'+p+'"')
.toggleClass('strike-out') .toggleClass('strike-out')
if(e.hasClass('strike-out')){ if(e.hasClass('strike-out')){
@ -4435,7 +4433,7 @@ var FileSystemWriterActions = actions.Actions({
// //
// For more info see file.writeIndex(..) and file.loadIndex(..). // For more info see file.writeIndex(..) and file.loadIndex(..).
// //
prepareIndexForWrite: ['File/Prepare index for writing', prepareIndexForWrite: ['- File/Prepare index for writing',
function(json, full){ function(json, full){
json = json || this.json('base') json = json || this.json('base')
var changes = full ? null var changes = full ? null