Skip to content

Instantly share code, notes, and snippets.

@smith
Created January 23, 2009 02:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smith/50841 to your computer and use it in GitHub Desktop.
Save smith/50841 to your computer and use it in GitHub Desktop.
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Blog In A Browser</title>
<style>
body { font-family: Helvetica, Arial, sans-serif; margin: 0em; }
h1, h2, h3 { font-weight: normal; padding-left: 1em; }
textarea, a { display: block; }
#tabs { float: left; width: 100%; list-style: none; border-bottom: 1px solid; clear: both; }
#tabs li { float: left; }
#tabs li a { display: block; width: 80px; padding: 10px; text-decoration: none; text-align: center; border: 1px solid #000000; color: #ffffff; background-color: #000000; margin-bottom: -2px; }
#tabs li a.active { color: #000000; background-color: #ffffff; border 1px solid #ffffff; border-bottom: 2px solid #ffffff; }
#view, #manage { padding: 1em; }
</style>
</head>
<body>
<h1>Blog In A Browser</h1>
<ul id="tabs">
<li><a href="#view">View</a></li>
<li><a href="#manage">Manage</a></li>
</ul>
<div id="view"></div>
<div id="manage">
<div id="createPost">
<h2>New Post</h2>
<label for="createPostTitle">Title</label>
<input id="createPostTitle" />
<textarea id="createPostText" rows="10" cols="24"></textarea>
<button disabled id="createPostButton">Create Post</button>
</div>
<div id="managePostsList"></div>
</div>
<!-- Templates for content -->
<div id="templates" style="display:none;">
<div id="viewTemplate">
<h2>#{title}</h2>
<div class="date">#{created}</div>
<p>#{text}</p>
<div class="comments">#{comments}</div>
<h3>Leave A Comment</h3>
<div class="commentForm">
<label for="commentEmail_#{id}">Email (we will spam you)</label>
<input id="commentEmail_#{id}" />
<textarea id="commentText_#{id}" rows="10" cols="24"></textarea>
<button id="commentButton_#{id}">Save Comment</button>
</div>
</div>
<div id="commentTemplate">
<p>Comment from #{email} posted at #{created}</p>
<p>#{text}</p>
</div>
<div id="manageTemplate">
<div class="editPost">
<h2>Post #{id} <small>(#{created})</small></h2>
<a id="deletePostLink_#{id}" href="#">Delete</a>
<label for="editPostTitle_#{id}">Title</label>
<input id="editPostTitle_#{id}" value="#{title}" />
<textarea id="editPostText_#{id}" rows="10" cols="24">#{text}</textarea>
<button id="editPostButton_#{id}">Save Post</button>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/prototype/1.6.0.3/prototype.js"></script>
<script src="active_record.js"></script>
<script>
/*
* This is a simple example of ActiveRecord using Prototype.js
*
* @author Nathan L Smith
* @date January 22, 2009
*/
document.observe("dom:loaded", function () {
// Set up Active Record models
ActiveRecord.connect();
ActiveRecord.logging = true;
var Comment = ActiveRecord.define("comments", {
email: '',
text: '',
created : new Date()
});
var Post = ActiveRecord.define("posts", {
title: '',
text: '',
created : new Date()
});
Post.hasMany("comments");
// Functions for behavior
/** Very simple tab implementation */
function tabs() {
var tabLinks = $$("#tabs li a");
var linkOne = tabLinks[0];
var linkTwo = tabLinks[1];
var tabOne = $("view");
var tabTwo = $("manage");
// Start on tab 2
tabOne.hide();
linkTwo.addClassName("active");
$("tabs").observe("click", function (evt) {
evt.stop();
var a = evt.findElement('a');
if (a && a.innerHTML === "View") {
tabOne.show();
tabTwo.hide();
} else {
tabTwo.show();
tabOne.hide();
}
linkOne.toggleClassName("active");
linkTwo.toggleClassName("active");
});
}
/**
* When the create post form is submitted, a new post is created and saved.
*/
function createPost(evt) {
var p = new Post({
title : $("createPostTitle").value,
text : $("createPostText").value
});
p.save();
// Clear the form
$("createPostTitle").clear();
$("createPostText").clear();
}
/**
* Update the post when it is edited
*/
function editPost(evt) {
var id = getId(evt);
var post = Post.first({ id : id });
post.set('title', $("editPostTitle_" + id).value);
post.set('text', $("editPostText_" + id).value);
post.save();
}
/**
* Create both the 'view' and 'manage' lists from the data and templates
*/
function getList() {
var viewTemplate = $("viewTemplate").innerHTML;
var manageTemplate = $("manageTemplate").innerHTML;
var viewDiv = $("view");
var manageDiv = $("managePostsList");
var posts = Post.find({ all : true, order : "created DESC" });
// Clear existing content
viewDiv.update("");
manageDiv.update("");
posts.each(function (p) {
var commentTemplate = $("commentTemplate").innerHTML;
var comments = "";
// Add comment list
// FIXME: This adds comments to the wrong post.
p.getCommentList().each(function (c) {
comments += commentTemplate.interpolate(c);
});
p.comments = comments;
// Insert interpolated templates
viewDiv.insert(viewTemplate.interpolate(p));
manageDiv.insert(manageTemplate.interpolate(p));
// Observe events on newly inserted buttons
$("editPostButton_" + p.id).observe("click", editPost);
$("deletePostLink_" + p.id).observe("click", destroyPost);
$("commentButton_" + p.id).observe("click", addComment);
});
}
/**
* Remove a post
*/
function destroyPost(evt) {
var id = getId(evt);
var p = Post.first({ id : id });
p.destroy();
}
function addComment(evt) {
var id = getId(evt);
var post = Post.first({ id : id });
post.createComment({
email : $("commentEmail_" + id).value,
text : $("commentText_" + id).value
});
post.save();
}
/**
* When an event passed to this function originiated from an element with
* an id, return the number N after the _ in xxxx_N.
*/
function getId(evt) {
return Number((evt.element().id || "").gsub(/.*_/, "")) || 0;
}
// Handle events
$("createPostButton").observe("click", createPost);
Post.observe("afterSave", getList);
Post.observe("afterDestroy", getList);
// Start up
tabs();
$("createPostButton").disabled = false;
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment