blob: 35768678a6d92a24313cd723dfaa15e80b0afad3 [file] [log] [blame]
/**
* Get information on matches,
* generate annotation tables and trees.
*
* @author Nils Diewald
*/
/*
* - Highlight (at least mark as bold) the match
* - Scroll to match vertically per default
* - A click on a table field and a tree node should at the field description to the fragments list.
*/
define([
'match/info', // rename to anno
'match/treeitem',
'buttongroup',
'buttongroup/menu',
'util'
], function (infoClass,treeItemClass,buttonGroupClass,buttonGroupMenuClass) { //, refClass) {
// Localization values
const loc = KorAP.Locale;
loc.SHOWINFO = loc.SHOWINFO || 'Show information';
loc.ADDTREE = loc.ADDTREE || 'Relations';
loc.SHOWANNO = loc.SHOWANNO || 'Tokens';
loc.CLOSE = loc.CLOSE || 'Close';
loc.SHOW_META = loc.SHOW_META || 'Metadata';
// 'corpusID', 'docID', 'textID'
const _matchTerms = ['textSigle', 'matchID', 'available'];
const d = document;
/**
* Match object
*/
return {
/**
* Create a new annotation object.
* Expects an array of available foundry/layer=type terms.
* Supported types are 'spans', 'tokens' and 'rels'.
*/
create : function (match) {
return Object.create(this)._init(match);
},
/**
* Initialize match.
*/
_init : function (match) {
this._element = null;
// No match defined
if (arguments.length < 1 ||
match === null ||
match === undefined) {
throw new Error('Missing parameters');
}
// Match defined as a node
else if (match instanceof Node) {
this._element = match;
// Circular reference !!
match["_match"] = this;
/*
this.corpusID = match.getAttribute('data-corpus-id'),
this.docID = match.getAttribute('data-doc-id'),
this.textID = match.getAttribute('data-text-id'),
*/
if (match.hasAttribute('data-text-sigle')) {
this.textSigle = match.getAttribute('data-text-sigle')
}
else {
this.textSigle = match.getAttribute('data-corpus-id') +
'/' +
match.getAttribute('data-doc-id') +
'/' +
match.getAttribute('data-text-id');
};
this.matchID = match.getAttribute('data-match-id');
// List of available annotations
this.available = match.getAttribute('data-available-info').split(' ');
}
// Match as an object
else {
// Iterate over allowed match terms
for (var i in _matchTerms) {
var term = _matchTerms[i];
this[term] = match[term] !== undefined ? match[term] : undefined;
};
};
this._avail = {
tokens : [],
spans : [],
rels : []
};
// Iterate over info layers
for (var i = 0; i < this.available.length; i++) {
var term = this.available[i];
// Create info layer objects
try {
var layer = require('match/infolayer').create(term);
this._avail[layer.type].push(layer);
}
catch (e) {
continue;
};
};
return this;
},
/**
* Return a list of parseable tree annotations.
*/
getSpans : function () {
return this._avail.spans;
},
/**
* Return a list of parseable token annotations.
*/
getTokens : function () {
return this._avail.tokens;
},
/**
* Return a list of parseable relation annotations.
*/
getRels : function () {
return this._avail.rels;
},
/**
* Open match
*/
open : function () {
// Add actions unless it's already activated
var element = this._element;
// There is an element to open
if (this._element === undefined || this._element === null)
return false;
// The element is already opened
if (element.classList.contains('active'))
return false;
// Add active class to element
element.classList.add('active');
// Already there
if (element.classList.contains('action'))
return true;
// Create action buttons
var ul = d.createElement('ul');
ul.classList.add('action', 'right');
element.appendChild(ul);
element.classList.add('action');
// Todo: Open in new frame
// Add close button
var close = d.createElement('li');
close.addE('span').addT(loc.CLOSE);
close.classList.add('close');
close.setAttribute('title', loc.CLOSE);
var that = this;
// TODO:
// Introduce panel object here!
// Add meta button
var refLine = element.querySelector("p.ref");
// No reference found
if (!refLine)
return;
var btns = buttonGroupClass.create(['action', 'bottom']);
// Add meta button
btns.add(
loc.SHOW_META, ['meta'], function (e) {
that.info().showMeta();
}
);
// Add token annotation button
btns.add(
loc.SHOWANNO, ['info'], function (e) {
that.info().showTable();
}
);
// Add tree view button
btns.add(
loc.ADDTREE, ['tree'], function (e) {
if (KorAP.TreeMenu === undefined) {
KorAP.TreeMenu = buttonGroupMenuClass.create([], treeItemClass);
};
var tm = KorAP.TreeMenu;
// Reread list
tm.info(that.info());
tm.readItems(that.treeMenuList());
// Reposition and show menu
tm.show();
tm.button(this);
tm.focus();
}
);
// Insert before reference line
refLine.insertBefore(
btns.element(),
refLine.firstChild
);
// Close match
close.addEventListener('click', function (e) {
e.halt();
that.close()
});
ul.appendChild(close);
return true;
},
// Todo: Test toggle
toggle : function () {
if (this._element.classList.contains('active'))
this.close();
else
this.open();
},
/**
* Close info view
*/
close : function () {
this._element.classList.remove('active');
/*
if (this._info !== undefined) {
this._info.destroy();
};
*/
},
/**
* Get and open associated match infos.
*/
info : function () {
// TODO:
// Rename info() to panel()
// Create match info
if (this._info === undefined)
this._info = infoClass.create(this);
// There is an element to append
if (this._element === undefined ||
this._element === null)
return this._info;
// Info is already activated
if (this._info._element !== undefined)
return this._info;
var refLine = this._element.querySelector("p.ref");
this._element.insertBefore(
this._info.element(),
refLine
);
return this._info;
},
// Return tree menu list
treeMenuList : function () {
if (this._menuList)
return this._menuList;
// Join spans and relations
var treeLayers = []
var spans = this.getSpans();
var rels = this.getRels();
var i;
for (i in spans) {
treeLayers.push(spans[i]);
};
for (i in rels) {
treeLayers.push(rels[i]);
};
// Get spans
treeLayers = treeLayers.sort(
function (a, b) {
if (a.foundry < b.foundry) {
return -1;
}
else if (a.foundry > b.foundry) {
return 1;
}
else if (a.layer < b.layer) {
return -1;
}
else if (a.layer > b.layer) {
return 1;
};
return 0;
});
var menuList = [];
// Show tree views
for (var i = 0; i < treeLayers.length; i++) {
var span = treeLayers[i];
// Add foundry/layer to menu list
menuList.push([
span.foundry + '/' + span.layer,
span.foundry,
span.layer,
span.type
]);
};
// Create tree menu
this._menuList = menuList;
return menuList;
},
/**
* Get match element.
*/
element : function () {
return this._element; // May be null
}
};
});