outline/manager.js
function outlineExpand (p, subject1, options) {
    options = options || {}
    var pane = options.pane
    var already = !!options.already
    var immediate = options.immediate

    UI.log.info('@outlineExpand, dom is now ' + dom.location)
      // remove callback to prevent unexpected repaint
    sf.removeCallback('done', 'expand')
    sf.removeCallback('fail', 'expand')

    var subject = kb.canon(subject1)
    // var requTerm = subject.uri ? kb.sym(UI.rdf.uri.docpart(subject.uri)) : subject

    function render () {
      subject = kb.canon(subject)
      if (!p || !p.parentNode || !p.parentNode.parentNode) return false

      var newTable
      UI.log.info('@@ REPAINTING ')
      if (!already) { // first expand
        newTable = propertyTable(subject, undefined, pane, options)
      } else {
        UI.log.info(' ... p is  ' + p)
        for (newTable = p.firstChild; newTable.nextSibling; newTable = newTable.nextSibling) {
          UI.log.info(' ... checking node ' + newTable)
          if (newTable.nodeName === 'table') break
        }
        newTable = propertyTable(subject, newTable, pane, options)
      }
      already = true
      if (UI.utils.ancestor(p, 'TABLE') && UI.utils.ancestor(p, 'TABLE').style.backgroundColor === 'white') {
        newTable.style.backgroundColor = '#eee'
      } else {
        newTable.style.backgroundColor = 'white'
      }
      try {
        if (YAHOO.util.Event.off) YAHOO.util.Event.off(p, 'mousedown', 'dragMouseDown')
      } catch (e) {
        console.log('YAHOO ' + e)
      }
      UI.utils.emptyNode(p).appendChild(newTable)
      thisOutline.focusTd = p // I don't know why I couldn't use 'this'...because not defined in callbacks
      UI.log.debug('expand: Node for ' + subject + ' expanded')
          // fetch seeAlso when render()
          // var seeAlsoStats = sf.store.statementsMatching(subject, UI.ns.rdfs('seeAlso'))
          // seeAlsoStats.map(function (x) {sf.lookUpThing(x.object, subject,false);})
      var seeAlsoWhat = kb.each(subject, UI.ns.rdfs('seeAlso'))
      for (var i = 0; i < seeAlsoWhat.length; i++) {
        if (i === 25) {
          UI.log.warn('expand: Warning: many (' +
                seeAlsoWhat.length + ') seeAlso links for ' + subject)
              // break; Not sure what limits the AJAX system has here
        }
        sf.lookUpThing(seeAlsoWhat[i], subject)
      }
    }

    function expand (uri) {
      if (arguments[3]) return true // already fetched indicator
      var cursubj = kb.canon(subject) // canonical identifier may have changed
      UI.log.info('@@ expand: relevant subject=' + cursubj + ', uri=' + uri + ', already=' + already)
      // var term = kb.sym(uri)
      var docTerm = kb.sym(UI.rdf.uri.docpart(uri))
      if (uri.indexOf('#') >= 0) { throw new Error('Internal error: hash in ' + uri) }

      var relevant = function () { // Is the loading of this URI relevam to the display of subject?
        if (!cursubj.uri) return true // bnode should expand()
        var as = kb.uris(cursubj)
        if (!as) return false
        for (var i = 0; i < as.length; i++) { // canon'l uri or any alias
          for (var rd = UI.rdf.uri.docpart(as[i]); rd; rd = kb.HTTPRedirects[rd]) {
            if (uri === rd) return true
          }
        }
        if (kb.anyStatementMatching(cursubj, undefined, undefined, docTerm)) return true // Kenny: inverse?
        return false
      }
      if (relevant()) {
        UI.log.success('@@ expand OK: relevant subject=' + cursubj + ', uri=' + uri + ', source=' +
              already)

        render()
        return false //  @@@@@@@@@@@ Will this allow just the first
      }
      return true
    }
        // Body of outlineExpand

    if (options.solo) {
      dom.title = UI.utils.label(subject)
    }
    UI.log.debug('outlineExpand: dereferencing ' + subject)
    var status = dom.createElement('span')
    p.appendChild(status)
    sf.addCallback('done', expand) // @@@@@@@ This can really mess up existing work
    sf.addCallback('fail', expand) // Need to do if there s one a gentle resync of page with store

    var returnConditions = [] // this is quite a general way to do cut and paste programming
      // I might make a class for this
    if (subject.uri && subject.uri.split(':')[0] === 'rdf') { // what is this? -tim
      render()
      return
    }

    for (var i = 0; i < returnConditions.length; i++) {
      var returnCode
      if (returnCode === returnConditions[i](subject)) {
        render()
        UI.log.debug('outline 1815')
        if (returnCode[1]) outlineElement.removeChild(outlineElement.lastChild)
        return
      }
    }
    if (subject.uri && !immediate && !UI.widgets.isAudio(subject) &&
        !UI.widgets.isVideo(subject) && // Never parse videos as data
        !kb.holds(subject, UI.ns.rdf('type'), $rdf.Util.mediaTypeClass('application/pdf'))) { // or PDF
        // Wait till at least the main URI is loaded before expanding:
      sf.nowOrWhenFetched(subject.doc(), undefined, function (ok, body) {
        if (ok) {
          sf.lookUpThing(subject)
          render() // inital open, or else full if re-open
          if (options.solo) { // Update window title with new information
            dom.title = UI.utils.label(subject)
          }
        } else {
          var message = dom.createElement('pre')
          message.textContent = body
          message.setAttribute('style', 'background-color: #fee;')
          message.textContent = 'Outline.expand: Unable to fetch ' + subject.doc() + ': ' + body
          p.appendChild(message)
        }
      })
    } else {
      render()
    };
  }
