X-Git-Url: http://git.bytex64.net/?a=blobdiff_plain;f=www%2Fjs%2Fblerg.js;h=d0135b8abda05ff5591979b11c02b0253946704e;hb=36bef82c002dfa65064635cb8d3fae3660a6cde2;hp=38e3f721f849365d44a8ac6af9946da892617d0c;hpb=88c6a9fc4bb0ed732cc7aaac463b71d1afd235cf;p=blerg.git diff --git a/www/js/blerg.js b/www/js/blerg.js index 38e3f72..d0135b8 100644 --- a/www/js/blerg.js +++ b/www/js/blerg.js @@ -5,10 +5,10 @@ // Config var baseURL = ''; var recordTemplate = new Template( - '
#{data}
Posted #{date}
' + '
#{data}
Posted #{date}. [permalink] [reply]
' ); var tagRecordTemplate = new Template( - '
#{data}
Posted by @#{author} on #{date}
' + '
#{data}
Posted by @#{author} on #{date}. [permalink] [reply]
' ); var latestRecordsTemplate = new Template( '
@#{author} #{data}
' @@ -69,7 +69,7 @@ LoginStatus.prototype.logout = function() { parameters: { username: this.username }, - onSuccess: function(r) { + onComplete: function(r) { this.loggedIn = false; document.cookie = "auth=; expires=1-Jan-1970 00:00:00 GMT"; this.update(); @@ -111,8 +111,7 @@ LoginStatus.prototype.post = function(msg) { qlink(this.username); } else { currentPager.itemCount++; - currentPager.pageStart = null; - currentPager.loadItems(); + currentPager.reload(); } } else { alert('Post failed!'); @@ -128,13 +127,25 @@ LoginStatus.prototype.post = function(msg) { // Base object for paged data function Pager() { this.itemsPerPage = 10; -} - -Pager.prototype.initPager = function() { this.itemCache = new Hash(); this.pageStart = null; } +Pager.prototype.updateState = function(m) { + return false; +} + +Pager.prototype.show = function() { + items.show(); +} + +Pager.prototype.hide = function() { + items.hide(); + items.update(); + $('newer_link').hide(); + $('older_link').hide(); +} + Pager.prototype.olderPage = function() { if (this.pageStart >= this.itemsPerPage) { qlink(this.baseFrag + '/p' + (this.pageStart - this.itemsPerPage)); @@ -181,33 +192,95 @@ Pager.prototype.displayItems = function() { } 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) { - if (this.itemCache[r] && this.itemCache[r - 9]) { + 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); + this.loadItems((r >= 49 ? r - 49 : 0), r, Pager.prototype.showPageAt.bind(this, r)); } } Pager.prototype.showRecord = function(r) { - this.showPageAt(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)); + } } +Pager.prototype.loadItems = function(from, to, continuation) { } + // Object to render user pages -function User(username) { - this.initPager(); - this.username = username; - this.baseFrag = username; +function User(m) { + Pager.call(this); + this.username = m[1]; + this.baseFrag = m[1]; + this.permalink = (m[2] != 'p'); + this.pageStart = parseInt(m[3]); +} +User.prototype = new Pager(); +User.prototype.constructor = User; + +User.prototype.updateState = function(m) { + if (m[1] != this.username) + return false; + + this.permalink = (m[2] != 'p'); + this.pageStart = parseInt(m[3]); + this.show(); + + return true; +} + +User.prototype.show = function() { + Pager.prototype.show.call(this); + + $$('[name=section]').each(function(v) { v.update(' @' + this.username) }.bind(this)); + $('rss').show(); + $('rsslink').href = '/rss/' + this.username; + $$('[name=user.reflink]').each(function(e) { + e.href = '/#/ref/' + this.username; + }.bind(this)); + $('usercontrols').show(); + + if (this.permalink && this.pageStart) { + this.showRecord(this.pageStart); + } else if (this.pageStart) { + this.showPageAt(this.pageStart); + } else { + this.reload(); + } +} + +User.prototype.hide = function() { + Pager.prototype.hide.call(this); + $('signup').hide(); + $('rss').hide(); + $('usercontrols').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, { + new Ajax.Request(baseURL + '/feedinfo/' + this.username, { method: 'post', parameters: { username: loginStatus.username @@ -225,33 +298,19 @@ function User(username) { }); } - 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(); + var response = r.responseText.evalJSON(); + if (response) { + this.itemCount = parseInt(response.record_count); + 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; @@ -267,13 +326,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(); @@ -326,12 +386,12 @@ function mangleRecord(record, template) { 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'); + l = l.replace(/([^\w\\]|^)\*\*(\w[^*]*)\*\*(\W|$)/g, '$1$2$3'); + l = l.replace(/([^\w\\]|^)\*(\w[^*]*)\*(\W|$)/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'); + l = l.replace(/(\s|^)@([A-Za-z0-9_-]+)(\/\d+)?/g, '$1@$2'); // Create lists when lines begin with * if (l[0] == '*') { @@ -345,17 +405,20 @@ function mangleRecord(record, template) { endpush = ''; } - // Create headers when lines begin with = - 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 = ''; } } + // Remove backslashes from escaped metachars + l = l.replace(/\\([*\[\]@#])/g, '$1'); + out.push(l); if (endpush) { out.push(endpush); @@ -380,27 +443,28 @@ function displayError(msg) { // Object for browsing tags -function Tag(type, tag) { - this.initPager(); - this.type = type; - this.tag = tag; +function Tag(m) { + Pager.call(this); + this.type = m[1]; + this.tag = m[2]; + this.pageStart = parseInt(m[3]); var url = baseURL + "/tag/"; - switch(type) { + switch(this.type) { case 'tag': //url += '%23'; url += 'H'; // apache is eating the hash, even encoded. Probably a security feature. - this.baseFrag = '/tag/' + tag; + this.baseFrag = '/tag/' + this.tag; break; case 'ref': url += '%40'; - this.baseFrag = '/ref/' + tag; + this.baseFrag = '/ref/' + this.tag; break; default: - alert('Invalid tag type: ' + type); + alert('Invalid tag type: ' + this.type); return; } - url += tag; + url += this.tag; new Ajax.Request(url, { method: 'get', @@ -413,7 +477,9 @@ function Tag(type, tag) { mangleRecord(v, tagRecordTemplate) }); this.addItems(j); - this.pageStart = j.length - 1; + if (!this.pageStart) + this.pageStart = j.length - 1; + this.itemCount = j.length; } this.displayItems(); }.bind(this), @@ -426,26 +492,33 @@ function Tag(type, tag) { Tag.prototype = new Pager(); Tag.prototype.constructor = Tag; +Tag.prototype.updateState = function(m) { + if (this.type != m[1] || this.tag != m[2]) + return false; + + this.pageStart = parseInt(m[3]) || this.itemCount - 1; + this.displayItems(); + + return true; +} + Tag.prototype.show = function() { + Pager.prototype.show.call(this); + var ctype = {ref: '@', tag: '#'}[this.type]; $$('[name=section]').each(function(v) { v.update(' about ' + ctype + this.tag); }.bind(this)); - $('welcome').hide(); - $('post').hide(); - $('older_link').hide(); - $('newer_link').hide(); - $('rss').hide(); - items.show(); - $('usercontrols').hide(); } // Pager for browsing subscription feeds -function Feed() { - this.initPager(); +function Feed(m) { + Pager.call(this); + this.username = loginStatus.username; this.baseFrag = '/feed'; + this.pageStart = parseInt(m[1]); new Ajax.Request(baseURL + '/feed', { method: 'post', @@ -461,7 +534,9 @@ function Feed() { mangleRecord(v, tagRecordTemplate) }); this.addItems(response); - this.pageStart = response.length - 1; + if (!this.pageStart) + this.pageStart = response.length - 1; + this.itemCount = response.length; } this.displayItems(); }.bind(this), @@ -473,28 +548,31 @@ function Feed() { Feed.prototype = new Pager(); Feed.prototype.constructor = Feed; +Feed.prototype.updateState = function(m) { + this.pageStart = parseInt(m[1]) || this.itemCount - 1; + this.displayItems(); + + return true; +} + Feed.prototype.show = function() { + Pager.prototype.show.call(this); $$('[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) { +function postPopup(initial) { + if (loginStatus.loggedIn || initial) { var post = $('post'); if (post.visible()) { post.hide(); } else { post.show(); - if (currentPager.username && currentPager.username != loginStatus.username && !$('post.content').value) { + if (initial) { + $('post.content').value = initial; + } else if (!$('post.content').value && currentPager.username && currentPager.username != loginStatus.username) { $('post.content').value = '@' + currentPager.username + ': '; } $('post.content').focus(); @@ -525,7 +603,7 @@ function signup() { function signup_cancel() { $('signup').hide(); - hashSwitch(); + urlSwitch(); } function subscribe() { @@ -648,7 +726,7 @@ function loadLatest() { j.tags.each(function(v) { var a = new Element('a', {href: '/#/tag/' + v}); a.insert('#' + v); - a.onclick = qlink; + a.onclick = "return qlink()"; a.className = 'ref'; $('latest-tags').insert(a); $('latest-tags').appendChild(document.createTextNode(' ')); @@ -675,62 +753,75 @@ function qlink(loc) { // Bogus qlink return; } - hashSwitch(); + lastHash = location.hash; + urlSwitch(); return false; } -function hashSwitch() { - var m; +function Welcome() { + loadLatest(); +} + +Welcome.prototype.show = function() { + $$('[name=section]').each(function(v) { v.update('Welcome') }); + $('welcome').show(); +} + +Welcome.prototype.hide = function() { 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]); - currentPager.show(); - } else if (m = location.hash.match(/^#\/feed/)) { - if (loginStatus.loggedIn) { - currentPager = new Feed(); - currentPager.show(); - } else { - location.href = baseURL; - } - } else if (m = location.hash.match(/^#([A-Za-z0-9_-]+)(?:\/(p)?(\d+))?$/)) { - if (!currentPager || currentPager.username != m[1]) - currentPager = new User(m[1]); - currentPager.show(); - loginStatus.update(); + $('welcome').hide(); +} - if (m[3]) { - var r = parseInt(m[3]); - if (m[2] == 'p') { - currentPager.showPageAt(r); - } else { - currentPager.showRecord(r); - } - } else { - currentPager.pageStart = currentPager.itemCount - 1; - currentPager.loadItems(); +function ExternalURLPost(m) { + this.title = decodeURIComponent(m[1]).replace(']','').replace('[',''); + this.url = decodeURIComponent(m[2]); +} + +ExternalURLPost.prototype.show = function() { + $('post.content').value = '[' + this.title + '](' + this.url + ')'; + $('post').show(); +} + +var urlmap = [ + ['search', /^\?post\/([^/]+)\/(.+)/, ExternalURLPost], + ['hash', /^#\/(ref|tag)\/([A-Za-z0-9_-]+)(?:\/p(\d+))?$/, Tag], + ['hash', /^#\/feed(?:\/p(\d+))?$/, Feed], + ['hash', /^#([A-Za-z0-9_-]+)(?:\/(p)?(\d+))?$/, User] +]; + +function urlSwitch() { + var m; + var pageconstructor; + + for (var i = 0; i < urlmap.length; i++) { + if (m = location[urlmap[i][0]].match(urlmap[i][1])) { + pageconstructor = urlmap[i][2]; + break; } - } else { - $$('[name=section]').each(function(v) { v.update('Welcome') }); - $('signup').hide(); - items.update(); - items.hide(); - $('newer_link').hide(); - $('older_link').hide(); - $('welcome').show(); - $('rss').hide(); - $('usercontrols').hide(); - loadLatest(); } + if (i == urlmap.length) + pageconstructor = Welcome; + + if (currentPager && currentPager instanceof pageconstructor) { + // updateState returns true if the state has been successfully updated. + // Otherwise, we continue and create a new instance. + if (currentPager.updateState(m)) + return; + } + + if (currentPager && currentPager.hide) + currentPager.hide(); + + currentPager = new pageconstructor(m); + if (currentPager.show) + currentPager.show(); } var lastHash; function hashCheck() { if (location.hash != lastHash) { lastHash = location.hash; - hashSwitch(); + urlSwitch(); } } @@ -739,7 +830,7 @@ function init() { loginStatus = new LoginStatus(); lastHash = location.hash; - hashSwitch(); + urlSwitch(); setInterval(hashCheck, 250);