From 21db04ef3e4f66d7b5c4c9be2be36703b18cbcaa Mon Sep 17 00:00:00 2001 From: Chip Black Date: Sat, 14 Apr 2012 23:48:31 -0700 Subject: [PATCH] First stab at enyo rewrite Rearchitected the way view loading works. Changed login box to be enyo-ish. Made enyo dialog signup. Made Welcome page way more obnoxious. No API is hooked up yet, though. --- www/css/blerg.css | 95 +++++++++++++++++++++++---------- www/index.html | 84 ++++------------------------- www/js/blerg.js | 81 ---------------------------- www/jssrc/blerg/API.js | 6 +++ www/jssrc/blerg/Blerg.js | 82 ++++++++++++++++++++++++++++ www/jssrc/blerg/Controls.js | 61 +++++++++++++++++++++ www/jssrc/blerg/Help.js | 6 +++ www/jssrc/blerg/Link.js | 5 ++ www/jssrc/blerg/Main.js | 16 ++++++ www/jssrc/blerg/PasswdDialog.js | 28 ++++++++++ www/jssrc/blerg/Post.js | 27 ++++++++++ www/jssrc/blerg/SignupDialog.js | 28 ++++++++++ www/jssrc/blerg/Title.js | 57 ++++++++++++++++++++ www/jssrc/blerg/Welcome.js | 46 ++++++++++++++++ www/jssrc/blerg/package.js | 13 +++++ www/jssrc/package.js | 4 ++ www/welcome.html | 46 ++++++++++++++++ 17 files changed, 502 insertions(+), 183 deletions(-) create mode 100644 www/jssrc/blerg/API.js create mode 100644 www/jssrc/blerg/Blerg.js create mode 100644 www/jssrc/blerg/Controls.js create mode 100644 www/jssrc/blerg/Help.js create mode 100644 www/jssrc/blerg/Link.js create mode 100644 www/jssrc/blerg/Main.js create mode 100644 www/jssrc/blerg/PasswdDialog.js create mode 100644 www/jssrc/blerg/Post.js create mode 100644 www/jssrc/blerg/SignupDialog.js create mode 100644 www/jssrc/blerg/Title.js create mode 100644 www/jssrc/blerg/Welcome.js create mode 100644 www/jssrc/blerg/package.js create mode 100644 www/jssrc/package.js create mode 100644 www/welcome.html diff --git a/www/css/blerg.css b/www/css/blerg.css index 1ceca6d..10e8ed5 100644 --- a/www/css/blerg.css +++ b/www/css/blerg.css @@ -20,44 +20,39 @@ a > img { border: 0; } -#header { +.blerg-header { background-color: #1E1E1E; color: white; padding: 8px 8px 16px 8px; } -#header .logo { +.blerg-header .logo { float: left; margin-right: 10px; } -#header h1 { +.blerg-header h1 { margin: 4px 0 0 0; font-size: 65px; text-shadow: black 0px 2px; } -#header a { +.blerg-header a { color: inherit; text-decoration: none; } -#header a:hover { +.blerg-header a:hover { text-decoration: underline; } -#header h2 { +.blerg-header h2 { margin: 0; font-size: 28px; text-shadow: black 0px 1px; } -#siteid { - float: left; - width: 40%; -} - -#controls { +.blerg-controls { float: right; width: 50%; margin-top: 8px; @@ -75,42 +70,60 @@ h1, h2, h3 { font-family: "Alte Haas Grotesk Bold", sans-serif; } -#main { +.blerg-main { padding: 15pt 15pt 20pt 15pt; } -#signup { - padding: 8pt; -} - -#main h2, #signup h2, #about h2 { +.blerg-main h2 { margin: 8pt 0; } -#post { +.blerg-post { padding: 20pt 20pt 16pt 20pt; } -#post h2 { +.blerg-post h2 { font-size: 14pt; - margin: 4pt 0 0 -4px; + margin: 0; } -#post\.buttons { +.blerg-post .buttons { text-align: right; - margin-right: -4px; } -#post\.buttons input { - font-size: 14pt; +.blerg-post .buttons .onyx-button { + margin-left: 4pt; + height: 0.4in; + width: 1in; +} + +.blerg-post .onyx-input-decorator { + display: block; + border-color: #CCC; + margin: 4pt 0; } -#post\.content { +.blerg-post .onyx-textarea { + display: block; + width: 100%; +} + +.blerg-post .content { font-size: 14pt; font-family: sans-serif; - margin: 4pt 0 4pt -4px; - border-width: 0; - padding: 4px; +} + +.login { + display: inline-block; + width: 200px; +} + +.login .onyx-button { + width: 100%; + margin-top: 4pt; +} + +.login .enyo-input { width: 100%; } @@ -175,3 +188,27 @@ h1, h2, h3 { padding-left: 6px; margin-left: 2px; } + +.blerg-dialog { + width: 300px; + padding: 8px; +} + +.blerg-dialog h2 { + font-size: 14pt; + margin: 0; +} + +.blerg-dialog .onyx-groupbox { + margin: 8px 0; +} + +.blerg-dialog .onyx-button { + display: block; + margin: 8px 0 0 0; + width: 100%; +} + +.blerg-dialog .onyx-input { + width: 100%; +} diff --git a/www/index.html b/www/index.html index c6dcec4..9c78587 100644 --- a/www/index.html +++ b/www/index.html @@ -6,15 +6,20 @@ Blërg! - - - - + + + + - + + + diff --git a/www/js/blerg.js b/www/js/blerg.js index 2ef48d9..6d555b8 100644 --- a/www/js/blerg.js +++ b/www/js/blerg.js @@ -830,24 +830,6 @@ function qlink(loc) { return false; } -function Welcome() { - loadLatest(); -} - -Welcome.prototype.show = function() { - $$('[name=section]').each(function(v) { v.update('Welcome') }); - $('welcome').show(); -} - -Welcome.prototype.hide = function() { - stopTicker(); - $('welcome').hide(); -} - -Welcome.prototype.updateState = function() { - this.show(); -} - function ExternalURLPost(m) { this.title = decodeURIComponent(m[1]).replace(']','').replace('[',''); this.url = decodeURIComponent(m[2]); @@ -857,66 +839,3 @@ 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; - } - } - 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; - urlSwitch(); - } -} - -function init() { - items = $('items'); - loginStatus = new LoginStatus(); - - lastHash = location.hash; - urlSwitch(); - - setInterval(hashCheck, 250); - - document.body.observe('keyup', function(event) { - if (event.shiftKey && event.keyCode == 32) { - postPopup(); - event.stop(); - } - }); - $('post.content').addEventListener('keyup', function(event) { - event.stopPropagation(); - }, true); -} diff --git a/www/jssrc/blerg/API.js b/www/jssrc/blerg/API.js new file mode 100644 index 0000000..04e7ff9 --- /dev/null +++ b/www/jssrc/blerg/API.js @@ -0,0 +1,6 @@ +enyo.kind({ + name: "blerg.API", + create: function() { + this.inherited(arguments); + } +}); diff --git a/www/jssrc/blerg/Blerg.js b/www/jssrc/blerg/Blerg.js new file mode 100644 index 0000000..080e644 --- /dev/null +++ b/www/jssrc/blerg/Blerg.js @@ -0,0 +1,82 @@ +enyo.kind({ + name: "blerg.Blerg", + kind: "Control", + lastHash: null, + handlers: { + onStartSignup: "showSignupDialog", + onTryLogin: "tryLogin", + onSetTitle: "setTitle" + }, + components: [ + {classes: "blerg-header", components: [ + {kind: "blerg.Title"}, + {kind: "blerg.Controls"}, + {style: "clear: both"}, + {name: "post", kind: "blerg.Post", showing: false}, + {name: "help", kind: "blerg.Help"} + ]}, + {name: "main", kind: "blerg.Main"}, + {name: "signupDialog", kind: "blerg.SignupDialog"}, + {name: "passwdDialog", kind: "blerg.PasswdDialog"} + ], + urlmap: [ + ['search', /^\?post\/([^/]+)\/(.+)/, "blerg.ExternalURLPost"], + ['hash', /^#\/(ref|tag)\/([A-Za-z0-9_-]+)(?:\/p(\d+))?$/, "blerg.Tag"], + ['hash', /^#\/feed(?:\/p(\d+))?$/, "blerg.Feed"], + ['hash', /^#([A-Za-z0-9_-]+)(?:\/(p)?(\d+))?$/, "blerg.User"] + ], + pathHandlers: [ blerg.Welcome ], + rendered: function() { + this.inherited(arguments); + + this.lastHash = location.hash; + this.urlSwitch(); + + //setInterval(this.hashCheck.bind(this), 250); + + document.body.addEventListener('keyup', function(event) { + if (event.shiftKey && event.keyCode == 32) { + this.$.post.show(); + event.stopPropagation(); + } + }, false); + }, + hashCheck: function() { + if (location.hash != this.lastHash) { + this.lastHash = location.hash; + this.urlSwitch(); + } + }, + urlSwitch: function() { + var m; + var objdef = null; + + for (var i = 0; i < this.pathHandlers.length; i++) { + var handler = this.pathHandlers[i]; + objdef = handler.locationDetect(window.location); + if (objdef) + break; + } + if (!objdef) + objdef = {classes: "blerg-error", content: "No handler found"} + + this.$.main.updateView(objdef); + }, + showSignupDialog: function() { + this.$.signupDialog.show(); + }, + setTitle: function(inSender, inEvent) { + if (inEvent.section != undefined) + this.$.title.setSection(inEvent.section); + + if (inEvent.subscribed != undefined) + this.$.title.setSubscribed(inEvent.subscribed); + + if (inEvent.showControls) + this.$.title.showControls() + else + this.$.title.hideControls(); + }, + tryLogin: function(inSender, inEvent) { + } +}); diff --git a/www/jssrc/blerg/Controls.js b/www/jssrc/blerg/Controls.js new file mode 100644 index 0000000..4ef8a41 --- /dev/null +++ b/www/jssrc/blerg/Controls.js @@ -0,0 +1,61 @@ +enyo.kind({ + name: "blerg.Controls", + kind: "Control", + style: "float: right", + classes: "blerg-controls", + published: { + loggedIn: false + }, + components: [ + {name: "loggedOutControls", components: [ + {tag: "form", onsubmit: "doLogin", classes: "login", components: [ + {kind: "onyx.Groupbox", components: [ + {kind: "onyx.InputDecorator", components: [ + {name: "username", kind: "onyx.Input", placeholder: "Username"} + ]}, + {kind: "onyx.InputDecorator", components: [ + {name: "password", kind: "onyx.Input", placeholder: "Password", type: "password"} + ]}, + ]}, + {kind: "onyx.Button", content: "Login", onclick: "doLogin"} + ]} + ]}, + {name: "loggedInControls", showing: false, components: [ + {name: "greeting"}, + {kind: "onyx.Toolbar", components: [ + {kind: "onyx.Button", content: "Write", onClick: "writeClicked"}, + {kind: "onyx.Button", content: "Hearsay", onClick: "chatterClicked"}, + {kind: "onyx.Button", content: "Stalking", onClick: "feedClicked"} + ]}, + {components: [ + {name: "rssButton", showing: false, kind: "blerg.Link", components: [ + {kind: "Image", src: "/images/rss.png", width: 16, height: 16}, + {noDom: true, content: " RSS"} + ]} + ]} + ]} + ], + showRSS: function(url) { + this.$.rssButton.show(); + if (url) + this.$.rssButton.setAttribute('href', url); + }, + hideRSS: function() { + this.$.rssButton.hide(); + }, + loggedInChanged: function() { + if (this.loggedIn) { + this.$.loggedOutControls.hide(); + this.$.loggedInControls.show(); + } else { + this.$.loggedOutControls.show(); + this.$.loggedInControls.hide(); + } + }, + doLogin: function() { + this.bubble('onTryLogin', { + username: this.$.username.getValue(), + password: this.$.password.getValue() + }); + } +}); diff --git a/www/jssrc/blerg/Help.js b/www/jssrc/blerg/Help.js new file mode 100644 index 0000000..130b799 --- /dev/null +++ b/www/jssrc/blerg/Help.js @@ -0,0 +1,6 @@ +enyo.kind({ + name: "blerg.Help", + kind: "Control", + components: [ + ] +}); diff --git a/www/jssrc/blerg/Link.js b/www/jssrc/blerg/Link.js new file mode 100644 index 0000000..929e1a5 --- /dev/null +++ b/www/jssrc/blerg/Link.js @@ -0,0 +1,5 @@ +enyo.kind({ + name: "blerg.Link", + tag: "a", + attributes: {href:"#"} +}); diff --git a/www/jssrc/blerg/Main.js b/www/jssrc/blerg/Main.js new file mode 100644 index 0000000..6fc7bb1 --- /dev/null +++ b/www/jssrc/blerg/Main.js @@ -0,0 +1,16 @@ +enyo.kind({ + name: "blerg.Main", + kind: "Control", + classes: "blerg-main", + currentView: null, + updateView: function(objdef) { + if (!this.currentView || this.currentView.kind != this.currentView.kind) { + this.destroyComponents(); + this.currentView = this.createComponent(objdef); + this.currentView.render(); + } else { + for (var i in objdef) + this.currentView.setProperty(i, objdef[i]) + } + } +}); diff --git a/www/jssrc/blerg/PasswdDialog.js b/www/jssrc/blerg/PasswdDialog.js new file mode 100644 index 0000000..4eed325 --- /dev/null +++ b/www/jssrc/blerg/PasswdDialog.js @@ -0,0 +1,28 @@ +enyo.kind({ + name: "blerg.PasswdDialog", + kind: "onyx.Popup", + classes: "blerg-dialog", + autoDismiss: true, + centered: true, + floating: true, + modal: true, + components: [ + {tag: "h2", content: "Sign Up"}, + {kind: "onyx.Groupbox", components: [ + {kind: "onyx.InputDecorator", components: [ + {name: "password1", kind: "onyx.Input", placeholder: "Username", type: "password"} + ]}, + {kind: "onyx.InputDecorator", components: [ + {name: "password2", kind: "onyx.Input", placeholder: "Password", type: "password"} + ]} + ]}, + {kind: "onyx.Button", content: "Change", onclick: "changeClick", classes: "onyx.affirmative"}, + {kind: "onyx.Button", content: "Cancel", onclick: "cancelClick", classes: "onyx-negative"} + ], + changeClick: function() { + // Do stuff + }, + cancelClick: function() { + this.hide(); + } +}); diff --git a/www/jssrc/blerg/Post.js b/www/jssrc/blerg/Post.js new file mode 100644 index 0000000..6e120a0 --- /dev/null +++ b/www/jssrc/blerg/Post.js @@ -0,0 +1,27 @@ +enyo.kind({ + name: "blerg.Post", + kind: "Control", + classes: "blerg-post", + components: [ + {tag: "h2", content: "What's on your mind?"}, + {kind: "onyx.InputDecorator", components: [ + {name: "postContent", classes: "content", kind: "onyx.TextArea", onkeydown: "resizePostContent"} + ]}, + {classes: "buttons", components: [ + {kind: "onyx.Button", content: "Close", onclick: "closePost", classes: "onyx-negative"}, + {kind: "onyx.Button", content: "Post", onclick: "doPost", classes: "onyx-affirmative"} + ]} + ], + getData: function() { + return this.$.postContent.getValue(); + }, + setData: function(inVal) { + this.$.postContent.setValue(inVal); + }, + closePost: function() { + this.hide(); + }, + doPost: function() { + this.bubble('onPost', {data: this.getData()}); + } +}); diff --git a/www/jssrc/blerg/SignupDialog.js b/www/jssrc/blerg/SignupDialog.js new file mode 100644 index 0000000..c62108b --- /dev/null +++ b/www/jssrc/blerg/SignupDialog.js @@ -0,0 +1,28 @@ +enyo.kind({ + name: "blerg.SignupDialog", + kind: "onyx.Popup", + classes: "blerg-dialog", + autoDismiss: true, + centered: true, + floating: true, + modal: true, + components: [ + {tag: "h2", content: "Sign Up"}, + {kind: "onyx.Groupbox", components: [ + {kind: "onyx.InputDecorator", components: [ + {name: "username", kind: "onyx.Input", placeholder: "Username"} + ]}, + {kind: "onyx.InputDecorator", components: [ + {name: "password", kind: "onyx.Input", placeholder: "Password", type: "password"} + ]} + ]}, + {kind: "onyx.Button", content: "Signup", onclick: "signupClick", classes: "onyx-affirmative"}, + {kind: "onyx.Button", content: "Cancel", onclick: "cancelClick", classes: "onyx-negative"} + ], + signupClick: function() { + // Do stuff + }, + cancelClick: function() { + this.hide(); + } +}); diff --git a/www/jssrc/blerg/Title.js b/www/jssrc/blerg/Title.js new file mode 100644 index 0000000..8fa9dbc --- /dev/null +++ b/www/jssrc/blerg/Title.js @@ -0,0 +1,57 @@ +enyo.kind({ + name: "blerg.Title", + kind: "Control", + style: "float: left; width: 40%", + published: { + subscribed: null, + section: "" + }, + components: [ + {kind: "Image", classes: "logo", src: "images/blerglogo.png", attributes: {width: 125, height: 122}}, + {tag: "h1", components: [ + {kind: "blerg.Link", content: "Blërg!"} + ]}, + {tag: "h2", components: [ + {name: "section", tag: "span"} + ]}, + {name: "userControls", showing: false, components: [ + {kind: "blerg.Link", onclick: "clickChatter", content: "[chatter]"}, + {name: "subscribeLink", kind: "blerg.Link", onclick: "clickSubscribe", showing: false, content: "[stalk]"}, + {name: "unsubscribeLink", kind: "blerg.Link", onclick: "clickUnsubscribe", showing: false, content: "[stop stalking]"} + ]} + ], + create: function() { + this.inherited(arguments); + this.subscribedChanged(); + }, + clickChatter: function() { + this.bubble("onChatter"); + }, + clickSubscribe: function() { + this.bubble("onSubscribe"); + }, + clickUnsubscribe: function() { + this.bubble("onUnsubscribe"); + }, + subscribedChanged: function() { + if (this.subscribed == null) { + this.$.subscribeLink.hide(); + this.$.unsubscribeLink.hide(); + } else if (this.subscribed) { + this.$.subscribeLink.hide(); + this.$.unsubscribeLink.show(); + } else { + this.$.subscribeLink.show(); + this.$.unsubscribeLink.hide(); + } + }, + sectionChanged: function() { + this.$.section.setContent(this.section); + }, + showControls: function() { + this.$.userControls.hide(); + }, + hideControls: function() { + this.$.userControls.hide(); + } +}); diff --git a/www/jssrc/blerg/Welcome.js b/www/jssrc/blerg/Welcome.js new file mode 100644 index 0000000..f255fff --- /dev/null +++ b/www/jssrc/blerg/Welcome.js @@ -0,0 +1,46 @@ +enyo.kind({ + name: "blerg.Welcome", + statics: { + locationDetect: function(l) { + if (l.hash.match(/^(#\/?)?$/)) + return {kind: "blerg.Welcome"} + else + return false; + } + }, + components: [ + {components: [ + {style: "float: right; text-align: center; margin: 0 0 1em 1em", components: [ + {style: "font-size: 14pt; margin-bottom: 4pt", content: "Curious? Click this unbelievably obnoxious button!"}, + {kind: "onyx.Button", content: "I want to Blërg!", style: "font-size: 40pt; padding: 1em; background-color: #C0F; color: #F88", onclick: "startSignup"} + ]} + ]}, + {allowHtml: true, content: '

