orchid-0.0.6: viewer/js/app.js
/* ------------------------------------------------------------------------- */
$(document).ready(
function start ()
{
setupLoadingIcon()
installCollapsers()
installOptions()
installSmartFields()
installHandlers()
index()
setupBrowserHistory()
updateAuth()
}
)
function index ()
{
// When no document is requested using the resource hash, open the index
// document by default.
if (!document.location.hash)
document.location.hash = 'Index'
}
function setupBrowserHistory ()
{
// History changes are reflected using the parseURI/update functions.
$.history.init(
function historyChange (hash)
{
parseURI()
update()
}
)
}
function setupLoadingIcon ()
{
$("#loading").ajaxStart(
function ()
{
$(this).show();
}
);
$("#loading").ajaxStop(
function ()
{
$(this).hide();
}
);
}
function installHandlers ()
{
$('#history-btn').click(showHistory)
$('#edit-btn').click(showEditor)
$('#login-btn').click(login)
$('#logout-btn').click(logout)
$('#create-account-btn').click(signup)
$('#save-btn').click(save)
$('#preview-btn').click(preview)
$('#delete-btn').click(_delete)
}
/* ------------------------------------------------------------------------- */
// Current application state.
Wiki = {
// Static information.
prefix : 'data/'
, previewURI : 'data/preview'
, loginURI : 'login'
, logoutURI : 'logout'
, loginfoURI : 'loginfo'
, signupURI : 'signup'
, viewerURI : '#'
// State information.
, title : ''
, ext : 'html'
, rev : ''
, anchor : ''
, prevTitle : ''
, prevExt : ''
, prevRev : ''
, prevAnchor : ''
, author : ''
, user : ''
}
function parseURI ()
{
var hash = window.location.hash
var parse = hash.match(/^#([^?#]*)\??([^#]*)#?(.*)/)
var ext = parse[1].match(/\.([^.]*)$/)
var tit = parse[1].match(/(.*)\.([^.]*)$/)
Wiki.prevTitle = Wiki.title
Wiki.prevExt = Wiki.ext
Wiki.prevRev = Wiki.rev
Wiki.prevAnchor = Wiki.anchor
Wiki.title = tit ? tit[1] : parse[1]
Wiki.ext = ext ? ext[1] : 'html'
Wiki.rev = parse[2]
Wiki.anchor = parse[3]
}
function update ()
{
var t = 0
// Only refresh when one of these change.
if (Wiki.title != Wiki.prevTitle ||
Wiki.ext != Wiki.prevExt ||
Wiki.rev != Wiki.prevRev) {
// Update information bar.
$('#document').html(Wiki.title)
$('#revision').html(Wiki.rev || '<i>head revision</i>')
$('#user').html(Wiki.user)
show()
showHistory()
updateAuth()
// Anchor focus delay when refreshing.
t = 1000
}
if (Wiki.anchor)
setTimeout(
function ()
{
followAnchor(Wiki.anchor)
}, t
)
}
function makeURI (prefix, title, ext, rev, anchor)
{
var p = prefix === undefined ? Wiki.prefix : prefix
var t = title === undefined ? Wiki.title : title
var e = ext === undefined ? Wiki.ext : ext
var r = rev === undefined ? Wiki.rev : rev
var a = anchor === undefined ? Wiki.anchor : anchor
return p + t
+ (e ? '.' + e : '')
+ (r ? '?' + r : '')
+ (a ? '#' + a : '')
}
function makeURIExt (ext)
{
return makeURI(undefined, undefined, ext)
}
/* ---- showing documents -------------------------------------------------- */
function viewerHTML (txt)
{
if (Wiki.ext == 'html') {
$('#plain-viewer').hide()
$('#plain-viewer').html('')
$('#rich-viewer').show()
$('#rich-viewer').html(txt)
} else {
$('#rich-viewer').hide()
$('#rich-viewer').html('')
$('#plain-viewer').show()
$('#plain-viewer').html(txt)
}
}
function setExternalLinks ()
{
$('#txt-btn'). attr('href', makeURI(Wiki.viewerURI, undefined, 'txt'))
$('#html-btn'). attr('href', makeURI(Wiki.viewerURI, undefined, 'html'))
$('#latex-btn'). attr('href', makeURI(Wiki.viewerURI, undefined, 'tex'))
$('#adt-btn'). attr('href', makeURI(Wiki.viewerURI, undefined, 'hs'))
$('#pdf-btn'). attr('href', makeURIExt('pdf'))
$('#print-btn'). attr('href', makeURIExt('html'))
$('#src-btn'). attr('href', makeURIExt('txt'))
}
function show ()
{
$.get(
makeURIExt(Wiki.ext)
, ''
// Showing existing document:
, function (res)
{
viewerHTML(res)
$('#history-btn').removeClass('disabled')
processLinks()
processImages()
setExternalLinks()
}
, ''
// `Showing' non-existing document:
, function ()
{
viewerHTML('new document, click <strong>edit</strong> to start editing')
$('#history-btn').addClass('disabled')
showEditor() //todo
}
)
}
function processLinks ()
{
$(".Internal").each(
function ()
{
var href = this.getAttribute('href')
if (!href.match(/:/))
this.setAttribute('href', '#' + href)
}
)
$(".Reference").each(
function ()
{
$(this).attr('href', makeURI(Wiki.viewerURI, undefined, undefined, undefined, $(this).attr('href').substring(1)))
}
)
}
function processImages ()
{
$("img").each(
function ()
{
var src = this.getAttribute('src')
this.setAttribute('src', src.replace(/^_/, 'data/_'))
}
)
}
function followAnchor (ref)
{
var target = $('*[name=' + ref + ']')[0]
target.scrollIntoView()
setTimeout(
function ()
{
focusElement(target)
}, 0)
}
function focusElement (target)
{
var div = document.createElement('div')
document.body.appendChild(div)
var bcr = target.getBoundingClientRect()
div.style.left = bcr.left
div.style.top = bcr.top
div.style.width = target.clientWidth
div.style.height = target.clientHeight
$(div).addClass('find')
$(div).fadeOut('slow')
}
/* ---- authentication bar ------------------------------------------------- */
function login ()
{
if ($('#login-btn').hasClass('disabled'))
return;
$.post(
Wiki.loginURI
, { username : $('#username').val()
, password : $('#password').val()
}
, function ()
{
$('#login-status').removeClass('error')
$('#login-status').html('login successful')
panelClose($('#auth-btn'), $('#auth'))
updateAuth()
}
, ''
, function (e)
{
$('#login-status').addClass('error')
$('#login-status').html('login failed: <span>' + e.responseText + '</span>')
}
)
}
function logout ()
{
if ($('#logout-btn').hasClass('disabled'))
return;
$.post(
Wiki.logoutURI
, function ()
{
$('#login-status').removeClass('error')
$('#login-status').html('logout successful')
$('#auth').fadeOut()
updateAuth()
}
)
}
function updateAuth ()
{
$.get(
Wiki.loginfoURI
, ''
, function (res)
{
var m = res.match(/username=(.*?\n)/)
Wiki.user = (m && m[1]) || ''
$('#user').html(Wiki.user)
var bla = $('#user-ui').val(Wiki.user)
fieldUpdate.call(bla)
}
, ''
, function (res)
{
Wiki.user = ''
$('#user').html('<i>not logged in</i>')
fieldUpdate.call($('#user-ui').val(''))
}
)
}
function signup ()
{
if ($('#signup-btn').hasClass('disabled'))
return;
$.post(
Wiki.signupURI
, { username : $('#su-username').val()
, password : $('#su-password').val()
}
, function ()
{
$('#signup-status').removeClass('error')
$('#signup-status').html('signup successful')
panelClose($('#signup-btn'), $('#signup'))
}
, ''
, function (e)
{
$('#signup-status').addClass('error')
$('#signup-status').html('signup failed: <span>' + e.responseText + '</span>')
}
)
}
/* ---- document history --------------------------------------------------- */
function showHistory (title)
{
// Refuse history updates when panel is closed.
if (!$('#history').hasClass('open'))
return
$.get(makeURIExt('his'), '',
function (res)
{
$('#history').html(historyTable(res))
}
)
}
function historyTable (res)
{
function row (c, i)
{
var lines = c.split('\n')
, modified = lines.shift()
, author = lines.shift()
, name = lines.shift()
// Side note.
var klass =
name == Wiki.rev ||
(i == 0 && !Wiki.rev)
? 'class="current" ' : ''
return [
, '<tr $klass>'
, '<td>$modified</td>'
, '<td>$author</td>'
, '<td><a href="' + makeURI(Wiki.viewerURI, undefined, undefined, i == 0 ? '' : name) + '">$name</a></td>'
, '</tr>'
].join('').interpolate({
'klass' : klass
, 'modified' : modified
, 'author' : author
, 'name' : name
})
}
function col (c)
{
return '<td>' + c + '</td>'
}
return '' +
'<table cellpadding="0" cellspacing="0"><tr>' +
'<th id="modified">modified</th>' +
'<th id="author">author</th>' +
'<th id="changename">change</th>' +
'</tr>' +
res.asHTML().split("\n\n").map(row).join('')
+ '</tbody></table>'
}
/* ---- document editor ---------------------------------------------------- */
function showEditor (title)
{
$.get(makeURIExt('txt'), '',
// Editing an existing document:
function (res)
{
$('#editField').val(res)
},
'',
// `Editing' a new document:
function (res)
{
$('#editField').val('<new document>')
}
)
}
function save (title)
{
if (!Wiki.user)
return;
$.put(
makeURI(undefined, undefined, 'txt', $('#change.full').val())
, $('#editField').val()
, function ()
{
$('#edit-status').removeClass('error')
$('#edit-status').html('save successful')
panelClose($('#edit-btn'), $('#editor'))
show()
showHistory()
}
, ''
, function (e)
{
$('#edit-status').addClass('error')
$('#edit-status').html('save failed: <span>' + e.responseText + '</span>')
}
)
}
function preview ()
{
$.put(
Wiki.previewURI + '.' + Wiki.ext
, $('#editField').val()
, function (res)
{
viewerHTML(res)
processLinks()
processImages()
$('#edit-status').removeClass('error')
$('#edit-status').html('preview successful')
}
)
}
function _delete ()
{
$._delete(
makeURI(undefined, undefined, '', $('#change.full').val())
, ''
, function (res)
{
$('#edit-status').removeClass('error')
$('#edit-status').html('delete successful')
// todo: close edit & history.
}
)
}