site/js/docurium.js in docurium-0.2.2 vs site/js/docurium.js in docurium-0.3.0

- old
+ new

@@ -1,697 +1,690 @@ $(function() { - // our document model - stores the datastructure generated from docurium - var Docurium = Backbone.Model.extend({ - - defaults: {'version': 'unknown'}, - + var FileListModel = Backbone.Model.extend({ initialize: function() { - this.loadVersions() + var docurium = this.get('docurium') + this.listenTo(docurium, 'change:data', this.extract) }, - loadVersions: function() { - $.getJSON("project.json", function(data) { - docurium.set({'versions': data.versions, 'github': data.github, 'signatures': data.signatures, 'name': data.name, 'groups': data.groups}) - if(data.name) { - $('#site-title').text(data.name + ' API') - document.title = data.name + ' API' - } - docurium.setVersionPicker() - docurium.setVersion() + extract: function() { + var docurium = this.get('docurium') + var data = docurium.get('data') + var version = docurium.get('version') + + // Function groups + var funs = _.map(data['groups'], function(group, i) { + var name = group[0] + var link = groupLink(name, version) + return {name: name, link: link, num: group[1].length} }) - }, - setVersionPicker: function () { - vers = docurium.get('versions') - $('#version-list').empty().hide() - for(var i in vers) { - version = vers[i] - vlink = $('<a>').attr('href', '#' + version).append(version).click( function() { - $('#version-list').hide(100) - }) - $('#version-list').append($('<li>').append(vlink)) + // Types + var getName = function(type) { + var name = type[0]; + var link = typeLink(name, version); + return {link: link, name: name}; } - vlink = $('<a>').attr('href', '#' + 'p/changelog').append("Changelog").click ( function () { - $('#version-list').hide(100) - }) - $('#version-list').append($('<li>').append(vlink)) - }, - setVersion: function (version) { - if(!version) { - version = _.first(docurium.get('versions')) + var enums = _.filter(data['types'], function(type) { + return type[1]['block'] && type[1]['type'] == 'enum'; + }).map(getName) + + var structs = _.filter(data['types'], function(type) { + return type[1]['block'] && type[1]['type'] != 'enum' + }).map(getName) + + var opaques = _.filter(data['types'], function(type) { + return !type[1]['block'] + }).map(getName) + + // File Listing + var files = _.map(data['files'], function(file) { + var url = this.github_file(file['file']) + return {url: url, name: file['file']} + }, docurium) + + // Examples List + var examples = [] + if(data['examples'] && (data['examples'].length > 0)) { + examples = _.map(data['examples'], function(file) { + return {name: file[0], path: file[1]} + }) } - if(docurium.get('version') != version) { - docurium.set({'version': version}) - $('#site-title').attr('href', '#' + version) - docurium.loadDoc() - } - }, - loadDoc: function() { - version = this.get('version') - $.ajax({ - url: version + '.json', - context: this, - dataType: 'json', - success: function(data){ - this.set({'data': data}) - Backbone.history.start() - } - }) + this.set('data', {funs: funs, enums: enums, structs: structs, opaques: opaques, + files: files, examples: examples}) }, + }) - collapseSection: function(data) { - $(this).next().toggle(100) - return false - }, + var FileListView = Backbone.View.extend({ + el: $('#files-list'), - showIndexPage: function(replace) { - version = docurium.get('version') - ws.navigate(version, {replace: replace}) + template: _.template($('#file-list-template').html()), - data = docurium.get('data') - content = $('.content') - content.empty() + typeTemplate: _.template($('#type-list-template').html()), - content.append($('<h1>').append("Public API Functions")) + events: { + 'click h3': 'toggleList', + }, - sigHist = docurium.get('signatures') - - // Function Groups - for (var i in data['groups']) { - group = data['groups'][i] - content.append($('<h2>').addClass('funcGroup').append(group[0])) - list = $('<p>').addClass('functionList') - for(var j in group[1]) { - fun = group[1][j] - link = $('<a>').attr('href', '#' + groupLink(group[0], fun)).append(fun) - if(sigHist[fun].changes[version]) { - link.addClass('changed') - } - if(version == _.first(sigHist[fun].exists)) { - link.addClass('introd') - } - list.append(link) - if(j < group[1].length - 1) { - list.append(', ') - } - } - content.append(list) - } + toggleList: function(e) { + $(e.currentTarget).next().toggle(100) + return false }, - getGroup: function(gname) { - var groups = docurium.get('data')['groups'] - for(var i in groups) { - if(groups[i][0] == gname) { - return groups[i] - } - } + initialize: function() { + this.listenTo(this.model, 'change:data', this.render) }, - showFun: function(gname, fname) { - group = docurium.getGroup(gname) + render: function() { + var data = this.model.get('data') - fdata = docurium.get('data')['functions'] - gname = group[0] - functions = group[1] + var enumList = this.typeTemplate({title: 'Enums', elements: data.enums}) + var structList = this.typeTemplate({title: 'Structs', elements: data.structs}) + var opaquesList = this.typeTemplate({title: 'Opaque Structs', elements: data.opaques}) + var menu = $(this.template({funs: data.funs, files: data.files, examples: data.examples})) - document.body.scrollTop = document.documentElement.scrollTop = 0; - content = $('.content') - content.empty() + $('#types-list', menu).append(enumList, structList, opaquesList) - // Show Function Name - content.append($('<h1>').addClass('funcTitle').append(fname)) - if(fdata[fname]['description']) { - sub = content.append($('<h3>').addClass('funcDesc').append( ' ' + fdata[fname]['description'] )) - } + this.$el.html(menu) + return this + }, + }) - // Show Function Arguments - argtable = $('<table>').addClass('funcTable') - args = fdata[fname]['args'] - for(var i=0; i<args.length; i++) { - arg = args[i] - row = $('<tr>') - row.append($('<td>').attr('valign', 'top').attr('nowrap', true).append(this.hotLink(arg.type))) - row.append($('<td>').attr('valign', 'top').addClass('var').append(arg.name)) - row.append($('<td>').addClass('comment').append(arg.comment)) - argtable.append(row) - } - content.append(argtable) + var VersionView = Backbone.View.extend({ + el: $('#version'), - // Show Function Return Value - retdiv = $('<div>').addClass('returns') - retdiv.append($('<h3>').append("returns")) - rettable = $('<table>').addClass('funcTable') - retrow = $('<tr>') - rettable.append(retrow) - retdiv.append(rettable) + initialize: function() { + this.listenTo(this.model, 'change:version', this.render) + this.listenTo(this.model, 'change:name', this.renderName) + this.title = $('#site-title') + }, - ret = fdata[fname]['return'] - retrow.append($('<td>').attr('valign', 'top').append(this.hotLink(ret.type))) - if(ret.comment) { - retrow.append($('<td>').addClass('comment').append(ret.comment)) - } - content.append(retdiv) + render: function() { + var version = this.model.get('version') + this.$el.text(version) + this.title.attr('href', '#' + version) + return this + }, - // Show Non-Parsed Function Comments - if (fdata[fname]['comments']) - content.append($('<div>').append(fdata[fname]['comments'])) + renderName: function() { + var name = this.model.get('name') + var title = name + ' API' + this.title.text(title) + document.title = title + return this + }, + }) - // Show Function Signature - ex = $('<code>').addClass('params') - ex.append(this.hotLink(fdata[fname]['return']['type'] + ' ' + fname + '(' + fdata[fname]['argline'] + ');')) - example = $('<div>').addClass('example') - example.append($('<h3>').append("signature")) - example.append(ex) - content.append(example) + var VersionPickerView = Backbone.View.extend({ + el: $('#versions'), - // Show Function History - sigs = $('<div>').addClass('signatures') - sigs.append($('<h3>').append("versions")) - sigHist = docurium.get('signatures')[fname] - var list = $('<ul>') - for(var i in sigHist.exists) { - ver = sigHist.exists[i] - link = $('<a>').attr('href', '#' + groupLink(gname, fname, ver)).append(ver) - if(sigHist.changes[ver]) { - link.addClass('changed') - } - if(ver == docurium.get('version')) { - link.addClass('current') - } - list.append($('<li>').append(link)) - } - sigs.append(list) - content.append(sigs) + list: $('#version-list'), - // Link to Function Def on GitHub - link = this.github_file(fdata[fname].file, fdata[fname].line, fdata[fname].lineto) - flink = $('<a>').attr('target', 'github').attr('href', link).append(fdata[fname].file) - content.append($('<div>').addClass('fileLink').append("Defined in: ").append(flink)) + template: _.template($('#version-picker-template').html()), - // Show where this is used in the examples - if(ex = fdata[fname].examples) { - also = $('<div>').addClass('funcEx') - also.append("Used in examples: ") - for( fname in ex ) { - lines = ex[fname] - line = $('<li>') - line.append($('<strong>').append(fname)) - for( var i in lines ) { - flink = $('<a>').attr('href', lines[i]).append(' [' + (parseInt(i) + 1) + '] ') - line.append(flink) - } - also.append(line) - } - content.append(also) - } + initialize: function() { + this.listenTo(this.model, 'change:versions', this.render) + }, - // Show other functions in this group - also = $('<div>').addClass('also') - flink = $('<a href="#' + docurium.get('version') + '/group/' + group[0] + '">' + group[0] + '</a>') - flink.click( docurium.showGroup ) - also.append("Also in ") - also.append(flink) - also.append(" group: <br/>") + events: { + 'click #version-picker': 'toggleList', + 'click': 'hideList', + }, - for(i=0; i<functions.length; i++) { - f = functions[i] - d = fdata[f] - link = $('<a>').attr('href', '#' + groupLink(gname, f)).append(f) - also.append(link) - also.append(', ') - } - content.append(also) + hideList: function() { + this.list.hide(100) + }, + toggleList: function(e) { + $(e.currentTarget).next().toggle(100) + return false + }, - this.addHotlinks() + render: function() { + var vers = this.model.get('versions') + list = this.template({versions: vers}) + this.list.html(list) + return this }, + }) - showChangeLog: function() { - content = $('.content') - content.empty() - content.append($('<h1>').append("Function Changelog")) + var ChangelogView = Backbone.View.extend({ + template: _.template($('#changelog-template').html()), + + itemTemplate: _.template($('#changelog-item-template').html()), + + initialize: function() { // for every version, show which functions added, removed, changed - from HEAD down - versions = docurium.get('versions') - sigHist = docurium.get('signatures') + var versions = this.model.get('versions') + var sigHist = this.model.get('signatures') - lastVer = _.first(versions) + var lastVer = _.first(versions) // fill changelog struct - changelog = {} + var changelog = {} for(var i in versions) { - version = versions[i] + var version = versions[i] changelog[version] = {'deletes': [], 'changes': [], 'adds': []} } // figure out the adds, deletes and changes - for(var func in sigHist) { - lastv = _.last(sigHist[func].exists) - firstv = _.first(sigHist[func].exists) - if (func != '__attribute__') { - changelog[firstv]['adds'].push(func) - } - if(lastv && (lastv != lastVer)) { - vi = _.indexOf(versions, lastv) - delv = versions[vi - 1] - changelog[delv]['deletes'].push(func) - } - for(var v in sigHist[func].changes) { - changelog[v]['changes'].push(func) - } - } + _.forEach(sigHist, function(func, fname) { + var lastv = _.last(func.exists) + var firstv = _.first(func.exists) + changelog[firstv]['adds'].push(fname) - // display the data - for(var i in versions) { - version = versions[i] - content.append($('<h3>').append(version)) - cl = $('<div>').addClass('changelog') + // figure out where it was deleted or changed + if (lastv && (lastv != lastVer)) { + var vi = _.indexOf(versions,lastv) + var delv = versions[vi-1] + changelog[delv]['deletes'].push(fname) - console.log(version) + _.forEach(func.changes, function(_, v) { + changelog[v]['changes'].push(fname) + }) + } + }) - for(var type in changelog[version]) { - adds = changelog[version][type] - adds.sort() - addsection = $('<p>') - for(var j in adds) { - add = adds[j] - if(type != 'deletes') { - gname = docurium.groupOf(add) - addlink = $('<a>').attr('href', '#' + groupLink(gname, add, version)).append(add) - } else { - addlink = add - } - addsection.append($('<li>').addClass(type).append(addlink)) - } - cl.append(addsection) - } - content.append(cl) - } + var vers = _.map(versions, function(version) { + var deletes = changelog[version]['deletes'] + deletes.sort() + + var additions = changelog[version]['adds'] + additions.sort() + var adds = _.map(additions, function(add) { + var gname = this.model.groupOf(add) + return {link: functionLink(gname, add, version), text: add} + }, this) + + return {title: version, listing: this.itemTemplate({dels: deletes, adds: adds})} + }, this) + + this.el = this.template({versions: vers}) }, - showType: function(data, manual) { - if(manual) { - id = '#typeItem' + domSafe(manual) - ref = parseInt($(id).attr('ref')) - } else { - ref = parseInt($(this).attr('ref')) - } - tdata = docurium.get('data')['types'][ref] - tname = tdata[0] - data = tdata[1] + render: function() { + return this + } + }) - ws.navigate(typeLink(tname)) - document.body.scrollTop = document.documentElement.scrollTop = 0; + var FunctionModel = Backbone.Model.extend({ + initialize: function() { + var gname = this.get('gname') + var fname = this.get('fname') + var docurium = this.get('docurium') - content = $('.content') - content.empty() - content.append($('<h1>').addClass('funcTitle').append(tname).append($("<small>").append(data.type))) + var group = docurium.getGroup(gname) - content.append($('<p>').append(data.value)) + var fdata = docurium.get('data')['functions'] + var functions = group[1] - if(data.comments) { - content.append($('<div>').append(data.comments)) - } + // Function Arguments + var args = _.map(fdata[fname]['args'], function(arg) { + return {link: this.hotLink(arg.type), name: arg.name, comment: arg.comment} + }, docurium) - if(data.block) { - content.append($('<pre>').append(data.block)) - } + var data = fdata[fname] + // function return value + var ret = data['return'] + var returns = {link: docurium.hotLink(ret.type), comment: ret.comment} + // function signature + var sig = docurium.hotLink(ret.type) + ' ' + fname + '(' + data['argline'] + ');' + // version history + var sigHist = docurium.get('signatures')[fname] + var version = docurium.get('version') + var sigs = _.map(sigHist.exists, function(ver) { + var klass = [] + if (sigHist.changes[ver]) + klass.push('changed') + if (ver == version) + klass.push('current') - var ret = data.used.returns - if (ret.length > 0) { - content.append($('<h3>').append('Returns')) - } - for(var i=0; i<ret.length; i++) { - gname = docurium.groupOf(ret[i]) - flink = $('<a>').attr('href', '#' + groupLink(gname, ret[i])).append(ret[i]) - flink.click( docurium.showFun ) - content.append(flink) - content.append(', ') - } + return {url: '#' + functionLink(gname, fname, ver), name: ver, klass: klass.join(' ')} + }) + // GitHub link + var fileLink = docurium.github_file(data.file, data.line, data.lineto) + // link to the group + var version = docurium.get('version') + var alsoGroup = '#' + groupLink(group[0], version) + var alsoLinks = _.map(functions, function(f) { + return {url: '#' + functionLink(gname, f, version), name: f} + }) - var needs = data.used.needs - if (needs.length > 0) { - content.append($('<h3>').append('Argument In')) - } - for(var i=0; i<needs.length; i++) { - gname = docurium.groupOf(needs[i]) - flink = $('<a>').attr('href', '#' + groupLink(gname, needs[i])).append(needs[i]) - flink.click( docurium.showFun ) - content.append(flink) - content.append(', ') - } + this.set('data', {name: fname, data: data, args: args, returns: returns, sig: sig, + sigs: sigs, fileLink: fileLink, groupName: gname, + alsoGroup: alsoGroup, alsoLinks: alsoLinks}) + } + }) - link = docurium.github_file(data.file, data.line, data.lineto) - flink = $('<a>').attr('target', 'github').attr('href', link).append(data.file) - content.append($('<div>').addClass('fileLink').append("Defined in: ").append(flink)) + var FunctionView = Backbone.View.extend({ + template: _.template($('#function-template').html()), + argsTemplate: _.template($('#function-args-template').html()), - return false + render: function() { + document.body.scrollTop = document.documentElement.scrollTop = 0; + var data = this.model.get('data') + data.argsTemplate = this.argsTemplate + var cont = this.template(data) + + this.el = cont + return this }, + }) - showGroup: function(data, manual, flink) { - if(manual) { - id = '#groupItem' + manual - ref = parseInt($(id).attr('ref')) - } else { - ref = parseInt($(this).attr('ref')) - } - group = docurium.get('data')['groups'][ref] - fdata = docurium.get('data')['functions'] - gname = group[0] + var GroupCollection = Backbone.Collection.extend({ + initialize: function(o) { + this.docurium = o.docurium + this.listenTo(this.docurium, 'change:data', this.refill) + }, - ws.navigate(groupLink(gname)); - document.body.scrollTop = document.documentElement.scrollTop = 0; + refill: function(o, doc) { + var data = o.changed.data + var sigHist = this.docurium.get('signatures') + var version = this.docurium.get('version') - functions = group[1] - $('.content').empty() - $('.content').append($('<h1>').append(gname + ' functions')) + var groups = _.map(data.groups, function(group) { + var gname = group[0] + var funs = _.map(group[1], function(fun) { + var klass = '' + if (sigHist[fun].changes[version]) + klass = 'changed' - table = $('<table>').addClass('methods') - for(i=0; i<functions.length; i++) { - f = functions[i] - d = fdata[f] - row = $('<tr>') - row.append($('<td>').attr('nowrap', true).attr('valign', 'top').append(d['return']['type'].substring(0, 20))) - link = $('<a>').attr('href', '#' + groupLink(gname, f)).append(f) - row.append($('<td>').attr('valign', 'top').addClass('methodName').append( link )) - args = d['args'] - argtd = $('<td>') - for(j=0; j<args.length; j++) { - argtd.append(args[j].type + ' ' + args[j].name) - argtd.append($('<br>')) - } - row.append(argtd) - table.append(row) - } - $('.content').append(table) + if (version == _.first(sigHist[fun].exists)) + klass = 'introd' - for(var i=0; i<functions.length; i++) { - f = functions[i] - argsText = '( ' + fdata[f]['argline'] + ' )' - link = $('<a>').attr('href', '#' + groupLink(gname, f)).append(f) - $('.content').append($('<h2>').append(link).append($('<small>').append(argsText))) - description = fdata[f]['description'] - if(fdata[f]['comments']) - description += "\n\n" + fdata[f]['comments'] + return {name: fun, url: '#' + functionLink(gname, fun, version), klass: klass} + }) + return {name: gname, funs: funs} + }) - $('.content').append($('<div>').addClass('description').append(description)) - } - return false + this.reset(groups) }, + }) - // look for structs and link them - hotLink: function(text) { - types = this.get('data')['types'] - for(var i=0; i<types.length; i++) { - type = types[i] - typeName = type[0] - typeData = type[1] - re = new RegExp(typeName + ' ', 'gi'); - link = '<a ref="' + i.toString() + '" class="typeLink' + domSafe(typeName) + '" href="#">' + typeName + '</a> ' - text = text.replace(re, link) - } - return text + var MainListView = Backbone.View.extend({ + template: _.template($('#index-template').html()), + + initialize: function() { + this.listenTo(this.collection, 'reset', this.render) }, - groupOf: function (func) { - return this.get('groups')[func] + render: function() { + this.el = this.template({groups: this.collection.toJSON()}) + this.trigger('redraw') + return this }, + }) - addHotlinks: function() { - types = this.get('data')['types'] - for(var i=0; i<types.length; i++) { - type = types[i] - typeName = type[0] - className = '.typeLink' + domSafe(typeName) - $(className).click( this.showType ) + var TypeModel = Backbone.Model.extend({ + initialize: function() { + var typename = this.get('typename') + var docurium = this.get('docurium') + var version = docurium.get('version') + var types = docurium.get('data')['types'] + var tdata = _.find(types, function(g) { + return g[0] == typename + }) + var tname = tdata[0] + var data = tdata[1] + + var toPair = function(fun) { + var gname = this.groupOf(fun) + var url = '#' + functionLink(gname, fun, version) + return {name: fun, url: url} } - }, - refreshView: function() { - data = this.get('data') + var returns = _.map(data.used.returns, toPair, docurium) + var needs = _.map(data.used.needs, toPair, docurium) + var fileLink = {name: data.file, url: docurium.github_file(data.file, data.line, data.lineto)} - // Function Groups - menu = $('<li>') - title = $('<h3><a href="#">Functions</a></h3>').click( this.collapseSection ) - menu.append(title) - list = $('<ul>') - _.each(data['groups'], function(group, i) { - flink = $('<a href="#" ref="' + i.toString() + '" id="groupItem' + group[0] + '">' + group[0] + ' &nbsp;<small>(' + group[1].length + ')</small></a>') - flink.click( this.showGroup ) - fitem = $('<li>') - fitem.append(flink) - list.append(fitem) - }, this) - menu.append(list) + this.set('data', {tname: tname, data: data, returns: returns, needs: needs, fileLink: fileLink}) + } + }) - // Types - title = $('<h3><a href="#">Types</a></h3>').click( this.collapseSection ) - menu.append(title) - list = $('<ul>') + var TypeView = Backbone.View.extend({ + template: _.template($('#type-template').html()), - fitem = $('<li>') - fitem.append($('<span>').addClass('divide').append("Enums")) - list.append(fitem) + render: function() { + var content = this.template(this.model.get('data')) + this.el = content + return this + } + }) - _.each(data['types'], function(group, i) { - if(group[1]['block'] && group[1]['type'] == 'enum') { - flink = $('<a href="#" ref="' + i.toString() + '" id="typeItem' + domSafe(group[0]) + '">' + group[0] + '</a>') - flink.click( this.showType ) - fitem = $('<li>') - fitem.append(flink) - list.append(fitem) - } - }, this) + var GroupView = Backbone.View.extend({ + template: _.template($('#group-template').html()), - fitem = $('<li>') - fitem.append($('<span>').addClass('divide').append("Structs")) - list.append(fitem) + initialize: function(o) { + var group = o.group + var gname = group[0] + var fdata = o.functions + var version = o.version - _.each(data['types'], function(group, i) { - if(group[1]['block'] && group[1]['type'] != 'enum') { - flink = $('<a href="#" ref="' + i.toString() + '" id="typeItem' + domSafe(group[0]) + '">' + group[0] + '</a>') - flink.click( this.showType ) - fitem = $('<li>') - fitem.append(flink) - list.append(fitem) - } - }, this) + this.functions = _.map(group[1], function(name) { + var url = '#' + functionLink(gname, name, version) + var d = fdata[name] + return {name: name, url: url, returns: d['return']['type'], argline: d['argline'], + description: d['description'], comments: d['comments'], args: d['args']} + }) + }, - fitem = $('<li>') - fitem.append($('<span>').addClass('divide').append("Opaque Structs")) - list.append(fitem) + render: function() { + var content = this.template({gname: this.gname, functions: this.functions}) - _.each(data['types'], function(group, i) { - if(!group[1]['block']) { - flink = $('<a href="#" ref="' + i.toString() + '" id="typeItem' + domSafe(group[0]) + '">' + group[0] + '</a>') - flink.click( this.showType ) - fitem = $('<li>') - fitem.append(flink) - list.append(fitem) - } - }, this) - list.hide() - menu.append(list) + this.el = content + return this + }, + }) - // File Listing - title = $('<h3><a href="#">Files</a></h3>').click( this.collapseSection ) - menu.append(title) - filelist = $('<ul>') - _.each(data['files'], function(file) { - url = this.github_file(file['file']) - flink = $('<a target="github" href="' + url + '">' + file['file'] + '</a>') - fitem = $('<li>') - fitem.append(flink) - filelist.append(fitem) - }, this) - filelist.hide() - menu.append(filelist) + var SearchFieldView = Backbone.View.extend({ + tagName: 'input', - // Examples List - if(data['examples'] && (data['examples'].length > 0)) { - title = $('<h3><a href="#">Examples</a></h3>').click( this.collapseSection ) - menu.append(title) - filelist = $('<ul>') - _.each(data['examples'], function(file) { - fname = file[0] - fpath = file[1] - flink = $('<a>').attr('href', fpath).append(fname) - fitem = $('<li>') - fitem.append(flink) - filelist.append(fitem) - }, this) - menu.append(filelist) - } + el: $('#search-field'), - list = $('#files-list') - list.empty() - list.append(menu) + events: { + 'keyup': function() { + this.trigger('keyup') + if (this.$el.val() == '') + this.trigger('empty') + } }, + }) - github_file: function(file, line, lineto) { - url = "https://github.com/" + docurium.get('github') - url += "/blob/" + docurium.get('version') + '/' + data.prefix + '/' + file - if(line) { - url += '#L' + line.toString() - if(lineto) { - url += '-' + lineto.toString() - } - } else { - url += '#files' - } - return url + var SearchCollection = Backbone.Collection.extend({ + defaults: { + value: '', }, - search: function(data) { - var searchResults = [] - var value = $('#search-field').val() + initialize: function(o) { + this.field = o.field + this.docurium = o.docurium - if (value.length < 3) { - docurium.showIndexPage(false) - return - } + this.listenTo(this.field, 'keyup', this.keyup) + }, - this.searchResults = [] + keyup: function() { + var newValue = this.field.$el.val() + if (this.value == newValue || newValue.length < 3) + return - ws.navigate(searchLink(value)) + this.value = newValue + this.refreshSearch() + }, - data = docurium.get('data') + refreshSearch: function() { + var docurium = this.docurium + var value = this.value + var data = docurium.get('data') + var searchResults = [] + + var version = docurium.get('version') // look for functions (name, comment, argline) - for (var name in data.functions) { - f = data.functions[name] + _.forEach(data.functions, function(f, name) { + var gname = docurium.groupOf(name) + // look in the function name first if (name.search(value) > -1) { - gname = docurium.groupOf(name) - var flink = $('<a>').attr('href', '#' + groupLink(gname, name)).append(name) - searchResults.push(['fun-' + name, flink, 'function']) + var gl = functionLink(gname, name, version) + var url = '#' + gl + searchResults.push({url: url, name: name, match: 'function', navigate: gl}) + return } - if (f.argline) { - if (f.argline.search(value) > -1) { - gname = docurium.groupOf(name) - var flink = $('<a>').attr('href', '#' + groupLink(gname, name)).append(name) - searchResults.push(['fun-' + name, flink, f.argline]) - } + + // if we didn't find it there, let's look in the argline + if (f.argline && f.argline.search(value) > -1) { + var gl = functionLink(gname, name, version) + var url = '#' + gl + searchResults.push({url: url, name: name, match: f.argline, navigate: gl}) } - } - for (var i in data.types) { - var type = data.types[i] - name = type[0] + }) + + // look for types + data.types.forEach(function(type) { + var name = type[0] + var tl = typeLink(name, version) + var url = '#' + tl if (name.search(value) > -1) { - var link = $('<a>').attr('href', '#' + typeLink(name)).append(name) - searchResults.push(['type-' + name, link, type[1].type]) + searchResults.push({url: url, name: name, match: type[1].type, navigate: tl}) } + }) + + this.reset(searchResults) + }, + }) + + var SearchView = Backbone.View.extend({ + template: _.template($('#search-template').html()), + + // initialize: function() { + // this.listenTo(this.model, 'reset', this.render) + // }, + + render: function() { + var content = this.template({results: this.collection.toJSON()}) + this.el = content + } + }) + + var MainView = Backbone.View.extend({ + el: $('#content'), + + setActive: function(view) { + view.render() + + if (this.activeView) { + this.stopListening() + this.activeView.remove() } - // look for types - // look for files - content = $('.content') - content.empty() + this.activeView = view + // make sure we know when the view wants to render again + this.listenTo(view, 'redraw', this.render) - content.append($('<h1>').append("Search Results")) - table = $("<table>") - var shown = {} - for (var i in searchResults) { - row = $("<tr>") - result = searchResults[i] - if (!shown[result[0]]) { - link = result[1] - match = result[2] - row.append($('<td>').append(link)) - row.append($('<td>').append(match)) - table.append(row) - shown[result[0]] = true - } + this.$el.html(view.el) + + // move back to the top when we switch views + document.body.scrollTop = document.documentElement.scrollTop = 0; + }, + + render: function() { + this.$el.html(this.activeView.el) + }, + }) + + // our document model - stores the datastructure generated from docurium + var Docurium = Backbone.Model.extend({ + + defaults: {'version': 'unknown'}, + + initialize: function() { + this.loadVersions() + this.bind('change:version', this.loadDoc) + }, + + loadVersions: function() { + $.getJSON("project.json").then(function(data) { + docurium.set({'versions': data.versions, 'github': data.github, 'signatures': data.signatures, 'name': data.name, 'groups': data.groups}) + docurium.setVersion() + }) + }, + + setVersion: function (version) { + if(!version) { + version = _.first(docurium.get('versions')) } - content.append(table) + docurium.set({version: version}) + }, - } + loadDoc: function() { + version = this.get('version') + $.getJSON(version + '.json').then(function(data) { + docurium.set({data: data}) + }) + }, + getGroup: function(gname) { + var groups = docurium.get('data')['groups'] + return _.find(groups, function(g) { + return g[0] == gname + }) + }, + + // look for structs and link them + hotLink: function(text) { + types = this.get('data')['types'] + var version = this.get('version') + for(var i=0; i<types.length; i++) { + type = types[i] + typeName = type[0] + typeData = type[1] + re = new RegExp(typeName + ' ', 'gi'); + var link = $('<a>').attr('href', '#' + typeLink(typeName, version)).append(typeName)[0] + text = text.replace(re, link.outerHTML + ' ') + } + return text + }, + + groupOf: function (func) { + return this.get('groups')[func] + }, + + github_file: function(file, line, lineto) { + var data = this.get('data') + url = ['https://github.com', docurium.get('github'), + 'blob', docurium.get('version'), data.prefix, file].join('/') + if(line) { + url += '#L' + line.toString() + if(lineto) { + url += '-' + lineto.toString() + } + } else { + url += '#files' + } + + return url + }, }) var Workspace = Backbone.Router.extend({ routes: { - "": "main", + "": "index", ":version": "main", ":version/group/:group": "group", ":version/type/:type": "showtype", ":version/group/:group/:func": "groupFun", ":version/search/:query": "search", "p/changelog": "changelog", }, + initialize: function(o) { + this.doc = o.docurium + this.search = o.search + this.mainView = o.mainView + this.groups = o.groups + }, + + index: function() { + // set the default version + this.doc.setVersion() + // and replate our URL with it, to avoid a back-button loop + this.navigate(this.doc.get('version'), {replace: true, trigger: true}) + }, + main: function(version) { - docurium.setVersion(version) - // when asking for '/', replace with 'HEAD' instead of redirecting - var replace = version == undefined - docurium.showIndexPage(replace) + this.doc.setVersion(version) + var view = new MainListView({collection: this.groups}) + this.mainView.setActive(view) }, group: function(version, gname) { - docurium.setVersion(version) - docurium.showGroup(null, gname) + this.doc.setVersion(version) + var group = this.doc.getGroup(gname) + var fdata = this.doc.get('data')['functions'] + var version = this.doc.get('version') + var view = new GroupView({group: group, functions: fdata, version: version}) + this.mainView.setActive(view) }, groupFun: function(version, gname, fname) { - docurium.setVersion(version) - docurium.showFun(gname, fname) + this.doc.setVersion(version) + var model = new FunctionModel({docurium: this.doc, gname: gname, fname: fname}) + var view = new FunctionView({model: model}) + this.mainView.setActive(view) }, showtype: function(version, tname) { - docurium.setVersion(version) - docurium.showType(null, tname) + this.doc.setVersion(version) + var model = new TypeModel({docurium: this.doc, typename: tname}) + var view = new TypeView({model: model}) + this.mainView.setActive(view) }, search: function(version, query) { - docurium.setVersion(version) - $('#search-field').val(query) - docurium.search() + this.doc.setVersion(version) + var view = new SearchView({collection: this.search}) + $('#search-field').val(query).keyup() + this.mainView.setActive(view) }, changelog: function(version, tname) { - docurium.setVersion() - docurium.showChangeLog() + // let's wait to process it until it's asked, and let's only do + // it once + if (this.changelogView == undefined) { + this.changelogView = new ChangelogView({model: this.doc}) + } + this.doc.setVersion() + this.mainView.setActive(this.ChangelogView) }, - }); - function groupLink(gname, fname, version) { - if(!version) { - version = docurium.get('version') - } - if(fname) { + function functionLink(gname, fname, version) { return version + "/group/" + gname + '/' + fname - } else { - return version + "/group/" + gname - } } - function typeLink(tname) { - return docurium.get('version') + "/type/" + tname + function groupLink(gname, version) { + return version + "/group/" + gname } - function searchLink(tname) { - return docurium.get('version') + "/search/" + tname + function typeLink(tname, version) { + return version + "/type/" + tname } - function domSafe(str) { - return str.replace('_', '-') + function searchLink(term, version) { + return version + "/search/" + term } - - window.docurium = new Docurium - window.ws = new Workspace + //_.templateSettings.variable = 'rc' - docurium.bind('change:version', function(model, version) { - $('#version').text(version) + var docurium = new Docurium + + var searchField = new SearchFieldView({id: 'search-field'}) + var searchCol = new SearchCollection({docurium: docurium, field: searchField}) + var groupCol = new GroupCollection({docurium: docurium}) + + var mainView = new MainView() + + var router = new Workspace({docurium: docurium, search: searchCol, mainView: mainView, + groups: groupCol}) + + searchField.on('empty', function() { + router.navigate(docurium.get('version'), {trigger: true}) }) - docurium.bind('change:data', function(model, data) { - model.refreshView() - }) - $('#search-field').keyup( docurium.search ) + docurium.once('change:data', function() {Backbone.history.start()}) - $('#version-picker').click( docurium.collapseSection ) + var fileList = new FileListModel({docurium: docurium}) + var fileListView = new FileListView({model: fileList}) + var versionView = new VersionView({model: docurium}) + var versionPickerView = new VersionPickerView({model: docurium}) + searchCol.on('reset', function(col, prev) { + if (col.length == 1) { + router.navigate(col.pluck('navigate')[0], {trigger: true, replace: true}) + } else { + var version = docurium.get('version') + // FIXME: this keeps recreating the view + router.navigate(searchLink(col.value, version), {trigger: true}) + } + }) })