X-Git-Url: http://git.bytex64.net/?a=blobdiff_plain;f=www%2Fjs%2Fblerg.js;h=ddc604a651427415dbeb2e9bebfdd53bd3520848;hb=778d18a1d105cf441c18e43a351c056e5d029b44;hp=9f92594ba51b22777d5855bf0390d4854d0bb3b9;hpb=f4bf2d2efc566e9f165b97bda72cd5a27e0d2b19;p=blerg.git diff --git a/www/js/blerg.js b/www/js/blerg.js index 9f92594..ddc604a 100644 --- a/www/js/blerg.js +++ b/www/js/blerg.js @@ -5,13 +5,13 @@ // Config var baseURL = ''; var recordTemplate = new Template( - '
#{data}
Posted #{date}
' + '
#{data}
Posted #{date}. [permalink]
' ); var tagRecordTemplate = new Template( - '
#{data}
Posted by @#{author} on #{date}
' + '
#{data}
Posted by @#{author} on #{date}. [permalink]
' ); var latestRecordsTemplate = new Template( - '
@#{author} #{data}
' + '
@#{author} #{data}
' ); // Page elements @@ -82,7 +82,7 @@ LoginStatus.prototype.update = function() { if (this.loggedIn) { $('userlink').href = '/#' + this.username; $('userlink').update('@' + this.username); - $('reflink').href = '/#ref/' + this.username; + $('reflink').href = '/#/ref/' + this.username; $('login').hide(); $('logout').show(); } else { @@ -108,12 +108,10 @@ LoginStatus.prototype.post = function(msg) { if (j && j.status == 'success') { $('post.content').value = ''; if (location.hash != '#' + this.username) { - location.href = '/#' + this.username; - hashSwitch(); + qlink(this.username); } else { currentPager.itemCount++; - currentPager.pageStart = null; - currentPager.loadItems(); + currentPager.reload(); } } else { alert('Post failed!'); @@ -138,15 +136,13 @@ Pager.prototype.initPager = function() { Pager.prototype.olderPage = function() { if (this.pageStart >= this.itemsPerPage) { - this.pageStart -= this.itemsPerPage; - this.displayItems(); + qlink(this.baseFrag + '/p' + (this.pageStart - this.itemsPerPage)); } } Pager.prototype.newerPage = function() { if (this.pageStart + this.itemsPerPage < this.itemCount) { - this.pageStart += this.itemsPerPage; - this.displayItems(); + qlink(this.baseFrag + '/p' + (this.pageStart + this.itemsPerPage)); } } @@ -171,15 +167,46 @@ Pager.prototype.displayItems = function() { items.insert("There doesn't seem to be anything here!"); } - if (this.pageStart < this.itemCount - 1) + if (this.pageStart < this.itemCount - 1) { + $('newer_link').href = '/#' + this.baseFrag + '/p' + (this.pageStart + this.itemsPerPage); $('newer_link').show(); - else + } else { $('newer_link').hide(); + } - if (this.pageStart >= 10) + if (this.pageStart >= 10) { + $('older_link').href = '/#' + this.baseFrag + '/p' + (this.pageStart - this.itemsPerPage); $('older_link').show(); - else + } else { $('older_link').hide(); + } + + document.body.scrollTo(); +} + +Pager.prototype.reload = function() { + this.pageStart = null; + this.loadItems(null, null, Pager.prototype.showPageAt.bind(this, this.itemCount - 1)); +} + +Pager.prototype.showPageAt = function(r) { + var end = (r - 9 > 0 ? r - 9 : 0); + if (this.itemCache[r] && this.itemCache[end]) { + this.pageStart = r; + this.displayItems(); + } else { + this.loadItems((r >= 49 ? r - 49 : 0), r, Pager.prototype.showPageAt.bind(this, r)); + } +} + +Pager.prototype.showRecord = function(r) { + if (this.itemCache[r]) { + $('older_link').hide(); + $('newer_link').hide(); + items.update(this.itemCache[r].html); + } else { + this.loadItems(r, r, Pager.prototype.showRecord.bind(this, r)); + } } @@ -187,9 +214,28 @@ Pager.prototype.displayItems = function() { function User(username) { this.initPager(); this.username = username; + this.baseFrag = username; +} +User.prototype = new Pager(); +User.prototype.constructor = User; + +User.prototype.show = function() { + $$('[name=section]').each(function(v) { v.update(' @' + this.username) }.bind(this)); + $('welcome').hide(); + items.show(); + $('rss').show(); + $('rsslink').href = '/rss/' + this.username; + $$('[name=user.reflink]').each(function(e) { + e.href = '/#/ref/' + this.username; + }.bind(this)); + $('usercontrols').show(); +} - $$('[name=user.obsesslink]').each(Element.hide); - $$('[name=user.unobsesslink]').each(Element.hide); +User.prototype.reload = function() { + this.pageStart = null; + + $$('[name=user.subscribelink]').each(Element.hide); + $$('[name=user.unsubscribelink]').each(Element.hide); if (loginStatus.loggedIn) { new Ajax.Request(baseURL + '/feedinfo/' + username, { @@ -200,43 +246,30 @@ function User(username) { onSuccess: function(r) { var json = r.responseText.evalJSON(); if (json.subscribed) { - $$('[name=user.obsesslink]').each(Element.hide); - $$('[name=user.unobsesslink]').each(Element.show); + $$('[name=user.subscribelink]').each(Element.hide); + $$('[name=user.unsubscribelink]').each(Element.show); } else { - $$('[name=user.obsesslink]').each(Element.show); - $$('[name=user.unobsesslink]').each(Element.hide); + $$('[name=user.subscribelink]').each(Element.show); + $$('[name=user.unsubscribelink]').each(Element.hide); } } }); } - new Ajax.Request(baseURL + '/info/' + username, { + new Ajax.Request(baseURL + '/info/' + this.username, { method: 'get', onSuccess: function(r) { var j = r.responseText.evalJSON(); if (j) { this.itemCount = parseInt(j.record_count); - this.displayItems(); + if (!this.pageStart) + this.showPageAt(this.itemCount - 1); } }.bind(this) }); } -User.prototype = new Pager(); -User.prototype.constructor = User; -User.prototype.show = function() { - $$('[name=section]').each(function(v) { v.update(' @' + this.username) }.bind(this)); - $('welcome').hide(); - items.show(); - $('rss').show(); - $('rsslink').href = '/rss/' + this.username; - $$('[name=user.reflink]').each(function(e) { - e.href = '/#ref/' + this.username; - }.bind(this)); - $('usercontrols').show(); -} - -User.prototype.loadItems = function(from, to) { +User.prototype.loadItems = function(from, to, continuation) { var url; if (from != undefined && to != undefined) { url = baseURL + '/get/' + this.username + '/' + from + '-' + to; @@ -252,13 +285,14 @@ User.prototype.loadItems = function(from, to) { if (records && records.length > 0) { records.each(function(v) { v.id = v.record; + v.author = this.username; mangleRecord(v, recordTemplate); - }); + }.bind(this)); this.addItems(records); if (!this.pageStart) this.pageStart = records[0].recInt; } - this.displayItems(); + continuation(); }.bind(this), onFailure: function(r) { this.displayItems(); @@ -292,6 +326,7 @@ function mangleRecord(record, template) { return; } + // Put quoted material into a special paragraph if (l[0] == '>') { var pi = out.lastIndexOf('