I am 12 and what is this

Blërg is a microblogging platform. Or maybe a miniblogging platform. Blërg is not sure. Blërg is a lot like Twitter, but aims to fix some of its idiosyncracies. Blërg does not want to be a full blogging platform like Wordpress or Livejournal. Blërg is also an open source tagged text database engine written in C that does the back-end work. Blërg\'s author finds it entertaining to anthropomorphize Blërg in the third person.

'}, + {name: "moreLink", kind: "blerg.Link", onclick: "loadMore", content: "Tell me more..."}, + {style: "clear: both"}, + {name: "contentBox", allowHtml: true}, + {tag: "h2", content: "Latest posts"}, + {name: "latestPosts"}, + {tag: "h2", content: "Latest tags"}, + {name: "latestTags"} + ], + rendered: function() { + this.inherited(arguments); + + this.bubble("onSetTitle", {section: "Welcome!"}); + }, + loadMore: function() { + var req = new enyo.Ajax({ + url: "/welcome.html", + handleAs: "text" + }); + req.response(function(inSender, inResponse) { + this.$.contentBox.setContent(inResponse); + this.$.moreLink.hide(); + }.bind(this)); + req.go(); + }, + startSignup: function() { + this.bubble('onStartSignup'); + } +}); diff --git a/www/jssrc/blerg/package.js b/www/jssrc/blerg/package.js new file mode 100644 index 0000000..764a0d0 --- /dev/null +++ b/www/jssrc/blerg/package.js @@ -0,0 +1,13 @@ +enyo.depends( + 'API.js', + 'Link.js', + 'Title.js', + 'Controls.js', + 'Post.js', + 'Help.js', + 'Main.js', + 'SignupDialog.js', + 'PasswdDialog.js', + 'Welcome.js', + 'Blerg.js' +); diff --git a/www/jssrc/package.js b/www/jssrc/package.js new file mode 100644 index 0000000..a1a20ce --- /dev/null +++ b/www/jssrc/package.js @@ -0,0 +1,4 @@ +enyo.depends( + 'onyx', + 'blerg' +); diff --git a/www/welcome.html b/www/welcome.html new file mode 100644 index 0000000..e053273 --- /dev/null +++ b/www/welcome.html @@ -0,0 +1,46 @@ + + +

