Long Polling, tutorial – cześć 1

Wyślij się!


Formularz juś się pokazuje, teraz trzeba go zachęcić, żeby “wysłał się” na serwer.

Jako, że jest to dość proste zadanie, skomplikujmy je sobie nieco (w końcu chcemy się czegoś nauczyć). Chcę rozszerzyć bibliotekę jQuery tak, żebym mógł wywołać metodę ajaxMe() dla elementów “złapanych” przy pomocy selektora jQuery (np. tak: $(“.some-forms”).ajaxMe()) skutkiem wywołania tej metody będzie to, że każdy ze “złapanych” formularzy, po kliknięciu submit zostanie wysłany na serwer ajaxem.

Zacznijmy od kodu, który rozszerzy bibliotekę jQuery. Ważną sprawą jest to, że skrypt ten powinien być ładowany po plikach jQuery. Jeśli w Twoim wypadku jest inaczej – przenieś includowanie thread.js.

Dodaj tą metodę do thread.js:

/app/webroot/thread.js
Thread.prototype.extendJQuery = function(callback){
	jQuery.fn.extend({
		ajaxMe: function(callback){
			jQuery(this).each(function(k, e){
				if(!jQuery(e).is("form")){
					e = $(e).find("form").ajaxMe();
				}else{
					$(e).submit(function(){
						$.ajax({
							url: this.action,
							type: this.method,
							data: $(this).serialize(),
							success: function(){window.location.reload();}
						});
						return false;
					});
				}
			});
			return this;
		}
	});
};

(proszę, nie zwracaj na razie uwagi na fragment window.location.reload – to jest tymaczsowe rozwiązanie, zmienimy to w następnej części tutoriala)
oraz uaktualnij konstruktor klasy Thread, żeby wywoływał metodę extendJQuery():

//wpp/webroot/thread.js
(function(window, document, udefined){
	window.Thread = function(_posts) {
		this.posts = _posts;
		this.extendJQuery(); //< -
		return this;	
	};
	
})(window, document);

Już prawie gotowe. Zachęćmy teraz nasz sklonowany formulaż, aby wysyłał się ajaxem, oraz ustawmy pole parent_id odpowiednio. Thread.createReplyDiv() powinien wyglądać mniej więcej tak:

// /webroot/js/thread.js
Thread.prototype.createReplyDiv = function(){
	return $("<div>", {class: "reply"}).bind(
		"click", function(){
			$("#add-form-template").find("div.posts").clone().appendTo(this);
			$(this).addClass("reply-extended").
				unbind("click").
				ajaxMe(). // < -
				find("input[name='data[Post][parent_id]']").val(this.parentNode.id); //< -
		}
	);
}

Ostatnia rzecz - jeśli skontrolujemy request XHR po kliknięciu 'submit' (na przykład przy pomocy firebuga) zobaczymy, że lecą dwa zapytania: posts/add oraz posts/(index). Spowodowane jest to redirect'em w akcji add(). Zacznijmy od teraz jawnie obsługiwać żądania (przynajmniej w tym miejscu). Dodajmy komponent

	var $components = array("RequestHandler");

do PostsController, oraz uaktualnijmy akcję add() w następujący sposób:

	function add() {
		if (!empty($this->data)) {
			$this->Post->create();
			if ($this->Post->save($this->data)) {
				$this->Session->setFlash(__('The post has been saved', true));
				if(!$this->RequestHandler->isAjax()){ //< ---
                    $this->redirect(array('action' => 'index')); //< --
				} //< --
			} else {
				$this->Session->setFlash(__('The post could not be saved. Please, try again.', true));
			}
		}
		$this->render("edit");
	}

Teraz akcja add() nie wysyła nagłówków do wykonania redirecta, jeśli żądanie przyszło ajaxem.

Teraz możemy umieszczać odpowiedzi w dyskusji. Czas zając się pobieraniem nowych wiadomości w miarę jak się będą pojawiać. Zajmiemy się tym w następnej części, gdzie użyjemy techniki long polling

Share Button

Leave a Reply

Your email address will not be published. Required fields are marked *