UNPKG

solid-panes

Version:

Solid-compatible Panes: applets and views for the mashlib and databrowser

1,359 lines (1,290 loc) 85.9 kB
/* istanbul ignore file */ // Original author: kennyluck // // Kenny's Notes: /* places to generate SPARQL update: clearInputAndSave() pasteFromClipboard()->insertTermTo(); undetermined statement generated formUndetStat() ->fillInRequest() ontological issues temporarily using the tabont namespace clipboard: 'predicates' 'objects' 'all'(internal) request: 'from' 'to' 'message' 'Request' */ import * as UI from 'solid-ui' import { store } from 'solid-logic' import * as panes from 'pane-registry' const $rdf = UI.rdf let UserInputFormula // Formula to store references of user's work let TempFormula // Formula to store incomplete triples (Requests), // temporarily disjoint with kb to avoid bugs export function UserInput (outline) { const myDocument = outline.document // is this ok? // UI.log.warn("myDocument when it's set is "+myDocument.location); this.menuId = 'predicateMenu1' /* //namespace information, as a subgraph of the knowledge base, is built in showMenu this.namespaces={}; for (var name in UI.ns) { this.namespaces[name] = UI.ns[name]('').uri; } var NameSpaces=this.namespaces; */ // hq, print and trim functions const qp = function qp (str) { console.log(str + '\n') } // var tabont = UI.ns.tabont; // var foaf = UI.ns.foaf const rdf = UI.ns.rdf // var RDFS = UI.ns.rdfs // var OWL = UI.ns.owl // var dc = UI.ns.dc // var rss = UI.ns.rss // var contact = UI.ns.contact // var mo = UI.ns.mo const bibo = UI.rdf.Namespace('http://purl.org/ontology/bibo/') // hql for pubsPane // var dcterms = UI.rdf.Namespace('http://purl.org/dc/terms/') const dcelems = UI.rdf.Namespace('http://purl.org/dc/elements/1.1/') let movedArrow = false // hq // var updateService=new updateCenter(kb); if (!UserInputFormula) { UserInputFormula = new UI.rdf.Formula() UserInputFormula.superFormula = store // UserInputFormula.registerFormula("Your Work"); } if (!TempFormula) TempFormula = new UI.rdf.IndexedFormula() // Use RDFIndexedFormula so add returns the statement TempFormula.name = 'TempFormula' if (!store.updater) store.updater = new UI.rdf.UpdateManager(store) return { // updateService: updateService, sparqler: store.updater, lastModified: null, // the last <input> being modified, .isNew indicates whether it's a new input lastModifiedStat: null, // the last statement being modified statIsInverse: false, // whether the statement is an inverse /** * Triggering Events: event entry points, should be called only from outline.js but not anywhere else * in userinput.js, should be as short as possible, function names to be discussed */ // Called when the blue cross under the default pane is clicked. // Add a new row to a property list ( P and O) addNewPredicateObject: function addNewPredicateObject (e) { if (UI.utils.getTarget(e).className !== 'bottom-border-active') return const This = outline.UserInput const target = UI.utils.getTarget(e) // UI.log.warn(ancestor(target,'TABLE').textContent); const insertTr = myDocument.createElement('tr') UI.utils .ancestor(target, 'DIV') .insertBefore(insertTr, UI.utils.ancestor(target, 'TR')) const tempTr = myDocument.createElement('tr') const reqTerm1 = This.generateRequest('(TBD)', tempTr, true) insertTr.appendChild(tempTr.firstChild) const reqTerm2 = This.generateRequest( '(Enter text or drag an object onto this field)', tempTr, false ) insertTr.appendChild(tempTr.firstChild) // there should be an elegant way of doing this // Take the why of the last TR and write to it. if ( UI.utils.ancestor(target, 'TR').previousSibling && // there is a previous predicate/object line UI.utils.ancestor(target, 'TR').previousSibling.AJAR_statement ) { const preStat = UI.utils.ancestor(target, 'TR').previousSibling .AJAR_statement // This should always(?) input a non-inverse statement This.formUndetStat( insertTr, preStat.subject, reqTerm1, reqTerm2, preStat.why, false ) } else { // no previous row: write to the document defining the subject const subject = UI.utils.getAbout( store, UI.utils.ancestor(target.parentNode.parentNode, 'TD') ) const doc = store.sym(UI.rdf.Util.uri.docpart(subject.uri)) This.formUndetStat(insertTr, subject, reqTerm1, reqTerm2, doc, false) } outline.walk('moveTo', insertTr.firstChild) UI.log.info( 'addNewPredicateObject: selection = ' + outline .getSelection() .map(function (item) { return item.textContent }) .join(', ') ) this.startFillInText(outline.getSelection()[0]) }, // Called when a blue cross on a predicate is clicked // tr.AJAR_inverse stores whether the clicked predicate is an inverse one // tr.AJAR_statement (an incomplete statement in TempFormula) stores the destination(why), now // determined by the preceding one (is this good?) addNewObject: function addNewObject (e) { const predicateTd = UI.utils.getTarget(e).parentNode.parentNode // var predicateTerm = UI.utils.getAbout(kb, predicateTd) const isInverse = predicateTd.parentNode.AJAR_inverse // var titleTerm=UI.utils.getAbout(kb,UI.utils.ancestor(predicateTd.parentNode,'TD')); // set pseudo lastModifiedStat here this.lastModifiedStat = predicateTd.parentNode.AJAR_statement const insertTr = this.appendToPredicate(predicateTd) const reqTerm = this.generateRequest(' (Error) ', insertTr, false) const preStat = insertTr.previousSibling.AJAR_statement if (!isInverse) { this.formUndetStat( insertTr, preStat.subject, preStat.predicate, reqTerm, preStat.why, false ) } else { this.formUndetStat( insertTr, reqTerm, preStat.predicate, preStat.object, preStat.why, true ) } outline.walk('moveTo', insertTr.lastChild) this.startFillInText(insertTr.lastChild) // this.statIsInverse=false; }, // Called when delete is pressed Delete: function Delete (selectedTd) { this.deleteTriple(selectedTd, false) }, // Called when enter is pressed Enter: function Enter (selectedTd) { this.literalModification(selectedTd) }, // Called when a selected cell is clicked again Click: function Click (e) { const target = UI.utils.getTarget(e) if (UI.utils.getTerm(target).termType !== 'Literal') return this.literalModification(target) // this prevents the generated inputbox to be clicked again e.preventDefault() e.stopPropagation() }, // Called when paste is called (Ctrl+v) pasteFromClipboard: function pasteFromClipboard (address, selectedTd) { function termFrom (fromCode) { const term = outline.clipboard[fromCode].shift() if (term === null) { UI.log.warn('no more element in clipboard!') return } switch (fromCode) { case 'predicates': case 'objects': { const allArray = outline.clipboard.all for (let i = 0; true; i++) { if (term.sameTerm(allArray[i])) { allArray.splice(i, 1) break } } break } case 'all': throw new Error( 'hostorical code not understood - what is theCollection?' ) /* var isObject = term.sameTerm(theCollection('objects').elements[0]) isObject ? outline.clipboard.objecs.shift() : outline.clipboard.predicates.shift() // drop the corresponding term return [term, isObject] break */ } return term } let term switch (selectedTd.className) { case 'undetermined selected': term = selectedTd.nextSibling ? termFrom('predicates') : termFrom('objects') if (!term) return break case 'pred selected': // paste objects into this predicate term = termFrom('objects') if (!term) return break case 'selected': { // header <TD>, undetermined generated const returnArray = termFrom('all') if (!returnArray) return term = returnArray[0] this.insertTermTo(selectedTd, term, returnArray[1]) return } } this.insertTermTo(selectedTd, term) }, /** * Intermediate Processing: */ // a general entry point for any event except Click&Enter(goes to literalModification) // do a little inference to pick the right input box startFillInText: function startFillInText (selectedTd) { switch (this.whatSortOfEditCell(selectedTd)) { case 'DatatypeProperty-like': // this.clearMenu(); // selectedTd.className=''; UI.utils.emptyNode(selectedTd) this.lastModified = this.createInputBoxIn( selectedTd, ' (Please Input) ' ) this.lastModified.isNew = false this.lastModified.select() break case 'predicate': // the goal is to bring back all the menus (with autocomplete functionality // this.performAutoCompleteEdit(selectedTd,['PredicateAutoComplete', // this.choiceQuery('SuggestPredicateByDomain')]); this.performAutoCompleteEdit(selectedTd, 'PredicateAutoComplete') break case 'ObjectProperty-like': case 'no-idea': // menu should be either function that this.performAutoCompleteEdit(selectedTd, 'GeneralAutoComplete') /* //<code time="original"> emptyNode(selectedTd); this.lastModified=this.createInputBoxIn(selectedTd,""); this.lastModified.select(); this.lastModified.addEventListener('keypress',this.AutoComplete,false); //this pops up the autocomplete menu this.AutoComplete(1); //</code> */ } }, literalModification: function literalModification (selectedTd) { UI.log.debug( 'entering literal Modification with ' + selectedTd + selectedTd.textContent ) // var This=outline.UserInput; if (selectedTd.className.indexOf(' pendingedit') !== -1) { UI.log.warn( 'The node you attempted to edit has a request still pending.\n' + 'Please wait for the request to finish (the text will turn black)\n' + 'before editing this node again.' ) return true } const target = selectedTd const about = this.getStatementAbout(target) // timbl - to avoid alert from random clicks if (!about) return let obj let trNode try { obj = UI.utils.getTerm(target) trNode = UI.utils.ancestor(target, 'TR') } catch (e) { UI.log.warn('userinput.js: ' + e + UI.utils.getAbout(store, selectedTd)) UI.log.error(target + ' getStatement Error:' + e) } let tdNode try { tdNode = trNode.lastChild } catch (e) { UI.log.error(e + '@' + target) } // seems to be a event handling problem of firefox3 /* if (e.type!='keypress'&&(selectedTd.className=='undetermined selected'||selectedTd.className=='undetermined')){ this.Refill(e,selectedTd); return; } */ // ignore clicking trNode.firstChild (be careful for <div> or <span>) // if (e.type!='keypress'&&target!=tdNode && UI.utils.ancestor(target,'TD')!=tdNode) return; if (obj.termType === 'Literal') { tdNode.removeChild(tdNode.firstChild) // remove the text if (obj.value.match('\n')) { // match a line feed and require <TEXTAREA> const textBox = myDocument.createElement('textarea') textBox.appendChild(myDocument.createTextNode(obj.value)) textBox.setAttribute( 'rows', (obj.value.match(/\n/g).length + 1).toString() ) // g is for global(??) textBox.setAttribute('cols', '100') // should be the size of <TD> textBox.setAttribute('class', 'textinput') tdNode.appendChild(textBox) this.lastModified = textBox } else { this.lastModified = this.createInputBoxIn(tdNode, obj.value) } this.lastModified.isNew = false // Kenny: What should be expected after you click a editable text element? // Choice 1 this.lastModified.select() // Choice 2 - direct the key cursor to where you click (failed attempt) // -------------------------------------------------------------------------- // duplicate the event so user can edit without clicking twice // var e2=myDocument.createEvent("MouseEvents"); // e2.initMouseEvent("click",true,true,window,0,0,0,0,0,false,false,false,false,0,null); // inputBox.dispatchEvent(e2); // --------------------------------------------------------------------------- } return true // this is not a valid modification }, /** * UIs: input event handlers, menu generation */ performAutoCompleteEdit: function performAutoCompleteEdit ( selectedTd, menu ) { UI.utils.emptyNode(selectedTd) qp('perform AutoCompleteEdit. THIS IS=' + this) this.lastModified = this.createInputBoxIn(selectedTd, '') this.lastModified.select() this.lastModified.addEventListener( 'keypress', this.getAutoCompleteHandler(menu), false ) /* keypress!? This is what I hate about UI programming. I shall write something about this but not now. */ // this pops up the autocomplete menu // Pops up the menu even though no keypress has occurred // 1 is a dummy variable for the "enterEvent" this.getAutoCompleteHandler(menu)(1) }, backOut: function backOut () { this.deleteTriple(this.lastModified.parentNode, true) this.lastModified = null }, clearMenu: function clearMenu () { const menu = myDocument.getElementById(this.menuID) if (menu) { menu.parentNode.removeChild(menu) // emptyNode(menu); } }, /* goes here when either this is a literal or escape from menu and then input text */ clearInputAndSave: function clearInputAndSave (e) { let obj if (!this.lastModified) return if (!this.lastModified.isNew) { try { obj = this.getStatementAbout(this.lastModified).object } catch (e) { return } } let s = this.lastModifiedStat // when 'isNew' this is set at addNewObject() let defaultpropview let trNode let reqTerm let preStat if (this.lastModified.value !== this.lastModified.defaultValue) { let trCache if (this.lastModified.value === '') { // ToDo: remove this this.lastModified.value = this.lastModified.defaultValue this.clearInputAndSave() return } else if (this.lastModified.isNew) { s = new UI.rdf.Statement( s.subject, s.predicate, store.literal(this.lastModified.value), s.why ) // TODO: DEFINE ERROR CALLBACK defaultpropview = this.views.defaults[s.predicate.uri] trCache = UI.utils.ancestor(this.lastModified, 'TR') try { store.updater.update([], [s], function ( uri, success, errorBody ) { if (!success) { UI.log.error( 'Error occurs while inserting ' + s + '\n\n' + errorBody + '\n' ) // UI.log.warn("Error occurs while inserting "+s+'\n\n'+errorBody); outline.UserInput.deleteTriple(trCache.lastChild, true) } }) } catch (e) { UI.log.error('Error inserting fact ' + s + ':\n\t' + e + '\n') return } s = store.add( s.subject, s.predicate, store.literal(this.lastModified.value), s.why ) } else { if (this.statIsInverse) { UI.log.error( "Invalid Input: a literal can't be a subject in RDF/XML" ) this.backOut() return } let s1, s2, s3 switch (obj.termType) { case 'Literal': { // generate path and nailing from current values // TODO: DEFINE ERROR CALLBACK const valueCache = this.lastModified.value trCache = UI.utils.ancestor(this.lastModified, 'TR') const oldValue = this.lastModified.defaultValue s2 = $rdf.st( s.subject, s.predicate, store.literal(this.lastModified.value), s.why ) try { store.updater.update([s], [s2], function ( uri, success, errorBody ) { if (success) { obj.value = valueCache } else { UI.log.warn( 'Error occurs while editing ' + s + '\n\n' + errorBody ) trCache.lastChild.textContent = oldValue } trCache.lastChild.className = trCache.lastChild.className.replace( / pendingedit/g, '' ) }) } catch (e) { UI.log.warn('Error occurs while editing ' + s + ':\n\t' + e) return } // obj.value=this.lastModified.value; // UserInputFormula.statements.push(s); break } case 'BlankNode': { // a request refill with text // var newStat const textTerm = store.literal(this.lastModified.value, '') // <Feature about="labelChoice"> if (s.predicate.termType === 'Collection') { // case: add triple ????????? Weird - tbl const selectedPredicate = s.predicate.elements[0] // @@ TBL elements is a list on the predicate?? if (store.any(undefined, selectedPredicate, textTerm)) { if (!e) { // keyboard const tdNode = this.lastModified.parentNode e = {} e.pageX = UI.utils.findPos(tdNode)[0] e.pageY = UI.utils.findPos(tdNode)[1] + tdNode.clientHeight } this.showMenu(e, 'DidYouMeanDialog', undefined, { dialogTerm: store.any(undefined, selectedPredicate, textTerm), bnodeTerm: s.subject }) } else { s1 = UI.utils.ancestor( UI.utils.ancestor(this.lastModified, 'TR').parentNode, 'TR' ).AJAR_statement s2 = $rdf.st(s.subject, selectedPredicate, textTerm, s.why) const type = store.the(s.subject, rdf('type')) s3 = store.anyStatementMatching( s.subject, rdf('type'), type, s.why ) // TODO: DEFINE ERROR CALLBACK // because the table is repainted, so... trCache = UI.utils.ancestor( UI.utils.ancestor(this.lastModified, 'TR'), 'TD' ).parentNode try { store.updater.update([], [s1, s2, s3], function ( uri, success, errorBody ) { if (!success) { console.log( 'Error occurs while editing ' + s1 + '\n\n' + errorBody ) outline.UserInput.deleteTriple(trCache.lastChild, true) // @@@@ This } }) } catch (e) { console.log( 'Error occurs while editing ' + s1 + ':\n\t' + e ) return } store.remove(s) store.add(s.subject, selectedPredicate, textTerm, s.why) // was: newStat = // a subtle bug occurs here, if foaf:nick hasn't been dereferneced, // this add will cause a repainting } const enclosingTd = UI.utils.ancestor( this.lastModified.parentNode.parentNode, 'TD' ) const defaultPane = panes.byName('default') // @@ check outline.outlineExpand(enclosingTd, s.subject, { pane: defaultPane, already: true }) outline.walk('right', outline.focusTd) // </Feature> } else { this.fillInRequest( 'object', this.lastModified.parentNode, store.literal(this.lastModified.value) ) return // The new Td is already generated by fillInRequest, so it's done. } break } } } } else if (this.lastModified.isNew) { // generate 'Request', there is no way you can input ' (Please Input) ' trNode = UI.utils.ancestor(this.lastModified, 'TR') reqTerm = this.generateRequest( '(To be determined. Re-type of drag an object onto this field)' ) preStat = trNode.previousSibling.AJAR_statement // the statement of the same predicate this.formUndetStat( trNode, preStat.subject, preStat.predicate, reqTerm, preStat.why, false ) // this why being the same as the previous statement this.lastModified = null // UI.log.warn("test .isNew)"); return } else if (s.predicate.termType === 'Collection') { store.removeMany(s.subject) const upperTr = UI.utils.ancestor( UI.utils.ancestor(this.lastModified, 'TR').parentNode, 'TR' ) preStat = upperTr.AJAR_statement reqTerm = this.generateRequest( '(To be determined. Re-type of drag an object onto this field)' ) this.formUndetStat( upperTr, preStat.subject, preStat.predicate, reqTerm, preStat.why, false ) outline.replaceTD( outline.outlineObjectTD(reqTerm, defaultpropview), upperTr.lastChild ) this.lastModified = null return } else if (this.statIsInverse) { /* if ((s.object.termType === 'BlankNode' && !this.statIsInverse) || s.subject.termType === 'BlankNode' && this.statIsInverse) { this.backOut() return */ if (s.subject.termType === 'BlankNode') { this.backOut() return } } else { if (s.object.termType === 'BlankNode') { this.backOut() return } } // case modified - literal modification only(for now). trNode = UI.utils.ancestor(this.lastModified, 'TR') // var defaultpropview = this.views.defaults[s.predicate.uri] if (!this.statIsInverse) { // this is for an old feature // outline.replaceTD(outline.outlineObjectTD(s.object, defaultpropview),trNode.lastChild); outline.replaceTD( outline.outlineObjectTD( store.literal(this.lastModified.value), defaultpropview ), trNode.lastChild ) } else { outline.replaceTD( outline.outlineObjectTD(s.subject, defaultpropview), trNode.lastChild ) } if (this.lastModified.value !== this.lastModified.defaultValue) { trNode.lastChild.className += ' pendingedit' } // trNode.AJAR_statement=s;//you don't have to set AJAR_inverse because it's not changed // This is going to be painful when predicate-edit allowed this.lastModified = null }, /* deletes the triple corresponding to selectedTd, remove that Td. */ deleteTriple: function deleteTriple (selectedTd, isBackOut) { // ToDo: complete deletion of a node UI.log.debug('deleteTriple entered') // allow a pending node to be deleted if it's a backout sent by SPARQL update callback if (!isBackOut && selectedTd.className.indexOf(' pendingedit') !== -1) { console.log( 'The node you attempted to edit has a request still pending.\n' + 'Please wait for the request to finish (the text will turn black)\n' + 'before editing this node again.' ) outline.walk('up') return } let removedTr // var afterTr const s = this.getStatementAbout(selectedTd) if ( !isBackOut && !store.whether(s.object, rdf('type'), UI.ns.link('Request')) && // Better to check whether provenance is internal? !store.whether(s.predicate, rdf('type'), UI.ns.link('Request')) && !store.whether(s.subject, rdf('type'), UI.ns.link('Request')) ) { UI.log.debug('about to send SPARQLUpdate') try { store.updater.update([s], [], function (uri, success, errorBody) { if (success) { removefromview() } else { // removedTr.AJAR_statement=kb.add(s.subject,s.predicate,s.object,s.why); console.log( 'Error occurs while deleting ' + s + '\n\n' + errorBody ) selectedTd.className = selectedTd.className.replace( / pendingedit/g, '' ) } }) selectedTd.className += ' pendingedit' } catch (e) { UI.log.error(e) UI.log.warn('Error deleting statement ' + s + ':\n\t' + e) return } UI.log.debug('SPARQLUpdate sent') } else { // removal of an undetermined statement associated with pending TRs // TempFormula.remove(s); } UI.log.debug('about to remove ' + s) UI.log.debug('removed') outline.walk('up') removedTr = selectedTd.parentNode // afterTr = removedTr.nextSibling function removefromview () { let trIterator for ( trIterator = removedTr; trIterator.childNodes.length === 1; trIterator = trIterator.previousSibling ); let predicateTd if (trIterator === removedTr) { const theNext = trIterator.nextSibling if (theNext.nextSibling && theNext.childNodes.length === 1) { predicateTd = trIterator.firstChild predicateTd.setAttribute( 'rowspan', parseInt(predicateTd.getAttribute('rowspan')) - 1 ) theNext.insertBefore(trIterator.firstChild, theNext.firstChild) } removedTr.parentNode.removeChild(removedTr) } else { // !DisplayOptions["display:block on"].enabled){ predicateTd = trIterator.firstChild predicateTd.setAttribute( 'rowspan', parseInt(predicateTd.getAttribute('rowspan')) - 1 ) removedTr.parentNode.removeChild(removedTr) } } if (isBackOut) removefromview() }, /* clipboard principle: copy wildly, paste carefully ToDoS: 1. register Subcollection? 2. copy from more than one selectedTd: 1.sequece 2.collection 3. make a clipboard class? */ clipboardInit: function clipboardInit () { outline.clipboard = {} outline.clipboard.objects = [] outline.clipboard.predicates = [] outline.clipboard.all = [] }, copyToClipboard: function copyToClipboard (address, selectedTd) { /* var clip = Components.classes["@mozilla.org/widget/clipboard;1"].getService(Components.interfaces.nsIClipboard); if (!clip) return false; var clipid = Components.interfaces.nsIClipboard; var trans = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable); if (!trans) return false; var copytext = "Tabulator!!"; var str = Components.classes["@mozilla.org/supports-string;1"]. createInstance(Components.interfaces.nsISupportsString); if (!str) return false; str.data = copytext; trans.addDataFlavor("text/x-moz-url"); trans.setTransferData("text/x-mox-url", str, copytext.length * 2); clip.setData(trans, null, clipid.kGlobalClipboard); */ const term = UI.utils.getTerm(selectedTd) switch (selectedTd.className) { case 'selected': // table header case 'obj selected': // var objects = outline.clipboard.objects outline.clipboard.objects.unshift(term) break case 'pred selected': case 'pred internal selected': outline.clipboard.predicates.unshift(term) } outline.clipboard.all.unshift(term) }, insertTermTo: function insertTermTo (selectedTd, term, isObject) { let defaultpropview let preStat switch (selectedTd.className) { case 'undetermined selected': defaultpropview = this.views.defaults[ selectedTd.parentNode.AJAR_statement.predicate.uri ] this.fillInRequest( selectedTd.nextSibling ? 'predicate' : 'object', selectedTd, term ) break case 'pred selected': { // paste objects into this predicate const insertTr = this.appendToPredicate(selectedTd) preStat = selectedTd.parentNode.AJAR_statement defaultpropview = this.views.defaults[preStat.predicate.uri] insertTr.appendChild(outline.outlineObjectTD(term, defaultpropview)) // modify store and update here const isInverse = selectedTd.parentNode.AJAR_inverse if (!isInverse) { insertTr.AJAR_statement = store.add( preStat.subject, preStat.predicate, term, preStat.why ) } else { insertTr.AJAR_statemnet = store.add( term, preStat.predicate, preStat.object, preStat.why ) } try { store.updater.update([], [insertTr.AJAR_statement], function ( uri, success, errorBody ) { if (!success) { UI.log.error( 'userinput.js (pred selected): Fail trying to insert statement ' + insertTr.AJAR_statement + ': ' + errorBody ) } }) } catch (e) { UI.log.error( 'Exception trying to insert statement ' + insertTr.AJAR_statement + ': ' + UI.utils.stackString(e) ) return } insertTr.AJAR_inverse = isInverse UserInputFormula.statements.push(insertTr.AJAR_statement) break } case 'selected': { // header <TD>, undetermined generated const paneDiv = UI.utils.ancestor(selectedTd, 'TABLE').lastChild const newTr = paneDiv.insertBefore( myDocument.createElement('tr'), paneDiv.lastChild ) // var titleTerm=UI.utils.getAbout(kb,UI.utils.ancestor(newTr,'TD')); preStat = newTr.previousSibling.AJAR_statement if (typeof isObject === 'undefined') isObject = true if (isObject) { // object inserted this.formUndetStat( newTr, preStat.subject, this.generateRequest('(TBD)', newTr, true), term, preStat.why, false ) // defaultpropview temporaily not dealt with newTr.appendChild(outline.outlineObjectTD(term)) outline.walk('moveTo', newTr.firstChild) this.startFillInText(newTr.firstChild) } else { // predicate inserted // existing predicate not expected const reqTerm = this.generateRequest( '(To be determined. Re-type of drag an object onto this field)', newTr ) this.formUndetStat( newTr, preStat.subject, term, reqTerm, preStat.why, false ) newTr.insertBefore( outline.outlinePredicateTD(term, newTr, false, false), newTr.firstChild ) outline.walk('moveTo', newTr.lastChild) this.startFillInText(newTr.lastChild) } break } } }, Refill: function Refill (e, selectedTd) { UI.log.info('Refill' + selectedTd.textContent) const isPredicate = selectedTd.nextSibling let predicateQuery if (isPredicate) { // predicateTd let subject let subjectClass let sparqlText if (selectedTd.nextSibling.className === 'undetermined') { /* Make set of proprties to propose for a predicate. The naive approach is to take those which have a class of the subject as their domain. But in fact we must offer anything which is not explicitly excluded, by having a domain disjointWith a class of the subject. */ /* SELECT ?pred WHERE{ ?pred a rdf:Property. ?pred rdfs:domain subjectClass. } */ /* SELECT ?pred ?class WHERE{ ?pred a rdf:Property. subjectClass owl:subClassOf ?class. ?pred rdfs:domain ?class. } */ /* SELECT ?pred WHERE{ subject a ?subjectClass. ?pred rdfs:domain ?subjectClass. } */ subject = UI.utils.getAbout( store, UI.utils.ancestor(selectedTd, 'TABLE').parentNode ) subjectClass = store.any(subject, rdf('type')) sparqlText = [] const endl = '.\n' sparqlText[0] = 'SELECT ?pred WHERE{\n?pred ' + rdf('type') + rdf('Property') + '.\n' + '?pred ' + UI.ns.rdfs('domain') + subjectClass + '.}' // \n is required? SPARQL parser bug? sparqlText[1] = 'SELECT ?pred ?class\nWHERE{\n' + '?pred ' + rdf('type') + rdf('Property') + '.\n' + subjectClass + UI.ns.rdfs('subClassOf') + ' ?class.\n' + '?pred ' + UI.ns.rdfs('domain') + ' ?class.\n}' sparqlText[2] = 'SELECT ?pred WHERE{\n' + subject + rdf('type') + store.variable('subjectClass') + endl + store.variable('pred') + UI.ns.rdfs('domain') + store.variable('subjectClass') + endl + '}' predicateQuery = sparqlText.map($rdf.SPARQLToQuery) } else { // ------selector /* SELECT ?pred WHERE{ ?pred a rdf:Property. ?pred rdfs:domain subjectClass. ?pred rdfs:range objectClass. } */ // Candidate /* SELECT ?pred WHERE{ subject a ?subjectClass. object a ?objectClass. ?pred rdfs:domain ?subjectClass. ?pred rdfs:range ?objectClass. */ subject = UI.utils.getAbout( store, UI.utils.ancestor(selectedTd, 'TABLE').parentNode ) subjectClass = store.any(subject, rdf('type')) const object = selectedTd.parentNode.AJAR_statement.object // var objectClass = (object.termType === 'Literal') ? UI.ns.rdfs('Literal') : kb.any(object, rdf('type')) // var sparqlText="SELECT ?pred WHERE{\n?pred "+rdf('type')+rdf('Property')+".\n"+ // "?pred "+UI.ns.rdfs('domain')+subjectClass+".\n"+ // "?pred "+UI.ns.rdfs('range')+objectClass+".\n}"; // \n is required? SPARQL parser bug? sparqlText = 'SELECT ?pred WHERE{' + subject + rdf('type') + '?subjectClass' + '.\n' + object + rdf('type') + '?objectClass' + '.\n' + '?pred ' + UI.ns.rdfs('domain') + '?subjectClass' + '.\n' + '?pred ' + UI.ns.rdfs('range') + '?objectClass' + '.\n}' // \n is required? SPARQL parser bug? predicateQuery = $rdf.SPARQLToQuery(sparqlText) } // -------presenter // ToDo: how to sort selected predicates? this.showMenu(e, 'GeneralPredicateChoice', predicateQuery, { isPredicate: isPredicate, selectedTd: selectedTd }) } else { // objectTd const predicateTerm = selectedTd.parentNode.AJAR_statement.predicate if ( store.whether( predicateTerm, rdf('type'), UI.ns.owl('DatatypeProperty') ) || predicateTerm.termType === 'Collection' || store.whether(predicateTerm, UI.ns.rdfs('range'), UI.ns.rdfs('Literal')) ) { selectedTd.className = '' UI.utils.emptyNode(selectedTd) this.lastModified = this.createInputBoxIn( selectedTd, ' (Please Input) ' ) this.lastModified.isNew = false this.lastModified.select() } // show menu for rdf:type if ( selectedTd.parentNode.AJAR_statement.predicate.sameTerm(rdf('type')) ) { const sparqlText = 'SELECT ?class WHERE{?class ' + rdf('type') + UI.ns.rdfs('Class') + '.}' // I should just use kb.each const classQuery = $rdf.SPARQLToQuery(sparqlText) this.showMenu(e, 'TypeChoice', classQuery, { isPredicate: isPredicate, selectedTd: selectedTd }) } } }, // This is where pubsPane.js comes in, with: outline.UserInput.getAutoCompleteHandler("JournalTAC")(e); getAutoCompleteHandler: function getAutoCompleteHandler (mode) { qp('\n\n***** In getAutoCompleteHandler ****** mode = ' + mode) if (mode === 'PredicateAutoComplete') { mode = 'predicate' } else if (mode !== 'JournalTAC') { // hq // why? -tim - not 'predicate' below mode = 'all' } let InputBox if (mode === 'JournalTAC') { // hq // Better to pass in InputBox as a param InputBox = myDocument.getElementById('inpid_journal_title') } else { InputBox = this.lastModified || outline.getSelection()[0].firstChild } qp('InputBox=' + InputBox) // hq qp('InputBox.value=' + InputBox.value) // hq return function (enterEvent) { qp('ENTER EVENT=' + enterEvent) // Firefox 2.0.0.6 makes this not working? 'this' becomes [object HTMLInputElement] // but not [wrapped ...] // var InputBox=(typeof enterEvent=='object')?this:this.lastModified;//'this' is the <input> element qp('1. outside (if eneterEvent)') const e = {} const tdNode = InputBox.parentNode if (!mode) mode = tdNode.nextSibling ? 'predicate' : 'all' e.pageX = UI.utils.findPos(tdNode)[0] e.pageY = UI.utils.findPos(tdNode)[1] + tdNode.clientHeight qp('epX=' + e.pageX + ', epY=' + e.pageY + ', mode=' + mode) let menu = myDocument.getElementById(outline.UserInput.menuID) function setHighlightItem (item) { if (!item) return // do not make changes if (menu.lastHighlight) menu.lastHighlight.className = '' menu.lastHighlight = item menu.lastHighlight.className = 'activeItem' outline.showURI(UI.utils.getAbout(store, menu.lastHighlight)) } if (enterEvent) { // either the real event of the pseudo number passed by OutlineKeypressPanel qp('2. in (if enterEvent). with type = ' + typeof enterEvent) let newText = InputBox.value if (typeof enterEvent === 'object') { qp( '3. in typeof enterEvent is object, will switch to keys, arrows, etc. keycode = ' + enterEvent.keyCode ) enterEvent.stopPropagation() if (menu && !menu.lastHighlight) { // this ensures the following operation valid setHighlightItem(menu.firstChild.firstChild) } switch (enterEvent.keyCode) { case 13: // enter case 9: // tab qp('handler: Enter or Tab') if (!menu) { outline.UserInput.clearInputAndSave() return } if (!menu.lastHighlight) { if (mode === 'JournalTAC') { outline.UserInput.clearMenu() qp('no lastH') return 'no lastH' } return } // warning? if (menu.lastHighlight.tagName === 'INPUT') { switch (menu.lastHighlight.value) { case 'New...': qp('subcase New') outline.UserInput.createNew() break case 'GiveURI': qp('subcase GiveURI') outline.UserInput.inputURI() break } } else { // pubsPane Stuff: if (mode === 'JournalTAC') { qp('movedArrow? ' + movedArrow) // Enter only works if arrows have been moved if (movedArrow && menu.lastHighlight) { // Get the title from the DOM // tr, th, div, innerHTML const jtitle = menu.lastHighlight.firstChild.firstChild.innerHTML // tr, th, td, innerHTML let juri = menu.lastHighlight.firstChild.nextSibling.innerHTML // clearing out the &lt; and &gt; from juri juri = juri.slice(4, -4) return ['gotdptitle', jtitle, juri] } // If doesn't qualify to be autocomplete, return this random string, since pubsPane checks for "gotdptitle" return 'asGivenTxt' } const inputTerm = UI.utils.getAbout(store, menu.lastHighlight) const fillInType = mode === 'predicate' ? 'predicate' : 'object' outline.UserInput.clearMenu() outline.UserInput.fillInRequest( fillInType, InputBox.parentNode, inputTerm ) // if (outline.UserInput.fillInRequest(fillInType,InputBox.parentNode,inputTerm)) // outline.UserInput.clearMenu(); } qp('outside') return case 38: // up qp('handler: Arrow UP') movedArrow = true // hq if ( newText === '' && menu.lastHighlight.tagName === 'TR' && !menu.lastHighlight.previousSibling ) { setHighlightItem(menu.firstChild.firstChild) } else { setHighlightItem(menu.lastHighlight.previousSibling) } return "I'm a little Arrow Up" case 40: // down qp('handler: Arrow Down') movedArrow = true // hq if (menu.lastHighlight.tagName === 'INPUT') { setHighlightItem(menu.childNodes[1].firstChild) } else { setHighlightItem(menu.lastHighlight.nextSibling) } return "I'm a little Down Arrow" case 37: // left case 39: // right qp('handler: Arrow left, right') if (menu.lastHighlight.tagName === 'INPUT') { if (enterEvent.keyCode === 37) { setHighlightItem(menu.lastHighlight.previousSibling) } else { setHighlightItem(menu.lastHighlight.nextSibling) } } return case 8: // backspace qp('handler: Backspace') newText = newText.slice(0, -1) break case 27: // esc to enter literal qp('handler: Esc') if (!menu) { outline.UserInput.backOut() return } outline.UserInput.clearMenu() // Not working? I don't know. // InputBox.removeEventListener('keypress',outline.UserInput.Autocomplete,false); return // break default: qp('handler: Default') movedArrow = false // hq // we need this because it is keypress, seeAlso performAutoCompleteEdit qp('oldtext=' + newText) newText += String.fromCharCode(enterEvent.charCode) qp('charcodent=' + enterEvent.charCode) qp('strcharcod=' + String.fromCharCode(enterEvent.charCode)) console.log('DEFAULT txtstr=' + newText + '\n') // hq } } // endif typeof(event) === object // UI.log.warn(InputBox.choices.length); // for(i=0;InputBox.choices[i].label<newText;i++); //O(n) ToDo: O(log n) if (mode === 'all') { qp('generalAC after switch, newText=' + newText + 'mode is all') outline.UserInput.clearMenu() // outline.UserInput.showMenu(e,'GeneralAutoComplete',undefined,{'isPredicate':false,'selectedTd':tdNode,'choices':InputBox.choices, 'index':i}); outline.UserInput.showMenu(e, 'GeneralAutoComplete', undefined, { inputText: newText, selectedTd: tdNode }) if (newText.length === 0) outline.UserInput.WildCardButtons() } else if (mode === 'predicate') { qp( 'predicateAC after switch, newText=' + newText + 'mode is predicate' ) outline.UserInput.clearMenu() outline.UserInput.showMenu(e, 'PredicateAutoComplete', undefined, { inputText: newText, isPredicate: true, selectedTd: tdNode }) } else if (mode === 'JournalTAC') { // hq qp('JouralTAC after switch, newText=' + newText) outline.UserInput.clearMenu() // Goto showMenu outline.UserInput.showMenu( e, 'JournalTitleAutoComplete', undefined, { inputText: newText }, 'orderisuseless' ) } menu = myDocument.getElementById(outline.UserInput.menuID) if (!menu) { qp('No menu element. Do not show menu.') return } qp('at end of handler\n^^^^^^^^^^^^^^^^^\n\n') setHighlightItem(menu.firstChild.firstChild) outl