'); if (pi != -1) { @@ -299,6 +334,28 @@ function mangleRecord(record, template) { l = l.replace(/^>\s*/, ''); } } + + // Sanitize HTML input + l = l.replace(/&/g, '&').replace(//g, '>'); + + // Turn HTTP URLs into links + l = l.replace(/(\s|^)(https?:\/\/[a-zA-Z0-9.-]*[a-zA-Z0-9](\/([^\s"]*[^.!,;?()\s])?)?)/g, '$1$2'); + + // Turn markdown links into links + l = l.replace(/(\s|^)\[([^\]]+)\]\((https?:\/\/[a-zA-Z0-9.-]*[a-zA-Z0-9](\/[^)"]*?)?)\)/g, '$1$2'); + + // Turn *foo* into italics and **foo** into bold + l = l.replace(/([^\w\\]|^)\*\*(\w[^*]*)\*\*(\W|$)/g, '$1$2$3'); + l = l.replace(/([^\w\\]|^)\*(\w[^*]*)\*(\W|$)/g, '$1$2$3'); + + // Remove backslashes from escaped metachars + l = l.replace(/\\([*\[\]])/g, '$1'); + + // Turn refs and tags into links + l = l.replace(/(\s|^)#([A-Za-z0-9_-]+)/g, '$1#$2'); + l = l.replace(/(\s|^)@([A-Za-z0-9_-]+)/g, '$1@$2'); + + // Create lists when lines begin with * if (l[0] == '*') { if (!listMode) { var pi = out.lastIndexOf('

