diff --git a/ui (gen4)/css/layout.less b/ui (gen4)/css/layout.less index 66688b74..f76b7aeb 100755 --- a/ui (gen4)/css/layout.less +++ b/ui (gen4)/css/layout.less @@ -1034,15 +1034,15 @@ stretching in width... */ } .mark.bookmark, -.mark.selected { +.mark.marked { width: 0px; margin-left: 0px; border: none; overflow: visible; } .mark.bookmark:after, -.mark.selected:before, -.mark.selected:after { +.mark.marked:before, +.mark.marked:after { display: block; position: absolute; content: ""; @@ -1082,9 +1082,9 @@ stretching in width... */ } -/* the selected tick... */ -.mark.selected:before, -.mark.selected:after { +/* the marked tick... */ +.mark.marked:before, +.mark.marked:after { top: @image-tile-size/30; left: -@image-tile-size/15; bottom: auto; @@ -1093,11 +1093,11 @@ stretching in width... */ .rotate(-45deg); } -.mark.selected:before { +.mark.marked:before { width: @image-tile-size/100; height: @image-tile-size/50; } -.mark.selected:after { +.mark.marked:after { width: @image-tile-size/25; height: @image-tile-size/100; } @@ -1406,7 +1406,7 @@ stretching in width... */ } -/* XXX REUSE: this is the same as selected/bookmarked image markers... */ +/* XXX REUSE: this is the same as marked/bookmarked image markers... */ .overlay-info .marked, .overlay-info .marked:after, .overlay-info .marked:before, diff --git a/ui (gen4)/features/base.js b/ui (gen4)/features/base.js index 16ee169c..8b70b391 100755 --- a/ui (gen4)/features/base.js +++ b/ui (gen4)/features/base.js @@ -1290,7 +1290,7 @@ module.TagsEditActions = actions.Actions({ // NOTE: setting source to 'both' and mode to 'reset' is the same as // 'images' and 'reset' as all .data tags will be lost on first // pass... - syncTags: ['Tag/Synchoronize tags between data and images', + syncTags: ['Tag/-10:Synchoronize tags between data and images', {journal: true}, function(source, mode){ // can't do anything if either .data or .images are not @@ -1350,8 +1350,8 @@ module.TagsEdit = core.ImageGridFeatures.Feature({ if(tags.length > 0){ this.markChanged('tags') - tags.indexOf('selected') >= 0 - && this.markChanged('selected') + tags.indexOf('marked') >= 0 + && this.markChanged('marked') tags.indexOf('bookmark') >= 0 && this.markChanged('bookmarked') @@ -1360,7 +1360,7 @@ module.TagsEdit = core.ImageGridFeatures.Feature({ this.markChanged('images', gids) }], - // store .tags and .tags.selected / .tags.bookmark separately from .data... + // store .tags and .tags.marked / .tags.bookmark separately from .data... // // XXX see if this can be automated... ['prepareIndexForWrite', @@ -1375,9 +1375,9 @@ module.TagsEdit = core.ImageGridFeatures.Feature({ res.index.tags = res.raw.data.tags } - // XXX should we save an empty list *iff* changes.selected is true??? - if(changes === true || changes.selected){ - res.index.marked = (res.raw.data.tags || {}).selected || [] + // XXX should we save an empty list *iff* changes.marked is true??? + if(changes === true || changes.marked){ + res.index.marked = (res.raw.data.tags || {}).marked || [] } // XXX should we save an empty list *iff* changes.bookmarked is true??? if(changes === true || changes.bookmarked){ @@ -1389,7 +1389,7 @@ module.TagsEdit = core.ImageGridFeatures.Feature({ // cleanup... if(res.index.data && res.index.data.tags){ - delete res.index.data.tags.selected + delete res.index.data.tags.marked delete res.index.data.tags.bookmark //delete res.index.data.tags.bookmark_data delete res.index.data.tags @@ -1399,7 +1399,7 @@ module.TagsEdit = core.ImageGridFeatures.Feature({ function(res, json){ res.data.tags = json.tags || {} - res.data.tags.selected = json.marked || [] + res.data.tags.marked = json.marked || [] res.data.tags.bookmark = json.bookmarked ? json.bookmarked[0] : [] //res.data.tags.bookmark_data = json.bookmarked ? json.bookmarked[1] : {} diff --git a/ui (gen4)/features/collections.js b/ui (gen4)/features/collections.js index d9d6fa47..db1ee31f 100755 --- a/ui (gen4)/features/collections.js +++ b/ui (gen4)/features/collections.js @@ -2865,7 +2865,7 @@ var CollectionMarksActions = actions.Actions({ CollectionTagsActions.config['collection-local-tags'] .concat([ 'bookmark', - 'selected', + 'marked', ]), 'collection-transfer-changes': @@ -2875,7 +2875,7 @@ var CollectionMarksActions = actions.Actions({ CollectionActions.config['collection-transfer-changes'] .concat([ 'bookmarked', - 'selected', + 'marked', ]), }, @@ -2883,13 +2883,13 @@ var CollectionMarksActions = actions.Actions({ collectMarked: ['- Collections|Mark/', function(collection){ return this.collect(this.marked, collection) }], - //return this.collectTagged('selected', collection) }], + //return this.collectTagged('marked', collection) }], uncollectMarked: ['Collections|Mark/Remove marked from collection', {browseMode: function(){ return (!this.collection || this.marked.length == 0) && 'disabled' }}, function(collection){ return this.uncollect(this.marked, collection) }], - //return this.uncollectTagged('selected', collection) }], + //return this.uncollectTagged('marked', collection) }], // bookmarked... collectBookmarked: ['- Collections|Bookmark/', diff --git a/ui (gen4)/features/demo.js b/ui (gen4)/features/demo.js index 40abf51a..a6188c14 100755 --- a/ui (gen4)/features/demo.js +++ b/ui (gen4)/features/demo.js @@ -37,7 +37,7 @@ module.demo_data = { }, tags: { - selected: ['b', 'z'], + marked: ['b', 'z'], bookmark: ['1', 'c', 'z'], }, diff --git a/ui (gen4)/features/examples.js b/ui (gen4)/features/examples.js index 08a7fb2d..840c8808 100755 --- a/ui (gen4)/features/examples.js +++ b/ui (gen4)/features/examples.js @@ -351,7 +351,7 @@ var ExampleUIActions = actions.Actions({ }) make('do nothing') - .addClass('selected') + .addClass('marked') make('nested dialog...', { @@ -767,8 +767,8 @@ var ExampleUIActions = actions.Actions({ }], showBookmarkedInDrawer: ['Test/Show bookmarked in drawer', function(){ this.showTaggedInDrawer('bookmark') }], - showSelectedInDrawer: ['Test/Show selected in drawer', - function(){ this.showTaggedInDrawer('selected') }], + showSelectedInDrawer: ['Test/Show marked in drawer', + function(){ this.showTaggedInDrawer('marked') }], makePartitionAfter: ['Test/Make Partition after image', diff --git a/ui (gen4)/features/filesystem.js b/ui (gen4)/features/filesystem.js index a580ebbe..f7f8f8ea 100755 --- a/ui (gen4)/features/filesystem.js +++ b/ui (gen4)/features/filesystem.js @@ -2083,7 +2083,7 @@ var FileSystemWriterActions = actions.Actions({ // tags... // XXX test: %n%(b)b%(m)m%e .replace( - /%\(([^)]*)\)m/, tags.indexOf('selected') >= 0 ? '$1' : '') + /%\(([^)]*)\)m/, tags.indexOf('marked') >= 0 ? '$1' : '') .replace( /%\(([^)]*)\)b/, tags.indexOf('bookmark') >= 0 ? '$1' : '') @@ -2369,7 +2369,7 @@ var FileSystemWriterUIActions = actions.Actions({ ['Marked:', actions.formatImageName(pattern, img, - {tags: ['selected']})], + {tags: ['marked']})], ['Bookmarked:', actions.formatImageName(pattern, img, @@ -2383,7 +2383,7 @@ var FileSystemWriterUIActions = actions.Actions({ img, { tags: [ - 'selected', + 'marked', 'bookmark', ], conflicts: { diff --git a/ui (gen4)/features/keyboard.js b/ui (gen4)/features/keyboard.js index e3037ac0..9bfcf0b4 100755 --- a/ui (gen4)/features/keyboard.js +++ b/ui (gen4)/features/keyboard.js @@ -208,6 +208,7 @@ module.GLOBAL_KEYBOARD = { alt_F: 'browseActions: "/File/" -- File menu...', alt_E: 'browseActions: "/Edit/" -- Edit menu...', alt_N: 'browseActions: "/Navigate/" -- Navigate menu...', + alt_T: 'browseActions: "/Tag/" -- Tag menu...', //alt_S: 'browseActions: "/Sort/" -- Sort menu...', alt_shift_A: 'listActions', @@ -398,6 +399,9 @@ module.GLOBAL_KEYBOARD = { I: 'showMetadata', //ctrl_shift_I: 'showMetadata: "current" "full" -- Show full metadata', + // XXX + ctrl_T: 'showTagCloud', + // marking... M: 'toggleMark', diff --git a/ui (gen4)/features/marks.js b/ui (gen4)/features/marks.js index fe058e32..82f0bfca 100755 --- a/ui (gen4)/features/marks.js +++ b/ui (gen4)/features/marks.js @@ -230,11 +230,11 @@ var ImageMarkActions = actions.Actions({ get marked(){ if(this.data == null || this.data.tags == null - || !('selected' in this.data.tags)){ + || !('marked' in this.data.tags)){ return [] } - //return this.data.tags['selected'].slice() - return this.data.getImages(this.data.tags['selected']) + //return this.data.tags['marked'].slice() + return this.data.getImages(this.data.tags['marked']) }, markedInRibbon: ['- Mark|Ribbon/', @@ -250,16 +250,16 @@ var ImageMarkActions = actions.Actions({ prevMarked: ['Mark|Navigate/Previous marked image', {browseMode: function(target){ return this.data.getImage('current', 'before', this.marked) == null && 'disabled' }}, - function(mode){ this.prevTagged('selected', mode) }], + function(mode){ this.prevTagged('marked', mode) }], nextMarked: ['Mark|Navigate/Next marked image', {browseMode: function(target){ return this.data.getImage('current', 'after', this.marked) == null && 'disabled' }}, - function(mode){ this.nextTagged('selected', mode) }], + function(mode){ this.nextTagged('marked', mode) }], cropMarked: ['Mark|Crop/Crop $marked images', {browseMode: function(target){ return this.marked.length == 0 && 'disabled' }}, - function(flatten){ this.cropTagged('selected', 'any', flatten) }], + function(flatten){ this.cropTagged('marked', 'any', flatten) }], removeMarkedFromCrop: ['Mark|Crop/Remove marked from crop', {browseMode: function(target){ @@ -320,7 +320,7 @@ var ImageMarkEditActions = actions.Actions({ // toggleMark: ['Mark|Image/Image $mark', undoTag('toggleMark'), - makeTagTogglerAction('selected')], + makeTagTogglerAction('marked')], toggleMarkBlock: ['Mark/Invert $block marks', core.doc`A block is a set of adjacent images either marked on unmarked in the same way @@ -485,8 +485,8 @@ module.ImageMarksUI = core.ImageGridFeatures.Feature({ && this.ribbons .toggleImageMark( gid, - 'selected', - this.data.hasTag(gid, 'selected') ? 'on' : 'off') + 'marked', + this.data.hasTag(gid, 'marked') ? 'on' : 'off') }], ], }) @@ -563,7 +563,7 @@ var ImageBookmarkEditActions = actions.Actions({ toggleBookmarkOnMarked: ['Bookmark|Mark/-70:Toggle bookmark on maked images', {browseMode: 'cropMarked'}, function(action){ - return this.toggleBookmark(this.data.getTaggedByAny('selected'), action) + return this.toggleBookmark(this.data.getTaggedByAny('marked'), action) }], }) diff --git a/ui (gen4)/features/meta.js b/ui (gen4)/features/meta.js index f67de4e0..7278f269 100755 --- a/ui (gen4)/features/meta.js +++ b/ui (gen4)/features/meta.js @@ -66,6 +66,8 @@ core.ImageGridFeatures.Feature('imagegrid-ui-minimal', [ 'ui-bounds-indicators', 'ui-current-image-indicator', + + 'ui-tags', ]) diff --git a/ui (gen4)/features/tags.js b/ui (gen4)/features/tags.js index 9e57c77a..0bd46cd6 100755 --- a/ui (gen4)/features/tags.js +++ b/ui (gen4)/features/tags.js @@ -11,6 +11,9 @@ var actions = require('lib/actions') var features = require('lib/features') var core = require('features/core') +var widgets = require('features/ui-widgets') + +var browse = require('lib/widget/browse') @@ -32,7 +35,6 @@ module.PersistentTags = core.ImageGridFeatures.Feature({ depends: [ 'base', ], - actions: PersistentTagsActions, handlers: [], @@ -53,6 +55,100 @@ module.PersistentTags = core.ImageGridFeatures.Feature({ // var TagUIActions = actions.Actions({ + // XXX use global tag list... (???) + showTagCloud: ['Tag|Edit|Image/$Tags...', + core.doc` + `, + {dialogTitle: function(_, gids){ + return (gids.length == 1 && gids[0] == 'marked') ? + 'Marked image tags' + : gids.length > 1 ? + 'Tags of: '+ gids.join(', ') + : 'Tags' }}, + widgets.makeUIDialog(function(...gids){ + var that = this + gids = gids.length == 0 ? ['current'] : gids + // handle 'marked' keyword... + gids = gids + .map(function(gid){ + return gid == 'marked' ? that.marked : gid }) + .reduce(function(res, cur){ + return res.concat(cur instanceof Array ? cur : [cur]) }, []) + .unique() + + // XXX + var removeTag = function(tag){ + console.log('REMOVE TAG:', tag) + } + + return browse.makeLister(null, function(path, make){ + var tags = that.data.getTags(gids) + + // tags... + // XXX make this a group... + // XXX indicate if some of the gids are tagged... + // ...need three states per tag: + // - on - all are tagged + // - partial - some are tagged + // - off - none are tagged + // XXX add key binding to delete a tag... + Object.keys(that.data.tags || {}) + .sort() + .map(function(tag){ + return make(tag, { + cls: tags.indexOf(tag) >= 0 ? 'tagged' : '', + style: { + opacity: tags.indexOf(tag) >= 0 ? '' : '0.3' + }, + open: function(){ + var e = $(this) + var on = e.css('opacity') + on = on == '' || on == '1' + + e.css('opacity', on ? 0.3 : '') + + on ? + that.data.untag(tag, gids) + : that.data.tag(tag, gids) + }, + buttons: [ + // remove tag button... + ['×', removeTag.bind(that, tag) ], + ], + }) + }) + + make.Separator() + + make.Editable('$New...', { + clear_on_edit: true, + editdone: function(evt, tag){ + tag = tag.trim() + // no empty tags... + if(tag == ''){ + return + } + + that.data.tag(tag, gids) + + // update tag list... + make.dialog + .update() + // select the new tag... + .then(function(){ + make.dialog.select(tag) }) + }, + }) + }, { + cloudView: true, + close: function(){ that.refresh() }, + }) + })], + showMakedTagCoud: ['Tag|Mark/$Tags of marked images...', + 'showTagCloud: "marked"'], + + // XXX crop/filter by tags... + // XXX }) diff --git a/ui (gen4)/features/ui-partial-ribbons-precache.js b/ui (gen4)/features/ui-partial-ribbons-precache.js index c18cf280..cd4890e2 100755 --- a/ui (gen4)/features/ui-partial-ribbons-precache.js +++ b/ui (gen4)/features/ui-partial-ribbons-precache.js @@ -22,7 +22,7 @@ var PreCacheActions = actions.Actions({ 'preload-radius': 5, // Sources to preload... - 'preload-sources': ['bookmark', 'selected'], + 'preload-sources': ['bookmark', 'marked'], }, // NOTE: this will not work from chrome when loading from a local fs... @@ -75,7 +75,7 @@ var PreCacheActions = actions.Actions({ // // Sources supported: // - pre-load images tagged with - // (default: ['bookmark', 'selected']) + // (default: ['bookmark', 'marked']) // - pre-cache from a specific ribbon // 'ribbon' - pre-cache from current ribbon // 'order' - pre-cache from images in order @@ -115,7 +115,7 @@ var PreCacheActions = actions.Actions({ : (this.data.getImage(target) || this.data.getImage(target, 'after')) - sources = sources || this.config['preload-sources'] || ['bookmark', 'selected'] + sources = sources || this.config['preload-sources'] || ['bookmark', 'marked'] sources = sources.constructor !== Array ? [sources] : sources radius = radius || this.config['preload-radius'] || 9 diff --git a/ui (gen4)/features/ui-preact-render.js b/ui (gen4)/features/ui-preact-render.js index a581c432..beac76e3 100755 --- a/ui (gen4)/features/ui-preact-render.js +++ b/ui (gen4)/features/ui-preact-render.js @@ -76,7 +76,7 @@ class IGRibbon extends preact.Component { var images = data.ribbons[ribbon] .map(function(gid){ - var marks = data.tags.selected.indexOf(gid) >= 0 ? + var marks = data.tags.marked.indexOf(gid) >= 0 ? h(IGImageMark, { gid: gid, type: 'selected', diff --git a/ui (gen4)/features/ui-status.js b/ui (gen4)/features/ui-status.js index 3ec23480..066b0596 100755 --- a/ui (gen4)/features/ui-status.js +++ b/ui (gen4)/features/ui-status.js @@ -477,7 +477,7 @@ var StatusBarActions = actions.Actions({ // ...this also simpler than handling '?' and other // special toggler args in the handler... var tags = this.data ? this.data.getTags(gid) : [] - var tag = type == 'mark' ? 'selected' : 'bookmark' + var tag = type == 'mark' ? 'marked' : 'bookmark' var on = item.hasClass('on') item[tags.indexOf(tag) < 0 ? 'removeClass' diff --git a/ui (gen4)/features/ui-virtual-dom.js b/ui (gen4)/features/ui-virtual-dom.js index ed7a79ff..9d2e8fac 100755 --- a/ui (gen4)/features/ui-virtual-dom.js +++ b/ui (gen4)/features/ui-virtual-dom.js @@ -236,8 +236,8 @@ var VirtualDOMRibbonsPrototype = { // XXX STUB: make this extensible... tags.indexOf('bookmark') >= 0 && marks.push('bookmark') - tags.indexOf('selected') >= 0 - && marks.push('selected') + tags.indexOf('marked') >= 0 + && marks.push('marked') return marks .map(function(type){ diff --git a/ui (gen4)/features/ui-widgets.js b/ui (gen4)/features/ui-widgets.js index 2bb8c351..5054e1b8 100755 --- a/ui (gen4)/features/ui-widgets.js +++ b/ui (gen4)/features/ui-widgets.js @@ -895,7 +895,7 @@ module.Dialogs = core.ImageGridFeatures.Feature({ && this.toggleOverlayBlur(this.config['ui-overlay-blur']) }], ['__call__', - function(res, action){ + function(res, action, args){ //if(res instanceof jQuery || res instanceof widget.Widget){ // var elem = (res.dom || res) if(res instanceof widget.Widget){ @@ -904,7 +904,10 @@ module.Dialogs = core.ImageGridFeatures.Feature({ var title = this.getActionAttr(action, 'dialogTitle') title ? - elem.attr('dialog-title', title) + elem.attr('dialog-title', + title instanceof Function ? + title.call(this, action, args) + : title) : !elem.attr('keep-dialog-title') && !this.getActionAttr(action, 'keepDialogTitle') && elem.attr('dialog-title', this.getDocTitle(action)) diff --git a/ui (gen4)/imagegrid/data.js b/ui (gen4)/imagegrid/data.js index 7a6e1500..018a29fd 100755 --- a/ui (gen4)/imagegrid/data.js +++ b/ui (gen4)/imagegrid/data.js @@ -2885,6 +2885,15 @@ var DataPrototype = { var DataWithTagsPrototype = { + // tags store... + // + // Format: + // { + // : [, ...], + // ... + // } + tags: null, + // XXX hate manual super calls... // ....is there a way not to say DataPrototype here??? __gid_lists: DataPrototype.__gid_lists.concat(['tags']), diff --git a/ui (gen4)/imagegrid/formats.js b/ui (gen4)/imagegrid/formats.js index 4b55f8d3..03a35038 100755 --- a/ui (gen4)/imagegrid/formats.js +++ b/ui (gen4)/imagegrid/formats.js @@ -129,35 +129,14 @@ function(data){ -/* This is best kept as a separate entity... -// XXX EXPERIMENTAL... +/* XXX template... module.VERSIONS['3.1'] = function(data){ - res = module.VERSIONS['3.0'](data) - - res.version = '3.1' - res.order_list = data.order_list != null ? JSON.parse(JSON.stringify(data.order_list)) : null - - return res -} -*/ - -/* XXX we do not have a ref to images... -module.VERSIONS['3.1'] = -function(data){ - res = module.VERSIONS['3.0'](data) + var res = data.version < '3.0' ? module.VERSIONS['3.0'](data) : data res.version = '3.1' - // XXX we do not have a ref to images here... - Object.values(res.images || {}) - .forEach(function(img){ - Object.keys(img.preview) - .forEach(function(res){ - var p = img.preview[res] - img.preview[res] = p.indexOf('%20') >= 0 ? decodeURI(p) : p - }) - }) + // XXX return res } diff --git a/ui (gen4)/lib/widget/browse.js b/ui (gen4)/lib/widget/browse.js index 9e6dbd31..5970d602 100755 --- a/ui (gen4)/lib/widget/browse.js +++ b/ui (gen4)/lib/widget/browse.js @@ -290,7 +290,7 @@ function(text, options){ // stop_propagation: 'open', // // // Called when editing is abrted... -// editaborted: , +// editaborted: , // // // Called when editing is done... // editdone: , @@ -2253,10 +2253,16 @@ var BrowserPrototype = { // ... // }, // + // // element attributes... // attrs: { // : , // ... // }, + // + // // element css style... + // style: { + // : , + // } // } // // format (optional): @@ -2658,6 +2664,8 @@ var BrowserPrototype = { opts.attrs && res.attr(opts.attrs) + opts.style + && res.css(opts.style) //--------------------------------------------- buttons --- // button container... @@ -4027,6 +4035,10 @@ var BrowserPrototype = { var dom = this.dom options = this.options + // handle close event... + options.close + && this.close(options.close) + // basic permanent interactions... dom.find('.path') // NOTE: these are used for full-path editing and are defined