But what's wrong with Twitter?

+ +

I'M GLAD YOU ASKED. There are two aspects of Twitter that just bug +me as an engineer:

+ +
    +
  1. Ruby on Rails - Using rails to prototype a system is +fine — scaling up to a million hits a day with it is just a bad +idea. As the service grew, I'm sure it cost them a lot more time than +it saved.
  2. +
  3. 140 characters is not enough - I routinely write +sentences longer than 140 characters, so I can't even begin to imagine +making a point in such a small space. This textual confinement has +led to the rise of URL shorteners, which are breaking the internet. +
+ +

Blërg solves these problems by applying absurd reactionary +engineering. Blërg's database backend is a custom C program that +handles requests over HTTP and stores data in a very small and +efficient indexed log-structured database. The frontend is done +entirely in client-side Javascript. A single post can be up to 65535 +bytes in length.

+ +

Which is not to say that I believe writing your service in C is the +solution to all your problems. Clearly, this approach has just as +many hairy problems that will bite you in the ass sooner or later. +The best way, as with most things, lies somewhere in the middle of +high-level abstraction and ZOMGHARDCORE OPTIMIZATION.

+ +

Is this a joke?

+ +

Yes. No. Maybe. Blërg is an exercise in constructive satire — a +fully functional service created in a fit of hubris to poke fun at Twitter's +engineering. It's just for fun, but no one is going to keep you from using +it seriously. :]

+ +

Tell me more about this database engine.

+ +

Here, take a look at the design docs.

+ +

I'm a social media whore and I want to share links!

+ +

I've created a bookmarklet just for you: Blërg it!

-- 2.25.1