Long Polling – tutorial, part 0

Fun with JS(ON) – don’t compute on server-side


The first thing we are going to do is generating our discussion tree, on that tree we’ll base our other functionalities like adding new posts and updating tree itself.

We’ll work on view.ctp view.

Let’s do some more cleanup. From view.ctp view remove div which class is “actions” – it’s basically the same on every view (index, edit and view). We’ll move it to element elements/posts/actions.ctp, and remove some links which are not needed (since it will view whole conversation rather than single post):

//views/elements/posts/actions.ctp

  • Html->link(sprintf(__('List %s', true), __('Posts', true)), array('action' => 'index')); ?>

We need to add jQuery library, so copy /cake/libs/view/layouts/default.ctp to /app/views/layouts/default.ctp and add jquery lib inside:



	
	

Now lets prepare scaffold of our view that will just show first message in discussion (just for now):

//views/posts/view.ctp

element("posts/actions") ?>

This is how we change view action in posts controller:

//posts_controller.php
	function view($id = null) {

		if (!$id) {
			$this->Session->setFlash(sprintf(__('Invalid %s', true), 'post'));
			$this->redirect(array('action' => 'index'));
		}
		$this->set('post', $this->Post->read(null, $id));
		$this->set(
         	'thread',
			$this->Post->children($id)
		);
	}

Now. We don’t want to generate tree structure of ul’s and li’s on the server side, so I just want to create js array containing the discussion, aviable on the site. I assume You have json extension in Your php. If yes – You can add this piece of code to view.ctp:

	

(if you dont want to use json extension you’ll need to generate that type of string: “[{“Post”:{“id”:”2″,”parent_id”:”1″,”user_id”:null,”lft”:”2″,”rght”:”5″,”message”:”my very first reply to the very first message!”,”modified”:”0000-00-00 00:00:00″}},{“Post”:{“id”:”4″,”parent_id”:”2″,”user_id”:null,”lft”:”3″,”rght”:”4″,”message”:”I think you shouldn’t make off-topics here”,”modified”:”0000-00-00 00:00:00″}},{“Post”:{“id”:”3″,”parent_id”:”1″,”user_id”:null,”lft”:”6″,”rght”:”7″,”message”:”I just have some opinion about first message, and will share it with you… soon.”,”modified”:”0000-00-00 00:00:00″}}]
” by yourself. If assistance is needed – please ask me in comment)

Now it’s time to play with javascript. Create file named /app/webroot/js/thread.js, link it in our default.ctp layout and please open it. We’ll do it in OOP style, so look out ;)

First of all – our object constructor:

(function(window, document, udefined){
	
	window.Thread = function(_posts) {
		this.posts = _posts;
		return this;
	};
	
})(window, document);

if You wander what’s (function(window, document, undefined){ })(window, document) means, please watch great video about 10 things that Paul Irish learned from jQuery source

Now, we can create our Thread object and pass our posts to it:

//views/layouts/default.ctp at the very bottom
	//...
	<script type="text/javascript">
		$(document).ready(function(){
			if(!window.posts) return false;
			window.thread = new Thread(posts);	
			console.log(thread);
		});
	</script>
	<?php echo $this->element('sql_dump'); ?>
	//...

Now we have our Thread object in thread var. Time to generate discussion tree:

//thread.js
Thread.prototype.createThread = function(){
	if(this.posts.length <1){
		return this;
	}
	$(this.posts).each(function(k, v){
		if($("#"+v.Post.parent_id).find("ul").length == 0){
                	$("
    ", {class: "posts children"}).appendTo("#"+v.Post.parent_id); } $("
  • ", { id: v.Post.id, innerHTML: "
    "+v.Post.message+"
    ", class: "post child" }). appendTo("#"+v.Post.parent_id+">ul"); }); return this; }

and update Thread object construction like that:

//views/layouts/default.ctp
window.thread = new Thread(posts).createThread();	

Now I’ll explain a little bit.

First of all, we’re able to chain methods, because every methot returns `this`. What is happening in createThread()?
If there’s no child posts, nothing happens. But if there is, first whay we do is to check if there’s ul container under message element we want to add children. If there isn’t any – we create it:

if($("#"+v.Post.parent_id).find("ul.children").length == 0){
	$("
    ", {class: "posts children"}).appendTo("#"+v.Post.parent_id); }

And in that container we add li elements with messages. It’s fast, because we do not traverse on any graph structure – just flat array of posts. We can do that because we are sure that every post is after it’s parent in this array.

In the next section we’ll implement reply functionality in our tree.Stay tuned for next partPlease take a look on the next part, where we implement reply functionality, and let me know if you liked this one.

Share Button