mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-31 03:10:07 +00:00 
			
		
		
		
	refactoring...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									fead30ce3d
								
							
						
					
					
						commit
						59d82686c8
					
				| @ -6,7 +6,6 @@ | |||||||
| * 	- base | * 	- base | ||||||
| * 		map to data and images | * 		map to data and images | ||||||
| * 	- crop | * 	- crop | ||||||
| * 	- tags |  | ||||||
| * 	- groups | * 	- groups | ||||||
| * 		XXX experimental... | * 		XXX experimental... | ||||||
| * | * | ||||||
| @ -100,9 +99,7 @@ actions.Actions({ | |||||||
| 	 | 	 | ||||||
| 	// Data...
 | 	// Data...
 | ||||||
| 	get data(){  | 	get data(){  | ||||||
| 		var d = this.__data = this.__data || data.Data()  | 		return (this.__data = this.__data || data.Data()) }, | ||||||
| 		return d  |  | ||||||
| 	}, |  | ||||||
| 	set data(value){  | 	set data(value){  | ||||||
| 		this.__data = value }, | 		this.__data = value }, | ||||||
| 
 | 
 | ||||||
| @ -154,8 +151,7 @@ actions.Actions({ | |||||||
| 	get direction(){ | 	get direction(){ | ||||||
| 		return this._direction >= 0 ? 'right' | 		return this._direction >= 0 ? 'right' | ||||||
| 			: this._direction < 0 ? 'left' | 			: this._direction < 0 ? 'left' | ||||||
| 			: 'right' | 			: 'right' }, | ||||||
| 	}, |  | ||||||
| 	set direction(value){ | 	set direction(value){ | ||||||
| 		// repeat last direction...
 | 		// repeat last direction...
 | ||||||
| 		if(value == '!'){ | 		if(value == '!'){ | ||||||
| @ -473,7 +469,6 @@ actions.Actions({ | |||||||
| 			has a slightly different signature to the above, this is done | 			has a slightly different signature to the above, this is done | ||||||
| 			for simplicity... | 			for simplicity... | ||||||
| 		`,
 | 		`,
 | ||||||
| 		//function(img, list){ this.data.focusImage.apply(this.data, arguments) }],
 |  | ||||||
| 		function(img, list){ this.data.focusImage(...arguments) }], | 		function(img, list){ this.data.focusImage(...arguments) }], | ||||||
| 	// Focuses a ribbon by selecting an image in it...
 | 	// Focuses a ribbon by selecting an image in it...
 | ||||||
| 	//
 | 	//
 | ||||||
| @ -1006,45 +1001,30 @@ actions.Actions({ | |||||||
| 
 | 
 | ||||||
| 	// basic image editing...
 | 	// basic image editing...
 | ||||||
| 	//
 | 	//
 | ||||||
| 	// Rotate image...
 |  | ||||||
| 	//
 |  | ||||||
| 	//	Rotate current image clockwise...
 |  | ||||||
| 	//	.rotate()
 |  | ||||||
| 	//	.rotate('cw')
 |  | ||||||
| 	//		-> actions
 |  | ||||||
| 	//
 |  | ||||||
| 	//	Rotate current image counterclockwise...
 |  | ||||||
| 	//	.rotate('ccw')
 |  | ||||||
| 	//		-> actions
 |  | ||||||
| 	//
 |  | ||||||
| 	//	Rotate target image clockwise...
 |  | ||||||
| 	//	.rotate(target)
 |  | ||||||
| 	//	.rotate(target, 'cw')
 |  | ||||||
| 	//		-> actions
 |  | ||||||
| 	//
 |  | ||||||
| 	//	Rotate target image counterclockwise...
 |  | ||||||
| 	//	.rotate(target, 'ccw')
 |  | ||||||
| 	//		-> actions
 |  | ||||||
| 	//
 |  | ||||||
| 	//
 |  | ||||||
| 	// Flip is similar...
 |  | ||||||
| 	//
 |  | ||||||
| 	// 	Flip current image ('horizontal' is default)...
 |  | ||||||
| 	//	.flip()
 |  | ||||||
| 	//	.flip('horizontal')
 |  | ||||||
| 	//	.flip('vertical')
 |  | ||||||
| 	//		-> actions
 |  | ||||||
| 	//
 |  | ||||||
| 	//	Flip target...
 |  | ||||||
| 	//	.flip(target)
 |  | ||||||
| 	//	.flip(target, 'horizontal')
 |  | ||||||
| 	//	.flip(target, 'vertical')
 |  | ||||||
| 	//		-> actions
 |  | ||||||
| 	//
 |  | ||||||
| 	//
 |  | ||||||
| 	// NOTE: target must be .data.getImage(..) compatible, see it for docs...
 |  | ||||||
| 	// XXX correct undo???
 | 	// XXX correct undo???
 | ||||||
| 	rotate: ['- Image|Edit/Rotate image', | 	rotate: ['- Image|Edit/Rotate image', | ||||||
|  | 		core.doc`Rotate image...
 | ||||||
|  | 
 | ||||||
|  | 			Rotate current image clockwise... | ||||||
|  | 			.rotate() | ||||||
|  | 			.rotate('cw') | ||||||
|  | 				-> actions | ||||||
|  | 
 | ||||||
|  | 			Rotate current image counterclockwise... | ||||||
|  | 			.rotate('ccw') | ||||||
|  | 				-> actions | ||||||
|  | 
 | ||||||
|  | 			Rotate target image clockwise... | ||||||
|  | 			.rotate(target) | ||||||
|  | 			.rotate(target, 'cw') | ||||||
|  | 				-> actions | ||||||
|  | 
 | ||||||
|  | 			Rotate target image counterclockwise... | ||||||
|  | 			.rotate(target, 'ccw') | ||||||
|  | 				-> actions | ||||||
|  | 
 | ||||||
|  | 		NOTE: target must be .data.getImage(..) compatible, see it for docs... | ||||||
|  | 		`,
 | ||||||
| 		{journal: true}, | 		{journal: true}, | ||||||
| 		function(target, direction){ | 		function(target, direction){ | ||||||
| 			if(arguments.length == 0){ | 			if(arguments.length == 0){ | ||||||
| @ -1060,6 +1040,22 @@ actions.Actions({ | |||||||
| 				&& this.images.rotateImage(target, direction || 'cw') | 				&& this.images.rotateImage(target, direction || 'cw') | ||||||
| 		}], | 		}], | ||||||
| 	flip: ['- Image|Edit/Flip image', | 	flip: ['- Image|Edit/Flip image', | ||||||
|  | 		core.doc`Flip image...
 | ||||||
|  | 		 | ||||||
|  | 			Flip current image ('horizontal' is default)... | ||||||
|  | 			 .flip() | ||||||
|  | 			 .flip('horizontal') | ||||||
|  | 			 .flip('vertical') | ||||||
|  | 				-> actions | ||||||
|  | 			 | ||||||
|  | 			 Flip target... | ||||||
|  | 			 .flip(target) | ||||||
|  | 			 .flip(target, 'horizontal') | ||||||
|  | 			 .flip(target, 'vertical') | ||||||
|  | 				-> actions | ||||||
|  | 		 | ||||||
|  | 		NOTE: target must be .data.getImage(..) compatible, see it for docs... | ||||||
|  | 		`,
 | ||||||
| 		{journal: true}, | 		{journal: true}, | ||||||
| 		function(target, direction){ | 		function(target, direction){ | ||||||
| 			if(target == 'vertical' || target == 'horizontal'){ | 			if(target == 'vertical' || target == 'horizontal'){ | ||||||
| @ -1164,256 +1160,6 @@ core.ImageGridFeatures.Feature({ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| //---------------------------------------------------------------------
 |  | ||||||
| // Tags...
 |  | ||||||
| 
 |  | ||||||
| // mode can be:
 |  | ||||||
| // 	"ribbon"	- next marked in current ribbon (default)
 |  | ||||||
| // 	"all"		- next marked in sequence
 |  | ||||||
| //
 |  | ||||||
| // XXX add support for tag lists...
 |  | ||||||
| var makeTagWalker = |  | ||||||
| module.makeTagWalker = |  | ||||||
| function(direction, dfl_tag){ |  | ||||||
| 	var meth = direction == 'next' ? 'nextImage' : 'prevImage' |  | ||||||
| 	return function(tag, mode){ |  | ||||||
| 		this[meth](this.data.tags.values(tag || dfl_tag), mode) } } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 |  | ||||||
| 
 |  | ||||||
| var TagsActions =  |  | ||||||
| module.TagsActions = actions.Actions({ |  | ||||||
| 	prevTagged: ['- Navigate/Previous image tagged with tag', |  | ||||||
| 		makeTagWalker('prev')], |  | ||||||
| 	nextTagged: ['- Navigate/Next image tagged with tag', |  | ||||||
| 		makeTagWalker('next')], |  | ||||||
| }) |  | ||||||
| 
 |  | ||||||
| var Tags = |  | ||||||
| module.Tags = core.ImageGridFeatures.Feature({ |  | ||||||
| 	title: '', |  | ||||||
| 
 |  | ||||||
| 	tag: 'tags', |  | ||||||
| 	depends: [ |  | ||||||
| 		'base', |  | ||||||
| 	], |  | ||||||
| 	suggested: [ |  | ||||||
| 		'tags-edit', |  | ||||||
| 	], |  | ||||||
| 
 |  | ||||||
| 	actions: TagsActions, |  | ||||||
| }) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 |  | ||||||
| 
 |  | ||||||
| var TagsEditActions =  |  | ||||||
| module.TagsEditActions = actions.Actions({ |  | ||||||
| 	// tags...
 |  | ||||||
| 	//
 |  | ||||||
| 	// XXX mark updated...
 |  | ||||||
| 	tag: ['- Tag/Tag image(s)', |  | ||||||
| 		{journal: true}, |  | ||||||
| 		function(tags, gids){ |  | ||||||
| 			gids = gids || this.current |  | ||||||
| 			gids = gids instanceof Array ? gids : [gids] |  | ||||||
| 			// XXX this is slow for very large data sets...
 |  | ||||||
| 			gids = this.data.getImages(gids) |  | ||||||
| 
 |  | ||||||
| 			tags = tags instanceof Array ? tags : [tags] |  | ||||||
| 
 |  | ||||||
| 			var that = this |  | ||||||
| 
 |  | ||||||
| 			if(gids.length == 0){ |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// data...
 |  | ||||||
| 			this.data.tag(tags, gids) |  | ||||||
| 
 |  | ||||||
| 			// images...
 |  | ||||||
| 			var images = this.images |  | ||||||
| 			gids.forEach(function(gid){ |  | ||||||
| 				var img = images[gid] = images[gid] || {} |  | ||||||
| 				img.tags = img.tags || [] |  | ||||||
| 
 |  | ||||||
| 				img.tags = img.tags.concat(tags).unique() |  | ||||||
| 
 |  | ||||||
| 				// XXX mark updated...
 |  | ||||||
| 			}) |  | ||||||
| 		}], |  | ||||||
| 	// XXX mark updated...
 |  | ||||||
| 	untag: ['- Tag/Untag image(s)', |  | ||||||
| 		{journal: true}, |  | ||||||
| 		function(tags, gids){ |  | ||||||
| 			gids = gids || this.current |  | ||||||
| 			gids = gids instanceof Array ? gids : [gids] |  | ||||||
| 			tags = tags instanceof Array ? tags : [tags] |  | ||||||
| 
 |  | ||||||
| 			// data...
 |  | ||||||
| 			this.data.untag(tags, gids) |  | ||||||
| 
 |  | ||||||
| 			// images...
 |  | ||||||
| 			var images = this.images |  | ||||||
| 			gids.forEach(function(gid){ |  | ||||||
| 				var img = images[gid] |  | ||||||
| 				if(img == null || img.tags == null){ |  | ||||||
| 					return |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				img.tags = img.tags.filter(function(tag){ return tags.indexOf(tag) < 0 }) |  | ||||||
| 
 |  | ||||||
| 				if(img.tags.length == 0){ |  | ||||||
| 					delete img.tags |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				// XXX mark updated...
 |  | ||||||
| 			}) |  | ||||||
| 		}], |  | ||||||
| 	// Sync tags...
 |  | ||||||
| 	//
 |  | ||||||
| 	// 	Sync both ways...
 |  | ||||||
| 	//	.syncTags()
 |  | ||||||
| 	//	.syncTags('both')
 |  | ||||||
| 	//
 |  | ||||||
| 	//	Sync from .data
 |  | ||||||
| 	//	.syncTags('data')
 |  | ||||||
| 	//
 |  | ||||||
| 	//	Sync from .images
 |  | ||||||
| 	//	.syncTags('images')
 |  | ||||||
| 	//
 |  | ||||||
| 	//	Sync from <images> object
 |  | ||||||
| 	//	.syncTags(<images>)
 |  | ||||||
| 	//
 |  | ||||||
| 	// NOTE: mode is data.tagsToImages(..) / data.tagsFromImages(..) 
 |  | ||||||
| 	// 		compatible...
 |  | ||||||
| 	// 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/-10:Synchoronize tags between data and images', |  | ||||||
| 		{journal: true}, |  | ||||||
| 		function(source, mode){ |  | ||||||
| 			// can't do anything if either .data or .images are not 
 |  | ||||||
| 			// defined...
 |  | ||||||
| 			if(this.images == null){ |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			source = source || 'both' |  | ||||||
| 			mode = mode || 'merge' |  | ||||||
| 
 |  | ||||||
| 			var images = this.images |  | ||||||
| 
 |  | ||||||
| 			if(typeof(source) != typeof('str')){ |  | ||||||
| 				images = source |  | ||||||
| 				source = 'images' |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if(source == 'data' || source == 'both'){ |  | ||||||
| 				this.data.tagsToImages(images, mode) |  | ||||||
| 			} |  | ||||||
| 			if(source == 'images' || source == 'both'){ |  | ||||||
| 				this.data.tagsFromImages(images, mode) |  | ||||||
| 			} |  | ||||||
| 		}], |  | ||||||
| 	 |  | ||||||
| }) |  | ||||||
| 
 |  | ||||||
| var TagsEdit = |  | ||||||
| module.TagsEdit = core.ImageGridFeatures.Feature({ |  | ||||||
| 	title: '', |  | ||||||
| 
 |  | ||||||
| 	tag: 'tags-edit', |  | ||||||
| 	depends: [ |  | ||||||
| 		'tags', |  | ||||||
| 		'edit', |  | ||||||
| 	], |  | ||||||
| 
 |  | ||||||
| 	actions: TagsEditActions, |  | ||||||
| 
 |  | ||||||
| 	handlers: [ |  | ||||||
| 		// tags and images...
 |  | ||||||
| 		// NOTE: tags are also stored in images...
 |  | ||||||
| 		['tag untag', |  | ||||||
| 			function(_, tags, gids){ |  | ||||||
| 				var that = this |  | ||||||
| 				var changes = [] |  | ||||||
| 
 |  | ||||||
| 				gids = gids || this.current |  | ||||||
| 				gids = gids instanceof Array ? gids : [gids] |  | ||||||
| 				gids = this.data.getImages(gids) |  | ||||||
| 
 |  | ||||||
| 				tags = tags || [] |  | ||||||
| 				tags = tags instanceof Array ? tags : [tags] |  | ||||||
| 
 |  | ||||||
| 				// tags...
 |  | ||||||
| 				if(tags.length > 0){ |  | ||||||
| 					this.markChanged('tags') |  | ||||||
| 
 |  | ||||||
| 					tags.indexOf('marked') >= 0 |  | ||||||
| 						&& this.markChanged('marked') |  | ||||||
| 
 |  | ||||||
| 					tags.indexOf('bookmark') >= 0 |  | ||||||
| 						&& this.markChanged('bookmarked') |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				this.markChanged('images', gids) |  | ||||||
| 			}], |  | ||||||
| 
 |  | ||||||
| 		// store .tags and .tags.marked / .tags.bookmark separately from .data...
 |  | ||||||
| 		//
 |  | ||||||
| 		// XXX see if this can be automated...
 |  | ||||||
| 		['prepareIndexForWrite',  |  | ||||||
| 			function(res){ |  | ||||||
| 				var changes = res.changes |  | ||||||
| 
 |  | ||||||
| 				if(!changes || !res.raw.data){ |  | ||||||
| 					return |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				if((changes === true || changes.tags) && res.raw.data.tags){ |  | ||||||
| 					res.index.tags = res.raw.data.tags |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				// XXX should we save an empty list *iff* changes.marked is true???
 |  | ||||||
| 				if(changes === true || changes.marked){ |  | ||||||
| 					res.index.marked =  |  | ||||||
| 						(res.raw.data.tags.tags || {}).marked || [] |  | ||||||
| 				} |  | ||||||
| 				// XXX should we save an empty list *iff* changes.bookmarked is true???
 |  | ||||||
| 				if(changes === true || changes.bookmarked){ |  | ||||||
| 					res.index.bookmarked = [ |  | ||||||
| 						(res.raw.data.tags.tags || {}).bookmark || [], |  | ||||||
| 						{}, |  | ||||||
| 					] |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				// cleanup...
 |  | ||||||
| 				if(res.index.data && res.index.data.tags){ |  | ||||||
| 					delete res.index.data.tags.tags.marked |  | ||||||
| 					delete res.index.data.tags.tags.bookmark |  | ||||||
| 					delete res.index.data.tags |  | ||||||
| 				} |  | ||||||
| 			}], |  | ||||||
| 		// merge the tags into data...
 |  | ||||||
| 		['prepareIndexForLoad.pre', |  | ||||||
| 			function(json){ |  | ||||||
| 				// NOTE: this is done before we build the data to let 
 |  | ||||||
| 				// 		Data handle format conversion...
 |  | ||||||
| 				json.data.tags = json.tags || {} |  | ||||||
| 			}], |  | ||||||
| 		// merge in marked and bookmark tags...
 |  | ||||||
| 		['prepareIndexForLoad', |  | ||||||
| 			function(res, json){ |  | ||||||
| 				res.data.tag('marked', json.marked || []) |  | ||||||
| 				res.data.tag('bookmark', json.bookmarked ? json.bookmarked[0] : []) |  | ||||||
| 			}], |  | ||||||
| 	], |  | ||||||
| }) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| //---------------------------------------------------------------------
 | //---------------------------------------------------------------------
 | ||||||
| // Image Group...
 | // Image Group...
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -18,10 +18,262 @@ var browse = require('lib/widget/browse') | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /*********************************************************************/ | /*********************************************************************/ | ||||||
|  | // Tags...
 | ||||||
|  | 
 | ||||||
|  | // mode can be:
 | ||||||
|  | // 	"ribbon"	- next marked in current ribbon (default)
 | ||||||
|  | // 	"all"		- next marked in sequence
 | ||||||
|  | //
 | ||||||
|  | // XXX add support for tag lists...
 | ||||||
|  | var makeTagWalker = | ||||||
|  | module.makeTagWalker = | ||||||
|  | function(direction, dfl_tag){ | ||||||
|  | 	var meth = direction == 'next' ? 'nextImage' : 'prevImage' | ||||||
|  | 	return function(tag, mode){ | ||||||
|  | 		this[meth](this.data.tags.values(tag || dfl_tag), mode) } } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  | var TagsActions =  | ||||||
|  | module.TagsActions = actions.Actions({ | ||||||
|  | 	// Navigation...
 | ||||||
|  | 	//
 | ||||||
|  | 	prevTagged: ['- Navigate/Previous image tagged with tag', | ||||||
|  | 		makeTagWalker('prev')], | ||||||
|  | 	nextTagged: ['- Navigate/Next image tagged with tag', | ||||||
|  | 		makeTagWalker('next')], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | var Tags = | ||||||
|  | module.Tags = core.ImageGridFeatures.Feature({ | ||||||
|  | 	title: '', | ||||||
|  | 
 | ||||||
|  | 	tag: 'tags', | ||||||
|  | 	depends: [ | ||||||
|  | 		'base', | ||||||
|  | 	], | ||||||
|  | 	suggested: [ | ||||||
|  | 		'tags-edit', | ||||||
|  | 	], | ||||||
|  | 
 | ||||||
|  | 	actions: TagsActions, | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  | var TagsEditActions =  | ||||||
|  | module.TagsEditActions = actions.Actions({ | ||||||
|  | 	// tags...
 | ||||||
|  | 	//
 | ||||||
|  | 	// XXX mark updated...
 | ||||||
|  | 	tag: ['- Tag/Tag image(s)', | ||||||
|  | 		{journal: true}, | ||||||
|  | 		function(tags, gids){ | ||||||
|  | 			gids = gids || this.current | ||||||
|  | 			gids = gids instanceof Array ? gids : [gids] | ||||||
|  | 			// XXX this is slow for very large data sets...
 | ||||||
|  | 			gids = this.data.getImages(gids) | ||||||
|  | 
 | ||||||
|  | 			tags = tags instanceof Array ? tags : [tags] | ||||||
|  | 
 | ||||||
|  | 			var that = this | ||||||
|  | 
 | ||||||
|  | 			if(gids.length == 0){ | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// data...
 | ||||||
|  | 			this.data.tag(tags, gids) | ||||||
|  | 
 | ||||||
|  | 			// images...
 | ||||||
|  | 			var images = this.images | ||||||
|  | 			gids.forEach(function(gid){ | ||||||
|  | 				var img = images[gid] = images[gid] || {} | ||||||
|  | 				img.tags = img.tags || [] | ||||||
|  | 
 | ||||||
|  | 				img.tags = img.tags.concat(tags).unique() | ||||||
|  | 
 | ||||||
|  | 				// XXX mark updated...
 | ||||||
|  | 			}) | ||||||
|  | 		}], | ||||||
|  | 	// XXX mark updated...
 | ||||||
|  | 	untag: ['- Tag/Untag image(s)', | ||||||
|  | 		{journal: true}, | ||||||
|  | 		function(tags, gids){ | ||||||
|  | 			gids = gids || this.current | ||||||
|  | 			gids = gids instanceof Array ? gids : [gids] | ||||||
|  | 			tags = tags instanceof Array ? tags : [tags] | ||||||
|  | 
 | ||||||
|  | 			// data...
 | ||||||
|  | 			this.data.untag(tags, gids) | ||||||
|  | 
 | ||||||
|  | 			// images...
 | ||||||
|  | 			var images = this.images | ||||||
|  | 			gids.forEach(function(gid){ | ||||||
|  | 				var img = images[gid] | ||||||
|  | 				if(img == null || img.tags == null){ | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				img.tags = img.tags.filter(function(tag){ return tags.indexOf(tag) < 0 }) | ||||||
|  | 
 | ||||||
|  | 				if(img.tags.length == 0){ | ||||||
|  | 					delete img.tags | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				// XXX mark updated...
 | ||||||
|  | 			}) | ||||||
|  | 		}], | ||||||
|  | 	// Sync tags...
 | ||||||
|  | 	//
 | ||||||
|  | 	// 	Sync both ways...
 | ||||||
|  | 	//	.syncTags()
 | ||||||
|  | 	//	.syncTags('both')
 | ||||||
|  | 	//
 | ||||||
|  | 	//	Sync from .data
 | ||||||
|  | 	//	.syncTags('data')
 | ||||||
|  | 	//
 | ||||||
|  | 	//	Sync from .images
 | ||||||
|  | 	//	.syncTags('images')
 | ||||||
|  | 	//
 | ||||||
|  | 	//	Sync from <images> object
 | ||||||
|  | 	//	.syncTags(<images>)
 | ||||||
|  | 	//
 | ||||||
|  | 	// NOTE: mode is data.tagsToImages(..) / data.tagsFromImages(..) 
 | ||||||
|  | 	// 		compatible...
 | ||||||
|  | 	// 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/-10:Synchoronize tags between data and images', | ||||||
|  | 		{journal: true}, | ||||||
|  | 		function(source, mode){ | ||||||
|  | 			// can't do anything if either .data or .images are not 
 | ||||||
|  | 			// defined...
 | ||||||
|  | 			if(this.images == null){ | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			source = source || 'both' | ||||||
|  | 			mode = mode || 'merge' | ||||||
|  | 
 | ||||||
|  | 			var images = this.images | ||||||
|  | 
 | ||||||
|  | 			if(typeof(source) != typeof('str')){ | ||||||
|  | 				images = source | ||||||
|  | 				source = 'images' | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if(source == 'data' || source == 'both'){ | ||||||
|  | 				this.data.tagsToImages(images, mode) | ||||||
|  | 			} | ||||||
|  | 			if(source == 'images' || source == 'both'){ | ||||||
|  | 				this.data.tagsFromImages(images, mode) | ||||||
|  | 			} | ||||||
|  | 		}], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | var TagsEdit = | ||||||
|  | module.TagsEdit = core.ImageGridFeatures.Feature({ | ||||||
|  | 	title: '', | ||||||
|  | 
 | ||||||
|  | 	tag: 'tags-edit', | ||||||
|  | 	depends: [ | ||||||
|  | 		'tags', | ||||||
|  | 		'edit', | ||||||
|  | 	], | ||||||
|  | 
 | ||||||
|  | 	actions: TagsEditActions, | ||||||
|  | 
 | ||||||
|  | 	handlers: [ | ||||||
|  | 		// tags and images...
 | ||||||
|  | 		// NOTE: tags are also stored in images...
 | ||||||
|  | 		['tag untag', | ||||||
|  | 			function(_, tags, gids){ | ||||||
|  | 				var that = this | ||||||
|  | 				var changes = [] | ||||||
|  | 
 | ||||||
|  | 				gids = gids || this.current | ||||||
|  | 				gids = gids instanceof Array ? gids : [gids] | ||||||
|  | 				gids = this.data.getImages(gids) | ||||||
|  | 
 | ||||||
|  | 				tags = tags || [] | ||||||
|  | 				tags = tags instanceof Array ? tags : [tags] | ||||||
|  | 
 | ||||||
|  | 				// tags...
 | ||||||
|  | 				if(tags.length > 0){ | ||||||
|  | 					this.markChanged('tags') | ||||||
|  | 
 | ||||||
|  | 					tags.indexOf('marked') >= 0 | ||||||
|  | 						&& this.markChanged('marked') | ||||||
|  | 
 | ||||||
|  | 					tags.indexOf('bookmark') >= 0 | ||||||
|  | 						&& this.markChanged('bookmarked') | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				this.markChanged('images', gids) | ||||||
|  | 			}], | ||||||
|  | 
 | ||||||
|  | 		// store .tags and .tags.marked / .tags.bookmark separately from .data...
 | ||||||
|  | 		//
 | ||||||
|  | 		// XXX see if this can be automated...
 | ||||||
|  | 		['prepareIndexForWrite',  | ||||||
|  | 			function(res){ | ||||||
|  | 				var changes = res.changes | ||||||
|  | 
 | ||||||
|  | 				if(!changes || !res.raw.data){ | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				if((changes === true || changes.tags) && res.raw.data.tags){ | ||||||
|  | 					res.index.tags = res.raw.data.tags | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				// XXX should we save an empty list *iff* changes.marked is true???
 | ||||||
|  | 				if(changes === true || changes.marked){ | ||||||
|  | 					res.index.marked =  | ||||||
|  | 						(res.raw.data.tags.tags || {}).marked || [] | ||||||
|  | 				} | ||||||
|  | 				// XXX should we save an empty list *iff* changes.bookmarked is true???
 | ||||||
|  | 				if(changes === true || changes.bookmarked){ | ||||||
|  | 					res.index.bookmarked = [ | ||||||
|  | 						(res.raw.data.tags.tags || {}).bookmark || [], | ||||||
|  | 						{}, | ||||||
|  | 					] | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				// cleanup...
 | ||||||
|  | 				if(res.index.data && res.index.data.tags){ | ||||||
|  | 					delete res.index.data.tags.tags.marked | ||||||
|  | 					delete res.index.data.tags.tags.bookmark | ||||||
|  | 					delete res.index.data.tags | ||||||
|  | 				} | ||||||
|  | 			}], | ||||||
|  | 		// merge the tags into data...
 | ||||||
|  | 		['prepareIndexForLoad.pre', | ||||||
|  | 			function(json){ | ||||||
|  | 				// NOTE: this is done before we build the data to let 
 | ||||||
|  | 				// 		Data handle format conversion...
 | ||||||
|  | 				json.data.tags = json.tags || {} | ||||||
|  | 			}], | ||||||
|  | 		// merge in marked and bookmark tags...
 | ||||||
|  | 		['prepareIndexForLoad', | ||||||
|  | 			function(res, json){ | ||||||
|  | 				res.data.tag('marked', json.marked || []) | ||||||
|  | 				res.data.tag('bookmark', json.bookmarked ? json.bookmarked[0] : []) | ||||||
|  | 			}], | ||||||
|  | 	], | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
| // Persistent tags (tree) 
 | // Persistent tags (tree) 
 | ||||||
| //
 | //
 | ||||||
| // XXX add save/load tree to fs...
 | // XXX add save/load tree to fs...
 | ||||||
| 
 | // XXX
 | ||||||
| var PersistentTagsActions = actions.Actions({ | var PersistentTagsActions = actions.Actions({ | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| @ -43,7 +295,7 @@ module.PersistentTags = core.ImageGridFeatures.Feature({ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| //---------------------------------------------------------------------
 | //---------------------------------------------------------------------
 | ||||||
| // Persistent tags UI...
 | // Tags UI...
 | ||||||
| //
 | //
 | ||||||
| // Provide the following interfaces:
 | // Provide the following interfaces:
 | ||||||
| // 	- cloud
 | // 	- cloud
 | ||||||
| @ -53,7 +305,6 @@ module.PersistentTags = core.ImageGridFeatures.Feature({ | |||||||
| // 	- edit tag tree
 | // 	- edit tag tree
 | ||||||
| // 	- edit image tags
 | // 	- edit image tags
 | ||||||
| //
 | //
 | ||||||
| 
 |  | ||||||
| var TagUIActions = actions.Actions({ | var TagUIActions = actions.Actions({ | ||||||
| 	config: { | 	config: { | ||||||
| 		// XXX should this be a list or a tree (list of paths)????
 | 		// XXX should this be a list or a tree (list of paths)????
 | ||||||
|  | |||||||
| @ -772,6 +772,10 @@ var DialogsActions = actions.Actions({ | |||||||
| 					//fullPathEdit: true,
 | 					//fullPathEdit: true,
 | ||||||
| 					//*/
 | 					//*/
 | ||||||
| 				}, options || {})) })], | 				}, options || {})) })], | ||||||
|  | 	// XXX
 | ||||||
|  | 	showCloud: ['- Interface/', | ||||||
|  | 		makeUIDialog(function(list, options){ | ||||||
|  | 			throw new Error('.showCloud(..): not implemented.') })], | ||||||
| 
 | 
 | ||||||
| 	// XXX do we need to split the options???
 | 	// XXX do we need to split the options???
 | ||||||
| 	showEditableList: ['- Interface/',  | 	showEditableList: ['- Interface/',  | ||||||
|  | |||||||
| @ -922,12 +922,13 @@ var TagsPrototype = { | |||||||
| 	// NOTE: if any renamed tag is renamed to '' it will be removed 
 | 	// NOTE: if any renamed tag is renamed to '' it will be removed 
 | ||||||
| 	// 		untagging all relevant values...
 | 	// 		untagging all relevant values...
 | ||||||
| 	//
 | 	//
 | ||||||
| 	// XXX need to sanitize from -- it can not contain regex characters...
 | 	// XXX need to sanitize tag -- it can not contain regex characters...
 | ||||||
| 	// 		...should we guard against this???
 | 	// 		...should we guard against this???
 | ||||||
| 	// XXX should both sides of the alias be renamed???
 | 	// XXX should both sides of the alias be renamed???
 | ||||||
| 	rename: function(tag, to, ...tags){ | 	rename: function(tag, to, ...tags){ | ||||||
| 		var that = this | 		var that = this | ||||||
| 
 | 
 | ||||||
|  | 		// XXX should we bo more pedantic here???
 | ||||||
| 		tag = this.normalize(tag) | 		tag = this.normalize(tag) | ||||||
| 		if(tag == ''){ | 		if(tag == ''){ | ||||||
| 			throw new Error(`.rename(..): first argument can not be an empty string.`) } | 			throw new Error(`.rename(..): first argument can not be an empty string.`) } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user