updated object.js + refactored tags and tag dict...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2018-12-24 21:50:37 +03:00
parent baec933d89
commit e4a11221e9
6 changed files with 101 additions and 43 deletions

View File

@ -858,7 +858,6 @@ var BaseTagsPrototype = {
// Edit API... // Edit API...
// //
// XXX save un-normalized tags to dict... ??? (a-la flickr)
tag: function(tags, value){ tag: function(tags, value){
var that = this var that = this
value = value instanceof Array ? value : [value] value = value instanceof Array ? value : [value]
@ -1117,7 +1116,7 @@ var BaseTagsPrototype = {
patchObj(this.__index || {}) patchObj(this.__index || {})
patchObj(this.definitions || {}, true) patchObj(this.definitions || {}, true)
} }
return this return this
}, },
@ -1312,6 +1311,8 @@ var BaseTagsPrototype = {
var index = this.__index || {} var index = this.__index || {}
normalizeSplit(others) normalizeSplit(others)
.forEach(function(other){ .forEach(function(other){
other.dict
&& (that.dict = Object.assign(that.dict || {}, other.dict))
Object.entries(other.__index || {}) Object.entries(other.__index || {})
.forEach(function(e){ .forEach(function(e){
index[e[0]] = new Set([...(index[e[0]] || []), ...e[1]]) }) }) index[e[0]] = new Set([...(index[e[0]] || []), ...e[1]]) }) })
@ -1681,11 +1682,10 @@ object.makeConstructor('BaseTags',
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// XXX EXPERIMENTAL... // XXX EXPERIMENTAL...
// ...this is a bit too generic, we need to save dict values only // XXX need a .dict cleanup strategy...
// when tagging or adding tags...
// ...also need to clear the dict when untagging...
var TagsWithDictPrototype = { var TagsWithDictPrototype = {
__proto__: BaseTags, __proto__: BaseTagsPrototype,
// Tag dictionary... // Tag dictionary...
// //
@ -1697,17 +1697,22 @@ var TagsWithDictPrototype = {
// //
dict: null, dict: null,
// XXX need to only do this when adding new tags...
// ...rename to .normalizeSave(..) and use in .tag(..), .toggle(..), ... // Normalize tags and save their dict values...
normalize: function(...tags){ //
var dict = this.dict = this.dict || {} // NOTE: this is signature-compatible with .normalize(..) with the
var res = TagsWithDict.__proto__.normalize.call(this, ...tags) // side-effect of saving non-normalized values to .dict
//
normalizeSave: function(...tags){
var sp = this.COMBINED_SEPARATOR var sp = this.COMBINED_SEPARATOR
var dict = this.dict = this.dict || {}
var res = this.normalize(...tags)
tags = normalizeSplit(tags) tags = normalizeSplit(tags)
.map(function(tag){ .map(function(tag){
return tag.split(sp) }) return tag.split(sp) })
.flat() .flat()
;(res instanceof Array ? res : [res]) ;(res instanceof Array ? res : [res])
.map(function(tag){ .map(function(tag){
return tag.split(sp) }) return tag.split(sp) })
@ -1717,12 +1722,23 @@ var TagsWithDictPrototype = {
var value = tags[i].trim() var value = tags[i].trim()
// only add tags if they are not the same as normalized... // only add tags if they are not the same as normalized...
tag != value tag != value
&& (dict[tag] = [value] // NOTE: we keep the first value added as main...
.concat(dict[tag] || []) && (dict[tag] = (dict[tag] || [])
.concat([value])
.unique()) }) .unique()) })
return res return res
}, },
// Translate normalized tag to the dict form...
//
// .translateTag(tag)
// -> str
//
// .translateTag(tag, ..)
// .translateTag([tag, ..])
// -> [str, ..]
//
translateTag: function(...tags){ translateTag: function(...tags){
var that = this var that = this
var dict = this.dict var dict = this.dict
@ -1745,6 +1761,58 @@ var TagsWithDictPrototype = {
return arguments.length == 1 && typeof(arguments[0]) == typeof('str') ? return arguments.length == 1 && typeof(arguments[0]) == typeof('str') ?
res[0] res[0]
: res }, : res },
// XXX batch remove???
// XXX
// Remove orphaned .dict values...
//
// NOTE: an orphan is a dict entry for a tag that is no longer used.
cleanupDict: function(){
// XXX is this the full list???
var sp = this.COMBINED_SEPARATOR
var tags = new Set(this.singleTags()
.concat(this.definitionPaths()
.map(function(p){
return p.split(sp) })
.flat()))
var dict = this.dict
dict
&& Object.keys(dict)
.filter(function(tag){
return !tags.has(tag) })
.forEach(function(tag){
delete dict[tag] })
return this
},
// Hooks...
tag: function(tags, value){
this.normalizeSave(tags)
return object.parent(TagsWithDictPrototype.tag, this).call(this, ...arguments) },
// XXX cleanup .dict...
untag: function(tags, value){
// XXX cleanup .dict...
return object.parent(TagsWithDictPrototype.untag, this).call(this, ...arguments) },
// XXX cleanup .dict...
rename: function(from, to, ...tags){
arguments.length == 2
&& this.normalizeSave(to)
// XXX cleanup dict...
return object.parent(TagsWithDictPrototype.rename, this).call(this, ...arguments) },
// XXX cleanup .dict...
togglePersistent: function(...tags){
// XXX remove action...
this.normalizeSave(tags)
// XXX cleanup dict...
return object.parent(TagsWithDictPrototype.togglePersistent, this).call(this, ...arguments) },
// XXX cleanup .dict...
define: function(tag, value){
arguments.length > 1
&& value != null
&& this.normalizeSave(tag, value)
return object.parent(TagsWithDictPrototype.define, this).call(this, ...arguments) },
} }
@ -1868,16 +1936,16 @@ var TagsWithHandlersPrototype = {
// //
tag: function(tags, value){ tag: function(tags, value){
var that = this var that = this
return TagsWithHandlersPrototype.__proto__.tag.call(this, return object.parent(TagsWithHandlersPrototype.tag, this).call(this,
that.handleSpecialTag(tags, 'tag', value), that.handleSpecialTag(tags, 'tag', value),
...[...arguments].slice(1)) }, ...[...arguments].slice(1)) },
untag: function(tags, value){ untag: function(tags, value){
var that = this var that = this
return TagsWithHandlersPrototype.__proto__.untag.call(this, return object.parent(TagsWithHandlersPrototype.untag, this).call(this,
that.handleSpecialTag(tags, 'untag', value), that.handleSpecialTag(tags, 'untag', value),
...[...arguments].slice(1)) }, ...[...arguments].slice(1)) },
rename: function(tag, to, ...tags){ rename: function(tag, to, ...tags){
return TagsWithHandlersPrototype.__proto__.rename.call(this, return object.parent(TagsWithHandlersPrototype.rename, this).call(this,
tags.length == 0 ? tags.length == 0 ?
this.handleSpecialTag(tag, to == '' ? 'remove' : 'rename', to) this.handleSpecialTag(tag, to == '' ? 'remove' : 'rename', to)
: tag, : tag,
@ -1903,19 +1971,9 @@ module.Tags =
//BaseTags //BaseTags
object.makeConstructor('Tags', object.makeConstructor('Tags',
BaseTagsClassPrototype, BaseTagsClassPrototype,
// XXX HACK??? object.mixin(BaseTagsPrototype,
// ...this is not a good way to do multiple inheritance/mixins...
Object.assign(
// XXX these must not intersect...
// ...intersecting methods will overwrite each other...
// ...another problem with this approach is that the mixin
// methods explicitly call the base method of the prototype
// which might not be the correct method in the inheritance
// tree (of two or more of the mixins define the same
// method only one definition will get called)...
{__proto__: BaseTagsPrototype},
TagsWithDictPrototype, TagsWithDictPrototype,
TagsWithHandlersPrototype)) TagsWithHandlers))

View File

@ -1115,7 +1115,7 @@ var KeyboardWithCSSModesPrototype = {
}, },
__init__: function(keyboard, context){ __init__: function(keyboard, context){
object.superMethod(KeyboardWithCSSModes, '__init__').call(this, keyboard) object.parent(KeyboardWithCSSModesPrototype.__init__, this).call(this, keyboard)
if(context instanceof Function){ if(context instanceof Function){
Object.defineProperty(this, 'context', { Object.defineProperty(this, 'context', {

View File

@ -1880,7 +1880,7 @@ var BrowserPrototype = {
// no items selected -- trigger event on main ui... // no items selected -- trigger event on main ui...
} else { } else {
object.superMethod(Browser, 'trigger').apply(this, arguments) object.parent(BrowserPrototype.trigger, this).apply(this, arguments)
} }
return this return this
@ -4030,7 +4030,7 @@ var BrowserPrototype = {
__init__: function(parent, options){ __init__: function(parent, options){
var that = this var that = this
object.superMethod(Browser, '__init__').call(this, parent, options) object.parent(BrowserPrototype.__init__, this).call(this, parent, options)
var dom = this.dom var dom = this.dom
options = this.options options = this.options

View File

@ -78,7 +78,7 @@ var OverlayPrototype = {
__init__: function(parent, client, options){ __init__: function(parent, client, options){
var that = this var that = this
object.superMethod(Overlay, '__init__').call(this, parent, client, options) object.parent(OverlayPrototype.__init__, this).call(this, parent, client, options)
// Prevent closing the overlay if clicked while blurred... // Prevent closing the overlay if clicked while blurred...
// i.e. // i.e.

View File

@ -345,7 +345,7 @@
}, },
"es6-promisify": { "es6-promisify": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
"integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
"dev": true, "dev": true,
"requires": { "requires": {
@ -1172,9 +1172,9 @@
} }
}, },
"ig-object": { "ig-object": {
"version": "1.0.7", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/ig-object/-/ig-object-1.0.7.tgz", "resolved": "https://registry.npmjs.org/ig-object/-/ig-object-1.2.0.tgz",
"integrity": "sha512-bBlxP0AE9oxjUEtIzgZN302nuUAYycAOeh2F2D/z3OSl4zUc+R0Cb9HMpwOO4gZfc6I4ZV9tr/Ax1lk4KkW/aQ==" "integrity": "sha512-+66y36wvev5bdn4bpsK6i6sbePUQ/eLMu+GJ3/lLzGzQSsNWAelOIllKsYpQSObllna3Sl8C2/57I1x/zjm2nQ=="
}, },
"image-size": { "image-size": {
"version": "0.5.5", "version": "0.5.5",
@ -1417,9 +1417,9 @@
} }
}, },
"moment": { "moment": {
"version": "2.22.2", "version": "2.23.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", "resolved": "https://registry.npmjs.org/moment/-/moment-2.23.0.tgz",
"integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=" "integrity": "sha512-3IE39bHVqFbWWaPOMHZF98Q9c3LDKGTmypMiTM2QygGXXElkFWIH7GxfmlwmY2vwa+wmNsoYZmG2iusf1ZjJoA=="
}, },
"ms": { "ms": {
"version": "2.0.0", "version": "2.0.0",
@ -1656,7 +1656,7 @@
}, },
"readable-stream": { "readable-stream": {
"version": "2.3.6", "version": "2.3.6",
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"dev": true, "dev": true,
"requires": { "requires": {
@ -1816,7 +1816,7 @@
}, },
"string_decoder": { "string_decoder": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true, "dev": true,
"requires": { "requires": {

View File

@ -28,8 +28,8 @@
"guarantee-events": "^1.0.0", "guarantee-events": "^1.0.0",
"ig-actions": "^3.22.0", "ig-actions": "^3.22.0",
"ig-features": "^3.3.4", "ig-features": "^3.3.4",
"ig-object": "^1.0.7", "ig-object": "^1.2.0",
"moment": "^2.22.2", "moment": "^2.23.0",
"openseadragon": "^2.4.0", "openseadragon": "^2.4.0",
"requirejs": "^2.3.6", "requirejs": "^2.3.6",
"requirejs-plugins": "^1.0.2", "requirejs-plugins": "^1.0.2",