'); @@ -309,33 +366,18 @@ function mangleRecord(record, template) { out.push('

  • '); endpush = '
  • '; } - if (l[0] == '=') { - var m = l.match(/^(=+)/); + + // Create headers when lines begin with = or # + if (l[0] == '=' || l[0] == '#') { + var m = l.match(/^([=#]+)/); var depth = m[1].length; if (depth <= 5) { - l = l.replace(/^=+\s*/, '').replace(/\s*=+$/, ''); + l = l.replace(/^[=#]+\s*/, '').replace(/\s*[=#]+$/, ''); out.push(''); endpush = ''; } } - // Sanitize HTML input - l = l.replace(/&/g, '&').replace(//g, '>'); - - // Turn HTTP URLs into links - l = l.replace(/(\s|^)(https?:\/\/[a-zA-Z0-9.-]*[a-zA-Z0-9](\/([^\s"]*[^.!,;?()\s])?)?)/g, '$1$2'); - - // Turn markdown links into links - l = l.replace(/(\s|^)\[([^\]]+)\]\((https?:\/\/[a-zA-Z0-9.-]*[a-zA-Z0-9](\/[^)"]*?)?)\)/g, '$1$2'); - - // Turn *foo* into italics and **foo** into bold - l = l.replace(/(\s)\*\*([^*]+)\*\*(\s)/g, '$1$2$3'); - l = l.replace(/(\s)\*([^*]+)\*(\s)/g, '$1$2$3'); - - // Turn refs and tags into links - l = l.replace(/(\s|^)#([A-Za-z0-9_-]+)/g, '$1#$2'); - l = l.replace(/(\s|^)@([A-Za-z0-9_-]+)/g, '$1@$2'); - out.push(l); if (endpush) { out.push(endpush); @@ -346,6 +388,8 @@ function mangleRecord(record, template) { }); while (out[out.length - 1] == '
    ' || out[out.length - 1] == '

    ') out.pop(); + if (listMode) + out.push(''); record.data = out.join(''); record.date = (new Date(record.timestamp * 1000)).toString(); @@ -368,9 +412,11 @@ function Tag(type, tag) { case 'tag': //url += '%23'; url += 'H'; // apache is eating the hash, even encoded. Probably a security feature. + this.baseFrag = '/tag/' + tag; break; case 'ref': url += '%40'; + this.baseFrag = '/ref/' + tag; break; default: alert('Invalid tag type: ' + type); @@ -390,6 +436,7 @@ function Tag(type, tag) { }); this.addItems(j); this.pageStart = j.length - 1; + this.itemCount = j.length; } this.displayItems(); }.bind(this), @@ -417,6 +464,54 @@ Tag.prototype.show = function() { $('usercontrols').hide(); } + +// Pager for browsing subscription feeds +function Feed() { + this.initPager(); + this.username = loginStatus.username; + this.baseFrag = '/feed'; + + new Ajax.Request(baseURL + '/feed', { + method: 'post', + parameters: { + username: loginStatus.username + }, + onSuccess: function(r) { + var response = r.responseText.evalJSON(); + if (response) { + var maxid = response.length - 1; + response.each(function(v, i) { + v.id = maxid - i; + mangleRecord(v, tagRecordTemplate) + }); + this.addItems(response); + this.pageStart = response.length - 1; + this.itemCount = response.length; + } + this.displayItems(); + }.bind(this), + onFailure: function(r) { + this.displayItems(); + }.bind(this) + }); +} +Feed.prototype = new Pager(); +Feed.prototype.constructor = Feed; + +Feed.prototype.show = function() { + $$('[name=section]').each(function(v) { + v.update(' ' + loginStatus.username + "'s spycam"); + }.bind(this)); + $('welcome').hide(); + $('post').hide(); + $('older_link').hide(); + $('newer_link').hide(); + $('rss').hide(); + items.show(); + $('usercontrols').hide(); +} + + function postPopup() { if (loginStatus.loggedIn) { var post = $('post'); @@ -443,8 +538,7 @@ function signup() { }, onSuccess: function(r) { $('signup').hide(); - location.href = '/#' + username; - hashSwitch(); + qlink(username); loginStatus.login(username, password); }, @@ -459,17 +553,7 @@ function signup_cancel() { hashSwitch(); } -function newer_page() { - if (currentPager) - currentPager.newerPage(); -} - -function older_page() { - if (currentPager) - currentPager.olderPage(); -} - -function obsess() { +function subscribe() { new Ajax.Request(baseURL + '/subscribe/' + currentPager.username, { method: 'post', parameters: { @@ -479,19 +563,19 @@ function obsess() { var response = r.responseText.evalJSON(); if (response.status == 'success') { alert("You call " + currentPager.username + " and begin breathing heavily into the handset."); - $$('[name=user.obsesslink]').each(Element.hide); - $$('[name=user.unobsesslink]').each(Element.show); + $$('[name=user.subscribelink]').each(Element.hide); + $$('[name=user.unsubscribelink]').each(Element.show); } else { - alert('Failed to obsess. This is probably for the best'); + alert('Failed to subscribe. This is probably for the best'); } }, onFailure: function(r) { - alert('Failed to obsess. This is probably for the best'); + alert('Failed to subscribe. This is probably for the best'); } }); } -function unobsess() { +function unsubscribe() { new Ajax.Request(baseURL + '/unsubscribe/' + currentPager.username, { method: 'post', parameters: { @@ -501,8 +585,8 @@ function unobsess() { var response = r.responseText.evalJSON(); if (response.status == 'success') { alert("You come to your senses."); - $$('[name=user.obsesslink]').each(Element.show); - $$('[name=user.unobsesslink]').each(Element.hide); + $$('[name=user.subscribelink]').each(Element.show); + $$('[name=user.unsubscribelink]').each(Element.hide); } else { alert('You are unable to tear yourself away (because something failed on the server)'); } @@ -587,8 +671,9 @@ function loadLatest() { $('latest-tags').update(); j.tags.each(function(v) { - var a = new Element('a', {href: '/#tag/' + v}); + var a = new Element('a', {href: '/#/tag/' + v}); a.insert('#' + v); + a.onclick = "return qlink()"; a.className = 'ref'; $('latest-tags').insert(a); $('latest-tags').appendChild(document.createTextNode(' ')); @@ -606,32 +691,61 @@ function loadLatest() { }); } +function qlink(loc) { + if (loc) { + location.hash = loc; + } else if (event && event.target) { + location.href = event.target.href; + } else { + // Bogus qlink + return; + } + hashSwitch(); + return false; +} + function hashSwitch() { var m; stopTicker(); if (m = location.search.match(/^\?post\/([^/]+)\/(.+)/)) { $('post').show(); $('post.content').value = '[' + decodeURIComponent(m[1]).replace(']','').replace('[','') + '](' + decodeURIComponent(m[2]) + ')'; - } else if (m = location.hash.match(/^#(ref|tag)\/([A-Za-z0-9_-]+)$/)) { - currentPager = new Tag(m[1], m[2]); + } else if (m = location.hash.match(/^#\/(ref|tag)\/([A-Za-z0-9_-]+)(?:\/p(\d+))?$/)) { + if (!currentPager || !(currentPager instanceof Tag) || currentPager.type != m[1] || currentPager.tag != m[2]) + currentPager = new Tag(m[1], m[2]); currentPager.show(); - } else if (m = location.hash.match(/^#([A-Za-z0-9_-]+)(:(\d+))?$/)) { - if (!currentPager || currentPager.username != m[1]) + + if (m[3]) { + var r = parseInt(m[3]); + currentPager.showPageAt(r); + } + } else if (m = location.hash.match(/^#\/feed(?:\/p(\d+))?$/)) { + if (loginStatus.loggedIn) { + if (!currentPager || !(currentPager instanceof Feed) || currentPager.username != loginStatus.username) + currentPager = new Feed(); + currentPager.show(); + if (m[3]) { + var r = parseInt(m[3]); + currentPager.showPageAt(r); + } + } else { + location.href = baseURL; + } + } else if (m = location.hash.match(/^#([A-Za-z0-9_-]+)(?:\/(p)?(\d+))?$/)) { + if (!currentPager || !(currentPager instanceof User) || currentPager.username != m[1]) currentPager = new User(m[1]); currentPager.show(); loginStatus.update(); if (m[3]) { var r = parseInt(m[3]); - currentPager.showRecord = r; - if (currentPager.itemCache[r]) { - currentPager.displayItems(); + if (m[2] == 'p') { + currentPager.showPageAt(r); } else { - currentPager.loadItems((r >= 49 ? r - 49 : 0), r); + currentPager.showRecord(r); } } else { - currentPager.pageStart = currentPager.itemCount - 1; - currentPager.loadItems(); + currentPager.reload(); } } else { $$('[name=section]').each(function(v) { v.update('Welcome') }); @@ -665,7 +779,7 @@ function init() { setInterval(hashCheck, 250); document.body.observe('keyup', function(event) { - if (event.shiftKey && event.keyCode == '32') { + if (event.shiftKey && event.keyCode == 32) { postPopup(); event.stop(); }