var account = 'agentzh'; //var host = 'http://10.32.24.16:8080'; var host = 'http://localhost:8080'; //var host = 'http://api.eeeeworks.org'; //var host = 'http://api.openresty.org'; //var host = 'http://10.62.136.86'; var openresty = null; var savedAnchor = null; var itemsPerPage = 5; var loadingCount = 0; var waitMessage = null; var timer = null; var thisYear = null; var thisMonth = null; var thisDay = null; var cachedPostCountRes = null; var months = [ null, 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ]; $(window).ready(init); function error (msg) { alert(msg); } function debug (msg) { $("#copyright").append(msg + "<br/>"); } $.fn.postprocess = function (className, options) { return this.find("a[@href*='#']").each( function () { //debug("HERE!"); var href = $(this).attr('href'); // We need the following hack because IE expands href to // absolute URL: var anchor = href.replace(/^.*?\#/, ''); //debug("Anchor: " + anchor); $(this).click( function () { //debug(location.hash); //$(".bnchor-location")[0].id = anchor; location.hash = anchor; //alert(location.hash); if (savedAnchor == anchor) savedAnchor = null; dispatchByAnchor(); } ); } ); }; //var count = 0;; function setStatus (isLoading, category) { if (isLoading) { if (++loadingCount == 1) { if (jQuery.browser.opera) $(waitMessage).css('top', '2px'); else $(waitMessage).show(); } } else { loadingCount--; if (loadingCount < 0) loadingCount = 0; if (loadingCount == 0) { // the reason we use this hack is to work around // a rendering bug in Win32 build of Opera // (at least 9.25 and 9.26) if (jQuery.browser.opera) $(waitMessage).css('top', '-200px'); else $(waitMessage).hide(); } } //count++; //debug("[" + count + "] setStatus: " + category + ": " + loadingCount + "(" + isLoading + ")"); } function init () { loadingCount = 0; var now = new Date(); thisYear = now.getFullYear(); thisMonth = now.getMonth(); thisDay = now.getDate(); waitMessage = document.getElementById('wait-message'); openresty = new OpenResty.Client( { server: host, user: account + '.Public' } ); //openresty.formId = 'new_model'; if (timer) { clearInterval(timer); } dispatchByAnchor(); timer = setInterval(dispatchByAnchor, 600); //debug("before getSidebar..."); getSidebar(); } function resetAnchor () { var anchor = location.hash; location.hash = anchor.replace(/^\#/, ''); } function dispatchByAnchor () { //debug(location.hash); var anchor = location.hash; anchor = anchor.replace(/^\#/, ''); if (savedAnchor == anchor) return; if (anchor == "") { anchor = 'posts/1'; location.hash = 'posts/1'; } savedAnchor = anchor; // prevent memory leaks from dynamically created <script> nodes: //if (loadingCount <= 0) openresty.purge(); loadingCount = 0; var match = anchor.match(/^post-(\d+)(:comments|comment-(\d+))?/); if (match) { var postId = match[1]; //alert("Post ID: " + postId); getPost(postId); return; } match = anchor.match(/^search\/(\d+)\/(.*)/); if (match) { var page = parseInt(match[1]); var query = match[2]; $('.pager').html(''); $('#searchbox').val(query); getSearchResults(query, page); getPagerForSearch(query, page); return; } match = anchor.match(/^archive\/(\d+)\/(\d+)$/); if (match) { var year = match[1]; var month = match[2]; getArchive(year, month); return; } match = anchor.match(/^(?:posts|posts\/(\d+))$/); var page = 1; //alert(anchor + " " + location.hash); if (match) page = parseInt(match[1]) || 1; else if (anchor != 'posts/1') top.location.hash = 'posts/1'; //debug("before getPostList..."); getPostList(page); //debug("before getPager..."); getPager(page); //debug("after getPager..."); $(".blog-top").attr('id', 'posts/' + page); } function getArchive (year, month) { setStatus(true, 'renderPostList'); $(".pager").html(''); openresty.callback = function (res) { renderPostList(res); setStatus(true, 'renderArchiveNav'); openresty.callback = renderArchiveNav; openresty.get( '/=/view/PrevNextArchive/~/~', { now: year + '-' + month + '-01', month: month, months: months } ); }; openresty.get( '/=/view/FullPostsByMonth/~/~', { count: 40, year: year, month: month } ); $(".blog-top").attr('id', 'archive/' + year + '/' + month); } function renderArchiveNav (res) { //debug("render archive nav: " + JSON.stringify(res)); setStatus(false, 'renderArchiveNav'); if (!openresty.isSuccess(res)) { error("Failed to get archive navigator: " + res.errstr); return; } var prev = null; var next = null; for (var i = 0; i < res.length; i++) { var item = res[i]; item.year = parseInt(item.year); item.month = parseInt(item.month); //debug("item: " + JSON.stringify(item)); if (item.id == "prev") prev = item; else if (item.id == "next") next = item; } //debug("next: " + JSON.stringify(next)); //debug("prev: " + JSON.stringify(prev)); $("#post-list-nav").html( Jemplate.process( 'archive-nav.tt', { next: next, prev: prev, months: months } ) ).postprocess(); } function getPostList (page) { setStatus(true, 'renderPostList'); openresty.callback = renderPostList; openresty.get('/=/model/Post/~/~', { _limit: itemsPerPage, _order_by: 'id:desc', _offset: itemsPerPage * (page - 1) }); } function getSearchResults (query, page) { setStatus(true, 'renderSearchResults'); openresty.callback = function (res) { renderSearchResults(res, query); }; var q = query2tsquery(query); //alert("Query: " + q); openresty.get('/=/view/PostSearch/~/~', { offset: itemsPerPage * (page - 1), count: itemsPerPage, query: q, order_dir: 'desc' }); } function doPostSearch () { var query = $('#searchbox').val(); savedAnchor = null; var anchor = '#search/1/' + query; location.hash = anchor; //alert(location.hash); if (savedAnchor == anchor.replace(/^\#/, '')) savedAnchor = null; dispatchByAnchor(); } function query2tsquery (query) { return query.replace(/[\s(){},.|&$]+/g, ' ') .replace(/^\s+|\s+$/g, '') .replace(/ +/g, '|'); } function getPagerForSearch (query, page) { setStatus(true, 'renderPagerForSearch'); openresty.callback = function (res) { renderPager(res, page, 'search/', '/' + query); }; var q = query2tsquery(query); openresty.get('/=/view/RowCountForSearch/~/~', {query: q}); } function getPager (page) { setStatus(true, 'renderPager'); if (cachedPostCountRes) { //alert("Hit!"); renderPager(cachedPostCountRes, page, 'posts/', ''); } else { openresty.callback = function (res) { renderPager(res, page, 'posts/', ''); }; openresty.get('/=/view/RowCount/~/~', { model: 'Post' }); } } function getSidebar () { //getRecentPosts(); //getRecentComments(); //getArchiveList(); setStatus(true, 'renderSidebar'); openresty.callback = function (res) { renderSidebar(res) }; openresty.get('/=/batch/GetSidebar/~/~', { year: thisYear, month: thisMonth + 1 }); } function renderSidebar (res) { setStatus(false, 'renderSidebar'); if (!openresty.isSuccess(res)) { error("Failed to fetch posts for calendar: " + res.errstr); return; } getCalendar(thisYear, thisMonth, res[0]); setStatus(true, 'renderRecentPosts'); renderRecentPosts(res[1], 0, 6); setStatus(true, 'renderRecentComments'); renderRecentComments(res[2], 0, 6); setStatus(true, 'getArchiveList'); renderArchiveList(res[3], 0, 12); } function getCalendar (year, month, posts) { if (year == undefined || month == undefined) { year = thisYear; month = thisMonth; } var date = new Date(year, month, 1); var first_day_of_week = date.getDay(); var end_of_month; if (month == 11) { end_of_month = 31; } else { var delta = new Date(year, month + 1, 1) - date; end_of_month = Math.round(delta/1000/60/60/24); } //alert(year); //alert(month); //alert("thisday: " + thisDay); $(".module-calendar").html( Jemplate.process( 'calendar.tt', { year: year, month: month, first_day_of_week: first_day_of_week, end_of_month: end_of_month, today: (year == thisYear && month == thisMonth) ? thisDay : null, months: months } ) ).postprocess(); // We need this 0 timeout hack for IE 6 :( if (posts) { //alert("Shortcut!"); setStatus(true, 'renderPostsInCalendar'); renderPostsInCalendar(posts, year, month); } else { setTimeout( function () { setStatus(true, 'renderPostsInCalendar'); openresty.callback = function (res) { renderPostsInCalendar(res, year, month); }; openresty.get('/=/view/PostsByMonth/~/~', { year: year, month: month + 1 }); }, 0 ); } } function renderPostsInCalendar (res, year, month) { setStatus(false, 'renderPostsInCalendar'); //alert("hey!"); if (!openresty.isSuccess(res)) { error("Failed to fetch posts for calendar: " + res.errstr); } else { //alert(res.errstr); var prev_day = 0; for (var i = 0; i < res.length; i++) { var line = res[i]; if (prev_day == line.day) continue; prev_day = line.day; var id = 'day-' + year + '-' + month + '-' + line.day; //alert("ID: " + id); var cell = $("#" + id); if (cell.length == 0) return; //alert("cell html: " + cell.html()); cell.html('<a href="#post-' + line.id + '"><b>' + cell.html() + '</b></a>').postprocess(); } } } function getRecentComments (offset) { if (!offset) offset = 0; setStatus(true, 'renderRecentComments'); openresty.callback = function (res) { renderRecentComments(res, offset, 6) }; openresty.get('/=/view/RecentComments/~/~', { limit:6, offset: offset }); } function renderRecentComments (res, offset, count) { setStatus(false, 'renderRecentComments'); if (!openresty.isSuccess(res)) { error("Failed to get the recent comments: " + res.errstr); } else { //alert("Get the recent comments: " + res.errstr); var html = Jemplate.process( 'recent-comments.tt', { comments: res, offset: offset, count: count } ); $("#recent-comments").html(html).postprocess(); } } function getRecentPosts (offset) { if (!offset) offset = 0; setStatus(true, 'renderRecentPosts'); openresty.callback = function (res) { renderRecentPosts(res, offset, 6) }; openresty.get('/=/view/RecentPosts/~/~', { limit:6, offset: offset }); } function renderRecentPosts (res, offset, count) { setStatus(false, 'renderRecentPosts'); if (!openresty.isSuccess(res)) { error("Failed to get the recent posts: " + res.errstr); } else { //alert("Get the recent comments: " + res.errstr); var html = Jemplate.process( 'recent-posts.tt', { posts: res, offset: offset, count: count } ); $("#recent-posts").html(html).postprocess(); } } function getArchiveList (offset) { if (offset == undefined) offset = 0; setStatus(true, 'getArchiveList'); openresty.callback = function (res) { renderArchiveList(res, offset, 12); }; openresty.get( '/=/view/PostCountByMonths/~/~', { offset: offset, count: 12 } ); } function renderArchiveList (res, offset, count) { setStatus(false, 'getArchiveList'); if (!openresty.isSuccess(res)) { error("Failed to get archive list: " + res.errstr); return; } for (var i = 0; i < res.length; i++) { var item = res[i]; var match = item.year_month.match(/^(\d\d\d\d)-0?(\d+)/); if (match) { item.year = parseInt(match[1]); item.month = parseInt(match[2]); } else { error("Failed to match against year_month: " + item.year_month); } //debug(JSON.stringify(item)); } $("#archive-list").html( Jemplate.process( 'archive-list.tt', { archives: res, count: count, offset: offset, months: months } ) ).postprocess(); } function postComment (form) { var data = {}; data.sender = $("#comment-author").val(); data.email = $("#comment-email").val(); data.url = $("#comment-url").val(); data.body = $("#comment-text").val(); data.post_id = $("#comment-for").val(); //alert(JSON.stringify(data)); if (!data.sender) { error("Name is required."); return false; } if (!data.email) { error("Email address is required."); return false; } if (!data.body) { error("Comment body is required."); return false; } //openresty.purge(); setStatus(true, 'afterPostComment'); openresty.callback = afterPostComment; //openresty.formId = 'comment-form'; // TODO openresty.post('/=/batch/NewComment/~/~', data); openresty.get('/=/batch/NewComment/~/~', data); return false; } function afterPostComment (res) { setStatus(false, 'afterPostComment'); //alert("HERE!!! afterPostComment"); if (!openresty.isSuccess(res)) { error("Failed to post the comment: " + res.errstr); } else { //alert(res.errstr); $("#comment-text").val(''); var spans = $(".comment-count"); var commentCount = parseInt(spans.text()); var postId = spans.attr('post'); //debug(JSON.stringify(res)); var commentId = res[0].insert_id; location.hash = 'post-' + postId + ':' + (commentId ? 'comment-' + commentId : 'comments'); spans.text(commentCount + 1); getRecentComments(0); } } function getPost (id) { //alert("Go to Post " + id); $(".blog-top").attr('id', 'post-' + id); //alert($(".blog-top").attr('id')); setStatus(true, 'renderPost'); openresty.callback = renderPost; openresty.get('/=/batch/GetFullPost/~/~', { id: id }); } function renderPost (res) { setStatus(false, 'renderPost'); //alert(JSON.stringify(post)); if (!openresty.isSuccess(res)) { error("Failed to render post: " + res.errstr); } else { var post = res[0][0]; //if (!post) return; $("#beta-inner.pkg").html( Jemplate.process('post-page.tt', { post: post }) ).postprocess(); renderPrevNextPost(post.id, res[1]); //debug(JSON.stringify(post)); setStatus(true, 'renderComments'); renderComments(res[2]); $(".pager").html(''); resetAnchor(); } } function renderPrevNextPost (currentId, res) { if (!openresty.isSuccess(res)) { error("Failed to render prev next post navigation: " + res.errstr); } else { //alert("Going to render prev next post navigation: " + res.errstr); $(".content-nav").html( Jemplate.process('nav.tt', { posts: res, current: currentId }) ).postprocess(); //resetAnchor(); } } function renderComments (res) { setStatus(false, 'renderComments'); //alert("Comments: " + res.errstr); if (!openresty.isSuccess(res)) { error("Failed to get post list: " + res.errstr); } else { $(".comments-content").html( Jemplate.process('comments.tt', { comments: res }) ); //resetAnchor(); //setTimeout( function () { alert("Hi"); resetAnchor(); }, 1000 ); } } function renderPostList (res) { setStatus(false, 'renderPostList'); if (!openresty.isSuccess(res)) { error("Failed to get post list: " + res.errstr); } else { //alert(JSON.stringify(data)); $("#beta-inner.pkg").html( Jemplate.process('post-list.tt', { post_list: res }) ).postprocess(); } //resetAnchor(); } function renderSearchResults (res, query) { setStatus(false, 'renderSearchResults'); if (!openresty.isSuccess(res)) { error("Failed to get search results: " + res.errstr); } else { if (res.length) { var html = Jemplate.process('post-list.tt', { post_list: res }) $("#beta-inner.pkg").html(html).postprocess(); } else { $("#beta-inner.pkg").html("<p>Sorry, no search results found for query <b>\"" + query + "\"</b>.</p>"); } } } function renderPager (res, page, prefix, suffix) { setStatus(false, 'renderPager'); if (!openresty.isSuccess(res)) { error("Failed to render pager: " + res.errstr); } else { //debug("before rendering pager..."); cachedPostCountRes = res; var pageCount = Math.ceil(parseInt(res[0].count) / itemsPerPage); if (pageCount < 2) return; //debug("before redering pager (2)..."); var html = Jemplate.process( 'pager.tt', { page: page, page_count: pageCount, title: 'Pages', prefix: prefix, suffix: suffix } ); //debug("after html generation..."); // we use the .each hack here to work aound a JS runtime error in IE 6: $(".pager").each( function () { $(this).html( html ).postprocess(); } ); //debug("after rendering pager..."); resetAnchor(); } }