<commit_before># offline app - for App

appcache = require 'appcache'
templateApp = require 'templates/App'
HomeView = require 'views/Home'
CacheStateWidgetView = require 'views/CacheStateWidget'
FormUploadWidgetView = require 'views/FormUploadWidget'
LocationWidgetView = require 'views/LocationWidget'

BookletView = require 'views/Booklet'
ThingView = require 'views/Thing'
PlaceView = require 'views/Place'
HtmlView = require 'views/Html'
ListView = require 'views/List'
FormView = require 'views/Form'
UserView = require 'views/User'

ThingListView = require 'views/ThingList'
FormUploadView = require 'views/FormUpload'
AboutView = require 'views/About'
ShareView = require 'views/Share'
LocationView = require 'views/Location'

localdb = require 'localdb'
formdb = require 'formdb'
working = require 'working'
location = require 'location'

#config = window.mediahubconfig

appid = null
dburl = null
appconfig = null

appmodel = new Backbone.Model {}

items = {}
currentView = null

topLevelThings = new Backbone.Collection()

class Router extends Backbone.Router
  routes: 
    "" : "entries"
    "#" : "entries"
    "thing/:id": "thing"
    "booklet/:id/:page": "bookletPage"
    "booklet/:id/:page/": "bookletPage"
    "booklet/:id/:page/:anchor": "bookletPage"
    "upload": "upload"
    "user": "user"
    "about": "about"
    "share": "share"
    "location": "location"

  removeCurrentView: ->
    if currentView?
      try 
        currentView.remove()
      catch err
        console.log "error removing current view: #{err.message}"
      currentView = null

  setCurrentView: (view) ->
    @removeCurrentView()
    currentView = view
    $('#page-content-holder').empty()
    if not view.el
      console.log "Error: new current view has no element - trying to render"
      view.render()
    $('#page-content-holder').append view.el
    if view.title
      $('#app-title').html view.title
    else if view.model?.attributes?.title
      $('#app-title').html view.model.attributes.title
    else if HomeView.prototype.isPrototypeOf view
      $('#app-title').html appconfig?.title ? 'Home'
    else
      $('#app-title').html 'Home'

  upload: () ->
    console.log "show upload"
    @setCurrentView new FormUploadView model: formdb.getFormUploadState()
    true

  entries: ->
    console.log "router: entries"
    @setCurrentView new HomeView model: topLevelThings, id: ''
    true

  thing: (id) ->
    console.log "show thing #{id}"
    thing = items[id]
    if not thing?
      alert "Sorry, could not find thing #{id}"
      @navigate '#', { trigger:true, replace:true }
      return false
    
    if thing.attributes.type=='booklet'
      view = new BookletView model: thing
    else if thing.attributes.type=='place'
      view = new PlaceView model: thing
    else if thing.attributes.type=='html'
      view = new HtmlView model: thing
    else if thing.attributes.type=='form'
      view = new FormView model: thing
    else if thing.attributes.type=='list'
      view = new ListView model: thing
    else if thing.attributes.type?
      view = new ThingView model: thing
    else
      alert "Sorry, not sure how to display #{id}"
      @navigate '#', { trigger:true, replace:true }
      return false
 
    @setCurrentView view
    true

  bookletPage: (id,page,anchor) ->
    if not currentView? or currentView.model.id != id
      if not @thing id
        return
    currentView.showPage page,anchor

  user: () ->
    @setCurrentView new UserView model: (require 'user').getUser()

  about: () ->
    @setCurrentView new AboutView model: appmodel

  share: () ->
    @setCurrentView new ShareView model: appmodel

  location: () ->
    @setCurrentView new LocationView model: location.getLocation()

makeThing = (data, collection) ->
  try
    thing = new Backbone.Model data
    if thing.id
      items[thing.id] = thing
    collection.add thing
    if data.thingIds?
      console.log "create new thing collection for #{thing.id}"
      thing.things = new Backbone.Collection()
      loadThings data,thing.things
  catch err
    console.log "error making thing: #{err.message}: #{data}\n#{err.stack}"

checkThing = (data,collection) ->
  #if instanceid isnt localdb.currentInstanceid()
  #  console.log "Ignore item on load; old instanceid #{instanceid} vs #{localdb.currentInstanceid()}"
  #  return
  try 
    data = JSON.parse data
    if data.type?
      makeThing data, collection
    else
      console.log "unknown item type #{data.type} - ignored"
  catch err
    console.log "error parsing thing: #{err.message}: #{data}"

loadThing = (thingId,collection) ->
  console.log "load thing #{thingId}"
  $.ajax dburl+"/"+encodeURIComponent(thingId),
    success: (data)->
      checkThing data, collection
    dataType: "text"
    error: (xhr,status,err) ->
      console.log "get thing error "+xhr.status+": "+err.message
      # on android (at least) files from cache sometimes have status 0!!
      if xhr.status==0 && xhr.responseText
        checkThing xhr.responseText, collection

loadThings = (app,collection) ->
  for thingId in app.thingIds
    # id, url, type
    loadThing thingId,collection
  working.done()

checkConfig = (app) ->
  console.log  "config(app): "+app 
  try 
    appconfig = app = JSON.parse app
  catch err
    console.log "error parsing app config: #{err.message}: #{app} - #{err.stack}"
    working.error 'Sorry, could not load initial information - please try reloading this app'<commit_msg>fix issue #24 offline app list items appear in random order<commit_after># offline app - for App

appcache = require 'appcache'
templateApp = require 'templates/App'
HomeView = require 'views/Home'
CacheStateWidgetView = require 'views/CacheStateWidget'
FormUploadWidgetView = require 'views/FormUploadWidget'
LocationWidgetView = require 'views/LocationWidget'

