outline/userInput.js
function clearInputAndSave (e) {
      if (!this.lastModified) return
      if (!this.lastModified.isNew) {
        try {
          var obj = this.getStatementAbout(this.lastModified).object
        } catch (e) { return }
      }
      var s = this.lastModifiedStat // when 'isNew' this is set at addNewObject()

      if (this.lastModified.value !== this.lastModified.defaultValue) {
        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, kb.literal(this.lastModified.value), s.why)
                // TODO: DEFINE ERROR CALLBACK
          var defaultpropview = this.views.defaults[s.predicate.uri]
          var trCache = UI.utils.ancestor(this.lastModified, 'TR')
          try {
            UI.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 = kb.add(s.subject, s.predicate, kb.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
          }
          var s1, s2, s3
          switch (obj.termType) {
            case 'Literal':
                        // generate path and nailing from current values

                        // TODO: DEFINE ERROR CALLBACK
              var valueCache = this.lastModified.value
              trCache = UI.utils.ancestor(this.lastModified, 'TR')
              var oldValue = this.lastModified.defaultValue
              s2 = $rdf.st(s.subject, s.predicate, kb.literal(this.lastModified.value), s.why)
              try {
                UI.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
              var textTerm = kb.literal(this.lastModified.value, '')
                        // <Feature about="labelChoice">
              if (s.predicate.termType === 'Collection') { // case: add triple   ????????? Weird - tbl
                var selectedPredicate = s.predicate.elements[0]   //    @@ TBL elements is a list on the predicate??
                if (kb.any(undefined, selectedPredicate, textTerm)) {
                  if (!e) { // keyboard
                    var 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': kb.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)
                  var type = kb.the(s.subject, rdf('type'))
                  s3 = kb.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 {
                    UI.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
                  }
                  kb.remove(s)
                  kb.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
                }
                var enclosingTd = UI.utils.ancestor(this.lastModified.parentNode.parentNode, 'TD')
                const defaultPane = panes.default // @@ check
                outline.outlineExpand(enclosingTd, s.subject, {'pane': defaultPane, 'already': true})
                outline.walk('right', outline.focusTd)
                        // </Feature>
              } else {
                this.fillInRequest('object', this.lastModified.parentNode, kb.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) '
        var trNode = UI.utils.ancestor(this.lastModified, 'TR')
        var reqTerm = this.generateRequest('(To be determined. Re-type of drag an object onto this field)')
        var 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') {
        kb.removeMany(s.subject)
        var 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 ((s.object.termType === 'BlankNode' && !this.statIsInverse) ||
                  s.subject.termType === 'BlankNode' && this.statIsInverse) {
        this.backOut()
        return
      */
      if (this.statIsInverse) {
        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(kb.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
    }
function clearInputAndSave (e) {
      if (!this.lastModified) return
      if (!this.lastModified.isNew) {
        try {
          var obj = this.getStatementAbout(this.lastModified).object
        } catch (e) { return }
      }
      var s = this.lastModifiedStat // when 'isNew' this is set at addNewObject()

      if (this.lastModified.value !== this.lastModified.defaultValue) {
        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, kb.literal(this.lastModified.value), s.why)
                // TODO: DEFINE ERROR CALLBACK
          var defaultpropview = this.views.defaults[s.predicate.uri]
          var trCache = UI.utils.ancestor(this.lastModified, 'TR')
          try {
            UI.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 = kb.add(s.subject, s.predicate, kb.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
          }
          var s1, s2, s3
          switch (obj.termType) {
            case 'Literal':
                        // generate path and nailing from current values

                        // TODO: DEFINE ERROR CALLBACK
              var valueCache = this.lastModified.value
              trCache = UI.utils.ancestor(this.lastModified, 'TR')
              var oldValue = this.lastModified.defaultValue
              s2 = $rdf.st(s.subject, s.predicate, kb.literal(this.lastModified.value), s.why)
              try {
                UI.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
              var textTerm = kb.literal(this.lastModified.value, '')
                        // <Feature about="labelChoice">
              if (s.predicate.termType === 'Collection') { // case: add triple   ????????? Weird - tbl
                var selectedPredicate = s.predicate.elements[0]   //    @@ TBL elements is a list on the predicate??
                if (kb.any(undefined, selectedPredicate, textTerm)) {
                  if (!e) { // keyboard
                    var 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': kb.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)
                  var type = kb.the(s.subject, rdf('type'))
                  s3 = kb.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 {
                    UI.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
                  }
                  kb.remove(s)
                  kb.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
                }
                var enclosingTd = UI.utils.ancestor(this.lastModified.parentNode.parentNode, 'TD')
                const defaultPane = panes.default // @@ check
                outline.outlineExpand(enclosingTd, s.subject, {'pane': defaultPane, 'already': true})
                outline.walk('right', outline.focusTd)
                        // </Feature>
              } else {
                this.fillInRequest('object', this.lastModified.parentNode, kb.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) '
        var trNode = UI.utils.ancestor(this.lastModified, 'TR')
        var reqTerm = this.generateRequest('(To be determined. Re-type of drag an object onto this field)')
        var 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') {
        kb.removeMany(s.subject)
        var 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 ((s.object.termType === 'BlankNode' && !this.statIsInverse) ||
                  s.subject.termType === 'BlankNode' && this.statIsInverse) {
        this.backOut()
        return
      */
      if (this.statIsInverse) {
        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(kb.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
    }
/* goes here when either this is a literal or escape from menu and then input text