function outlineExpand (p, subject1, options) {
    options = options || {}
    var pane = options.pane
    var already = !!options.already
    var immediate = options.immediate

    UI.log.info('@outlineExpand, dom is now ' + dom.location)
      // remove callback to prevent unexpected repaint
    sf.removeCallback('done', 'expand')
    sf.removeCallback('fail', 'expand')

    var subject = kb.canon(subject1)
    // var requTerm = subject.uri ? kb.sym(UI.rdf.uri.docpart(subject.uri)) : subject

    function render () {
      subject = kb.canon(subject)
      if (!p || !p.parentNode || !p.parentNode.parentNode) return false

      var newTable
      UI.log.info('@@ REPAINTING ')
      if (!already) { // first expand
        newTable = propertyTable(subject, undefined, pane, options)
      } else {
        UI.log.info(' ... p is  ' + p)
        for (newTable = p.firstChild; newTable.nextSibling; newTable = newTable.nextSibling) {
          UI.log.info(' ... checking node ' + newTable)
          if (newTable.nodeName === 'table') break
        }
        newTable = propertyTable(subject, newTable, pane, options)
      }
      already = true
      if (UI.utils.ancestor(p, 'TABLE') && UI.utils.ancestor(p, 'TABLE').style.backgroundColor === 'white') {
        newTable.style.backgroundColor = '#eee'
      } else {
        newTable.style.backgroundColor = 'white'
      }
      try {
        if (YAHOO.util.Event.off) YAHOO.util.Event.off(p, 'mousedown', 'dragMouseDown')
      } catch (e) {
        console.log('YAHOO ' + e)
      }
      UI.utils.emptyNode(p).appendChild(newTable)
      thisOutline.focusTd = p // I don't know why I couldn't use 'this'...because not defined in callbacks
      UI.log.debug('expand: Node for ' + subject + ' expanded')
          // fetch seeAlso when render()
          // var seeAlsoStats = sf.store.statementsMatching(subject, UI.ns.rdfs('seeAlso'))
          // seeAlsoStats.map(function (x) {sf.lookUpThing(x.object, subject,false);})
      var seeAlsoWhat = kb.each(subject, UI.ns.rdfs('seeAlso'))
      for (var i = 0; i < seeAlsoWhat.length; i++) {
        if (i === 25) {
          UI.log.warn('expand: Warning: many (' +
                seeAlsoWhat.length + ') seeAlso links for ' + subject)
              // break; Not sure what limits the AJAX system has here
        }
        sf.lookUpThing(seeAlsoWhat[i], subject)
      }
    }

    function expand (uri) {
      if (arguments[3]) return true // already fetched indicator
      var cursubj = kb.canon(subject) // canonical identifier may have changed
      UI.log.info('@@ expand: relevant subject=' + cursubj + ', uri=' + uri + ', already=' + already)
      // var term = kb.sym(uri)
      var docTerm = kb.sym(UI.rdf.uri.docpart(uri))
      if (uri.indexOf('#') >= 0) { throw new Error('Internal error: hash in ' + uri) }

      var relevant = function () { // Is the loading of this URI relevam to the display of subject?
        if (!cursubj.uri) return true // bnode should expand()
        var as = kb.uris(cursubj)
        if (!as) return false
        for (var i = 0; i < as.length; i++) { // canon'l uri or any alias
          for (var rd = UI.rdf.uri.docpart(as[i]); rd; rd = kb.HTTPRedirects[rd]) {
            if (uri === rd) return true
          }
        }
        if (kb.anyStatementMatching(cursubj, undefined, undefined, docTerm)) return true // Kenny: inverse?
        return false
      }
      if (relevant()) {
        UI.log.success('@@ expand OK: relevant subject=' + cursubj + ', uri=' + uri + ', source=' +
              already)

        render()
        return false //  @@@@@@@@@@@ Will this allow just the first
      }
      return true
    }
        // Body of outlineExpand

    if (options.solo) {
      dom.title = UI.utils.label(subject)
    }
    UI.log.debug('outlineExpand: dereferencing ' + subject)
    var status = dom.createElement('span')
    p.appendChild(status)
    sf.addCallback('done', expand) // @@@@@@@ This can really mess up existing work
    sf.addCallback('fail', expand) // Need to do if there s one a gentle resync of page with store

    var returnConditions = [] // this is quite a general way to do cut and paste programming
      // I might make a class for this
    if (subject.uri && subject.uri.split(':')[0] === 'rdf') { // what is this? -tim
      render()
      return
    }

    for (var i = 0; i < returnConditions.length; i++) {
      var returnCode
      if (returnCode === returnConditions[i](subject)) {
        render()
        UI.log.debug('outline 1815')
        if (returnCode[1]) outlineElement.removeChild(outlineElement.lastChild)
        return
      }
    }
    if (subject.uri && !immediate && !UI.widgets.isAudio(subject) &&
        !UI.widgets.isVideo(subject) && // Never parse videos as data
        !kb.holds(subject, UI.ns.rdf('type'), $rdf.Util.mediaTypeClass('application/pdf'))) { // or PDF
        // Wait till at least the main URI is loaded before expanding:
      sf.nowOrWhenFetched(subject.doc(), undefined, function (ok, body) {
        if (ok) {
          sf.lookUpThing(subject)
          render() // inital open, or else full if re-open
          if (options.solo) { // Update window title with new information
            dom.title = UI.utils.label(subject)
          }
        } else {
          var message = dom.createElement('pre')
          message.textContent = body
          message.setAttribute('style', 'background-color: #fee;')
          message.textContent = 'Outline.expand: Unable to fetch ' + subject.doc() + ': ' + body
          p.appendChild(message)
        }
      })
    } else {
      render()
    };
  }
function TabulatorMousedown