BookletView = require 'views/Booklet'
ThingView = require 'views/Thing'
PlaceView = require 'views/Place'
HtmlView = require 'views/Html'
ListView = require 'views/List'
FormView = require 'views/Form'
UserView = require 'views/User'

ThingListView = require 'views/ThingList'
FormUploadView = require 'views/FormUpload'
AboutView = require 'views/About'
ShareView = require 'views/Share'
LocationView = require 'views/Location'

localdb = require 'localdb'
formdb = require 'formdb'
working = require 'working'
location = require 'location'

#config = window.mediahubconfig

appid = null
dburl = null
appconfig = null

appmodel = new Backbone.Model {}

items = {}
currentView = null

topLevelThings = new Backbone.Collection()

class Router extends Backbone.Router
  routes: 
    "" : "entries"
    "#" : "entries"
    "thing/:id": "thing"
    "booklet/:id/:page": "bookletPage"
    "booklet/:id/:page/": "bookletPage"
    "booklet/:id/:page/:anchor": "bookletPage"
    "upload": "upload"
    "user": "user"
    "about": "about"
    "share": "share"
    "location": "location"

  removeCurrentView: ->
    if currentView?
      try 
        currentView.remove()
      catch err
        console.log "error removing current view: #{err.message}"
      currentView = null

  setCurrentView: (view) ->
    @removeCurrentView()
    currentView = view
    $('#page-content-holder').empty()
    if not view.el
      console.log "Error: new current view has no element - trying to render"
      view.render()
    $('#page-content-holder').append view.el
    if view.title
      $('#app-title').html view.title
    else if view.model?.attributes?.title
      $('#app-title').html view.model.attributes.title
    else if HomeView.prototype.isPrototypeOf view
      $('#app-title').html appconfig?.title ? 'Home'
    else
      $('#app-title').html 'Home'

  upload: () ->
    console.log "show upload"
    @setCurrentView new FormUploadView model: formdb.getFormUploadState()
    true

  entries: ->
    console.log "router: entries"
    @setCurrentView new HomeView model: topLevelThings, id: ''
    true

  thing: (id) ->
    console.log "show thing #{id}"
    thing = items[id]
    if not thing?
      alert "Sorry, could not find thing #{id}"
      @navigate '#', { trigger:true, replace:true }
      return false
    
    if thing.attributes.type=='booklet'
      view = new BookletView model: thing
    else if thing.attributes.type=='place'
      view = new PlaceView model: thing
    else if thing.attributes.type=='html'
      view = new HtmlView model: thing
    else if thing.attributes.type=='form'
      view = new FormView model: thing
    else if thing.attributes.type=='list'
      view = new ListView model: thing
    else if thing.attributes.type?
      view = new ThingView model: thing
    else
      alert "Sorry, not sure how to display #{id}"
      @navigate '#', { trigger:true, replace:true }
      return false
 
    @setCurrentView view
    true

  bookletPage: (id,page,anchor) ->
    if not currentView? or currentView.model.id != id
      if not @thing id
        return
    currentView.showPage page,anchor

  user: () ->
    @setCurrentView new UserView model: (require 'user').getUser()

  about: () ->
    @setCurrentView new AboutView model: appmodel

  share: () ->
    @setCurrentView new ShareView model: appmodel

  location: () ->
    @setCurrentView new LocationView model: location.getLocation()

makeThing = (data, collection, thingIds) ->
  try
    thing = new Backbone.Model data
    if thing.id
      items[thing.id] = thing
      # add in order of thingIds
      tix = thingIds.indexOf thing.id
      ix = 0
      for tid,i in thingIds when i<tix and ix<collection.length
        if (collection.at ix).id == tid
          ix++
      collection.add thing, at:ix
    if data.thingIds?
      console.log "create new thing collection for #{thing.id}"
      thing.things = new Backbone.Collection()
      loadThings data,thing.things
  catch err
    console.log "error making thing: #{err.message}: #{data}\n#{err.stack}"

checkThing = (data,collection,thingIds) ->
  #if instanceid isnt localdb.currentInstanceid()
  #  console.log "Ignore item on load; old instanceid #{instanceid} vs #{localdb.currentInstanceid()}"
  #  return
  try 
    data = JSON.parse data
    if data.type?
      makeThing data, collection, thingIds
    else
      console.log "unknown item type #{data.type} - ignored"
  catch err
    console.log "error parsing thing: #{err.message}: #{data}"

loadThing = (thingId,collection,thingIds) ->
  console.log "load thing #{thingId}"
  $.ajax dburl+"/"+encodeURIComponent(thingId),
    success: (data)->
      checkThing data, collection, thingIds
    dataType: "text"
    error: (xhr,status,err) ->
      console.log "get thing error "+xhr.status+": "+err.message
      # on android (at least) files from cache sometimes have status 0!!
      if xhr.status==0 && xhr.responseText
        checkThing xhr.responseText, collection, thingIds

loadThings = (app,collection) ->
  for thingId in app.thingIds
    # id, url, type
    loadThing thingId,collection,app.thingIds
  working.done()

checkConfig = (app) ->
  console.log  "config(app): "+app 
  try 
    appconfig = app = JSON.parse app
  catch err
    console.log "error parsing app config: #{err.message}: #{app} - #{err.stack}"
    working.error 'Sorry, could not load initial information - please try reloading this app'
{'fraction_non_alphanumeric': 0.12132516209254818, 'fraction_numerical': 0.0006217248423483436, 'mean_word_length': 3.2410546139359697, 'pattern_counts': {'":': 20, '<': 5, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1318754', 'n_tokens_mistral': 3426, 'n_tokens_neox': 3388, 'n_words': 995}