<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>webbricks &#187; jQuery</title>
	<atom:link href="http://blog.grzegorzpawlik.com/tag/jquery/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.grzegorzpawlik.com</link>
	<description>Doświadczenie, to coś, co zdobywamy tuż po chwili w której było nam potrzebne ...</description>
	<lastBuildDate>Tue, 07 Feb 2012 10:09:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Pubsub – super prosty i super ciekawy plugin jQuery</title>
		<link>http://blog.grzegorzpawlik.com/2010/11/pubsub-super-prosty-i-super-ciekawy-plugin-jquery/</link>
		<comments>http://blog.grzegorzpawlik.com/2010/11/pubsub-super-prosty-i-super-ciekawy-plugin-jquery/#comments</comments>
		<pubDate>Tue, 30 Nov 2010 14:28:22 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[JS and friends]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://blog.grzegorzpawlik.com/?p=1434</guid>
		<description><![CDATA[https://github.com/phiggins42/bloody-jquery-plugins/blob/master/pubsub.js Plugin pubsub, którego pierwowzorem była funkcjonalność frameworka Dojo. Służy do rejestracji i publikacji zdarzeń w naszej aplikacji (nie chodzi o eventy DOM). Dzięki czemu w niektórych przypadkach może udać się zmniejszyć ilość ścisłych powiązań w kodzie (coupling). Zresztą trudno &#8230; <a href="http://blog.grzegorzpawlik.com/2010/11/pubsub-super-prosty-i-super-ciekawy-plugin-jquery/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="https://github.com/phiggins42/bloody-jquery-plugins/blob/master/pubsub.js">https://github.com/phiggins42/bloody-jquery-plugins/blob/master/pubsub.js</a></p>
<p>Plugin pubsub, którego pierwowzorem była funkcjonalność frameworka <a href="http://www.dojotoolkit.org/">Dojo</a>. Służy do rejestracji i publikacji zdarzeń w naszej aplikacji (nie chodzi o eventy DOM). Dzięki czemu w niektórych przypadkach może udać się zmniejszyć ilość ścisłych powiązań w kodzie (coupling). Zresztą trudno to wyjaśnić pisząc tekst po polsku&#8230; zachęcam zatem do obejrzenia filmy Rebeki Murphey z <a href="http://net.tutsplus.com/tutorials/javascript-ajax/loose-coupling-with-the-pubsub-plugin/?utm_source=feedburner&#038;utm_medium=feed&#038;utm_campaign=Feed%3A+nettuts+%28Nettuts%2B%29">nettuts</a> (polecam jakość HD i fullscreen):</p>
<p><embed src="http://blip.tv/play/gcMVgoiTQQI%2Em4v" type="application/x-shockwave-flash" width="625" height="450" allowscriptaccess="always" allowfullscreen="true"></embed></p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.grzegorzpawlik.com/2010/11/pubsub-super-prosty-i-super-ciekawy-plugin-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>sammy.js</title>
		<link>http://blog.grzegorzpawlik.com/2010/11/sammy-js/</link>
		<comments>http://blog.grzegorzpawlik.com/2010/11/sammy-js/#comments</comments>
		<pubDate>Thu, 04 Nov 2010 09:53:54 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[JS and friends]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://blog.grzegorzpawlik.com/?p=1422</guid>
		<description><![CDATA[Świetny plugin do jQuery. A właściwie można by go nazwać frameworkiem rozszerzającym możliwości frameworka jQuery ;) Pozwala na zorganizowanie aplikacji intensywnie wykorzystującej Ajax tak, żeby nie tracić działania przycisku wstecz i w ogóle historii przeglądania. Mnie ostatnio przydało się, gdy &#8230; <a href="http://blog.grzegorzpawlik.com/2010/11/sammy-js/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Świetny plugin do jQuery. A właściwie można by go nazwać frameworkiem rozszerzającym możliwości frameworka jQuery ;)</p>
<p>Pozwala na zorganizowanie aplikacji intensywnie wykorzystującej Ajax tak, żeby nie tracić działania przycisku wstecz i w ogóle historii przeglądania. </p>
<p>Mnie ostatnio przydało się, gdy musiałem dorobić stronę w stronie i nie bardzo miałem ochotę grzebać w mechanizmach php, które tam zachodzą. Po prostu każdy link w podmenu ładuje treść ajaxem i każda taka strona ma swój własny link.</p>
<p>Polecam super krótki tutorial na nettuts, który pokaże Wam jak zacząć:<br />
<a href="http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-an-introduction-to-sammy-js/">http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-an-introduction-to-sammy-js/</a></p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.grzegorzpawlik.com/2010/11/sammy-js/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Long Polling, tutorial – cześć 1</title>
		<link>http://blog.grzegorzpawlik.com/2010/09/long-polling-tutorial-czesc-1/</link>
		<comments>http://blog.grzegorzpawlik.com/2010/09/long-polling-tutorial-czesc-1/#comments</comments>
		<pubDate>Mon, 20 Sep 2010 17:30:44 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[JS and friends]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://blog.grzegorzpawlik.com/?p=1222</guid>
		<description><![CDATA[(poprzednia część tego tutoriala) Teraz, kiedy mamy wygenerowane drzewo dyskusji, następnym krokiem będzie umożliwienie odpowiedzi w wątku. Użytkownik powinien móc kliknąć pod konkretną wypowiedzią i natychmiast zacząć wpisywać odpowiedź. Dlatego pod każdym elementem li.post utwórzmy div&#8217;a, którym będzie konterem dla &#8230; <a href="http://blog.grzegorzpawlik.com/2010/09/long-polling-tutorial-czesc-1/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="/?p=1189">(poprzednia część tego tutoriala)</a><br />
<!--pagetitle:Placeholder dla formularza odpowiedzi--><br />
Teraz, kiedy mamy wygenerowane drzewo dyskusji, następnym krokiem będzie umożliwienie odpowiedzi w wątku. Użytkownik powinien móc kliknąć pod konkretną wypowiedzią i natychmiast zacząć wpisywać odpowiedź.<br />
<span id="more-1222"></span></p>
<p>Dlatego pod każdym elementem li.post utwórzmy div&#8217;a, którym będzie konterem dla formularza odpowiedzi. Znajdź w thread.js linie odpowiedzialne za tworzenie elementów li zawierających posty i dodaj html z div&#8217;em do parametru innerHTML:</p>
<pre name="code" class="javascript">
//app/webroot/js/thread.js
$("
<li>", {
	    	  id: v.Post.id,
	    	  innerHTML: "
<div>"+v.Post.message+"</div>

" +
	    	  			 "
<div class='reply' />" //<---
	    	  ,
	 class: "post child"
	 }).
	 appendto("#"+v.post.parent_id+">ul");
</pre>
<p>Przyda się teraz nieco css&#8217;ów. Kontener powinien zajmować nieco więcej miejsca (żeby łatwiej było w  niego kliknąć) oraz po najechaniu na niego myszką powinien zmienić kolor, sugerując użytkownikowi, że może tam kliknąć. Podlinkuj nowy plik css do layoutu:</p>
<pre name="code" class="php">
//app/views/layouts/default.ctp
echo $this->Html->css('cake.generic');
echo $this->Html->css('thread'); //<-add this
echo $this->Javascript->link(array("thread"));
</pre>
<p>a następnie stwórz plik thread.css z taką zawartością:</p>
<pre name="code" class="css">
/* app/webroot/css/thread.css */
div.reply {
	height: 5px;
	cursor: text;
}
div.reply:hover{
	background-color: #8EAFEB;
}
</pre>
<p>
Tak to powinno wyglądać teraz:<br />
<img src="http://blog.grzegorzpawlik.com/wp-content/uploads/2010/09/replyplaceholder.png" alt="" title="replyplaceholder" width="708" height="274" class="alignnone size-full wp-image-1211" />
</p>
<p>Bardziej spostrzegawczy zauważyli od razu, że miejsce pod pierwszą wypowiedzią w wątku nie zachowuje się tak jak powinno, poprawmy nieco thread.js:</p>
<pre name="code" class="javascript">
if($("#"+v.Post.parent_id).find("ul").length == 0){
	if($("#"+v.Post.parent_id).find("div.reply").length == 0){
		$("
<div>", {class: "reply"}).appendTo("#"+v.Post.parent_id);
	}
	$("
<ul>", {class: "posts children"}).appendTo("#"+v.Post.parent_id);
}
</pre>
<p>Teraz pojawiło nam się odrobinę redundancji w kodzie &#8211; dwa miejsca, gdzie jest tworzony element div.reply. Naprawmy to. Usuniemy dodawanie stringa</p>
<pre>
&lt;div class='reply'/&gt;
</pre>
<p>i zastąpimy go tworzeniem elementu DOM przy pomocy jQuery, a następnie wyekstrahujemy motodę, która to robi. Ostatecznie kod powinien wyglądać tak:</p>
<pre name="code" class="javascript">
(function(window, document, udefined){
	window.Thread = function(_posts) {
		this.posts = _posts;
		return this;
	};
})(window, document);

Thread.prototype.createReplyDiv = function(){
	return $("
<div>", {class: "reply"});
}

Thread.prototype.createThread = function(){
	if(this.posts.length <1){
		return this;
	}
	var _this = this; //* patrz poniżej
	$(this.posts).each(function(k, v){
		if($("#"+v.Post.parent_id).find("ul").length == 0){
			if($("#"+v.Post.parent_id).find("div.reply").length == 0){
				_this.createReplyDiv().appendTo("#"+v.Post.parent_id);
			}
	        $("
<ul>", {class: "posts children"}).appendTo("#"+v.Post.parent_id);
		}
	     $("
<li>", {
	    	  id: v.Post.id,
	    	  innerHTML: "
<div>"+v.Post.message+"</div>

"
	    	  ,
	    	  class: "post child"
	     }).
	     append(_this.createReplyDiv()).
	     appendTo("#"+v.Post.parent_id+">ul");
	});
	return this;
}
</pre>
<p>(*)Jeśli zastanawiasz się po co zapamiętujemy `this` w zmiennej `_this` śpieszę z wyjaśnieniem. W kodzie chcemy wywołać, wyodrębnioną dopiero co, metodę createReplyDiv. Niestety w anonimowej funkcji, która jest przekazana do metody each(), `this` wskazuje już na konkretny element z kolekcji po której ów each() iteruje. Musimy zapamiętać &#8220;starą&#8221; referencję `this` (czyli obiekt klasy Thread).</p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.grzegorzpawlik.com/2010/09/long-polling-tutorial-czesc-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Long Polling &#8211; tutorial, part 0</title>
		<link>http://blog.grzegorzpawlik.com/2010/09/long-polling-tutorial-part-0/</link>
		<comments>http://blog.grzegorzpawlik.com/2010/09/long-polling-tutorial-part-0/#comments</comments>
		<pubDate>Fri, 10 Sep 2010 17:00:31 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Inne]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://blog.grzegorzpawlik.com/?p=1158</guid>
		<description><![CDATA[I was encouraged by good response on my first tutorial, so started to work on another. Unfortunately I didn&#8217;t finish it before my vacation, so I almost lost track of what I was doing. So I decided to ship it &#8230; <a href="http://blog.grzegorzpawlik.com/2010/09/long-polling-tutorial-part-0/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<blockquote><p>I was encouraged by good response on <a href="/?p=815">my first tutorial</a>, so started to work on another. Unfortunately I didn&#8217;t finish it before my vacation, so I almost lost track of what I was doing. So I decided to ship it to you in parts, so by doing every part before publishing I&#8217;ll be back on track, and find more mistakes, so hopefully it will be error-free. Enjoy. </p></blockquote>
<p><!--pagetitle:idea and basic preparations--></p>
<h4>What&#8217;s long pooling</h4>
<p>Long pooling is one of the method that mimics &#8220;<a href="http://en.wikipedia.org/wiki/Push_technology">server push</a>&#8221; behavior on stateless HTTP protocol (which is based on &#8220;server pull&#8221; principle) . Even though there are <a href="http://hacks.mozilla.org/2010/04/websockets-in-firefox/">web sockets</a> coming, I think it&#8217;s a good idea to get familiar with that kind of technique. </p>
<p>We&#8217;ll try to create just a bit of simple idea. Combination of chat and bulletin board, where You can post Your messages and can see other users messages appearing in &#8220;real time&#8221;.</p>
<p>We&#8217;ll do it with <a href="http://cakephp.org/">cakePHP</a>  on the server side and http://jquery.com/ on the client side. I assume You are a little bit familiar with that tools &#8211; I wouldn&#8217;t explain how to configure database connection in cakePHP etc.</p>
<p>The only features on this system are</p>
<ul>
<li>creating new discussion</li>
<li>replying in a discussion without reloading a page</li>
<li>getting users to see other people replies without reloading the page</li>
</ul>
<p>on top of that we&#8217;ll keep in mind that we are on small budget, so we want our application to be as light for the server as possible (to do that we&#8217;ll push as much work to client side as we can).</p>
<h4>Preparing project</h4>
<p>Let&#8217;s get last stable version of cake to get started fast:</p>
<pre>
$ git clone http://github.com/cakephp/cakephp.git longPolling
</pre>
<p>Then let&#8217;s create a database for our discussions</p>
<pre name="code" class="sql">
CREATE TABLE `posts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parent_id` int(11) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL,
  `lft` int(11) DEFAULT NULL,
  `rght` int(11) DEFAULT NULL,
  `message` text COLLATE utf8_unicode_ci NOT NULL,
  `modified` datetime NOT NULL,
  UNIQUE KEY `id` (`id`),
  KEY `parent_id` (`parent_id`),
  KEY `lft` (`lft`),
  KEY `rght` (`rght`),
  KEY `user_id` (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
</pre>
<p>As You can see, we&#8217;ll use &#8220;<a href="http://dev.mysql.com/tech-resources/articles/hierarchical-data.html">Nested set model</a>&#8221; which is implemented by <a href="http://book.cakephp.org/view/91/Tree">Treebehavior</a>. For maximum simplicity discussions don&#8217;t have topics and so, and to start discussion one should just post first message outside of any discussion.</p>
<p>Let&#8217;s bake model, controller and views for CRUD &#8211; this will be a foundation we&#8217;ll be working on. Just don&#8217;t mind validation and associations, neither admin routing &#8211; it&#8217;s not crucial to the topic. Add Tree behavior to Post model.</p>
<h4>Cleanup</h4>
<p>Now, we have some mess in our code already. `add` and `edit` views duplicate themselves, so I&#8217;ll remove `add` view and force PostsController::add() to render `edit` view:</p>
<pre name="code" class="php">
//posts_controller.php
	function add() {
		if (!empty($this->data)) {
			$this->Post->create();
			if ($this->Post->save($this->data)) {
				$this->Session->setFlash(__('The post has been saved', true));
				$this->redirect(array('action' => 'index'));
			} else {
				$this->Session->setFlash(__('The post could not be saved. Please, try again.', true));
			}
		}
		$this->render("edit");
	}
</pre>
<p>and, just to make it not look silly &#8211; surround code that generates &#8220;delete&#8221; link with one if statement:</p>
<pre name="code" class="php">
		&lt;?php if(!empty($this->data["Post"]["id"])): ?&gt;
			&lt;li><?php echo $this->Html->link(__('Delete', true), array('action' => 'delete', $this->Form->value('Post.id')), null, sprintf(__('Are you sure you want to delete # %s?', true), $this->Form->value('Post.id'))); ?&gt;</li>

		&lt;?php endif; ?>
</pre>
<p>To finally polish it &#8211; remove user_id, lft, rght, modified fields from the form (because there will be automatically filled).</p>
<p>Oh! I almost forgot, to be able to pick some of the existing topics as parent for message you are adding &#8211; create that method in PostsController and call it in add and edit actions:</p>
<pre name="code" class="php">
//posts_controller.php
function _getParentPosts(){
	$this->set('parents', $this->Post->find("list"));
}
</pre>
<p>Now create at least one discussion, so we can start working on some stuff. If it&#8217;s not fun for You just run this query:</p>
<pre name="code" class="sql">
INSERT INTO `posts` VALUES (1,NULL,NULL,1,8,'first message in the topic.','0000-00-00 00:00:00'),
(2,1,NULL,2,5,'my very first reply to the very first message!','0000-00-00 00:00:00'),
(3,1,NULL,6,7,'I just have some opinion about first message, and will share it with you... soon.','0000-00-00 00:00:00'),
(4,2,NULL,3,4,'I think you shouldn\'t make off-topics here','0000-00-00 00:00:00');
</pre>
<p>Now we&#8217;re up and running, and ready for the fun stuff.</p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.grzegorzpawlik.com/2010/09/long-polling-tutorial-part-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wyłączenie &#8220;submit&#8221; na czas działania zapytania Ajax</title>
		<link>http://blog.grzegorzpawlik.com/2010/07/wylaczenie-submit-na-czas-dzialania-zapytania-ajax/</link>
		<comments>http://blog.grzegorzpawlik.com/2010/07/wylaczenie-submit-na-czas-dzialania-zapytania-ajax/#comments</comments>
		<pubDate>Mon, 12 Jul 2010 16:00:39 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Inne]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[quick-tip]]></category>

		<guid isPermaLink="false">http://blog.grzegorzpawlik.com/?p=1068</guid>
		<description><![CDATA[Często spotykam się z tym ostatnio w pracy &#8211; jakieś dodatkowe listy są ładowane do formularza i póki się nie załadują `submit` powinien pozostać nieaktywny. Kod: jQuery("body").ajaxStart(function(){ $(".disable-on-xhr").attr("disabled", "disabled"); }); jQuery("body").ajaxStop(function(){ $(".disable-on-xhr").attr("disabled", ""); }); /** * w niektórych przypadkach możesz &#8230; <a href="http://blog.grzegorzpawlik.com/2010/07/wylaczenie-submit-na-czas-dzialania-zapytania-ajax/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Często spotykam się z tym ostatnio w pracy &#8211; jakieś dodatkowe listy są ładowane do formularza i póki się nie załadują `submit` powinien pozostać nieaktywny.</p>
<p>Kod:</p>
<pre name="code" class="javascript">
jQuery("body").ajaxStart(function(){
  $(".disable-on-xhr").attr("disabled", "disabled");
});
jQuery("body").ajaxStop(function(){
  $(".disable-on-xhr").attr("disabled", "");
});

/**
* w niektórych przypadkach możesz też chieć odblokować
* submit gdy zapytanie xhr się nie powiedzie
**/
jQuery("body").ajaxError(function(){
  $(".disable-on-xhr").attr("disabled", "");
});
</pre>
<p>Teraz wystarczy przyciskom submit dodać class=&#8221;disable-on-xhr&#8221; i smiga.</p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.grzegorzpawlik.com/2010/07/wylaczenie-submit-na-czas-dzialania-zapytania-ajax/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>10 things that Paul Irish learned from jQuery source (and sharing)</title>
		<link>http://blog.grzegorzpawlik.com/2010/06/10-things-that-paul-irish-learned-from-jquery-source-and-sharing/</link>
		<comments>http://blog.grzegorzpawlik.com/2010/06/10-things-that-paul-irish-learned-from-jquery-source-and-sharing/#comments</comments>
		<pubDate>Tue, 22 Jun 2010 10:43:41 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Inne]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://blog.grzegorzpawlik.com/?p=1031</guid>
		<description><![CDATA[I just need to put it on this blog. It may not be the best organized video, but the content is great and interesting. Enjoy.]]></description>
			<content:encoded><![CDATA[<p>I just need to put it on this blog. It may not be the best organized video, but the content is great and interesting. Enjoy.</p>
<p><object width="601" height="338"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=12529436&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=12529436&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="601" height="338"></embed></object></p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.grzegorzpawlik.com/2010/06/10-things-that-paul-irish-learned-from-jquery-source-and-sharing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>10 rzeczy, których Paul Irish nauczył się z kodu źródłowego jQuery</title>
		<link>http://blog.grzegorzpawlik.com/2010/06/10-rzeczy-ktorych-paul-irish-nauczyl-sie-z-kodu-zrodlowego-jquery/</link>
		<comments>http://blog.grzegorzpawlik.com/2010/06/10-rzeczy-ktorych-paul-irish-nauczyl-sie-z-kodu-zrodlowego-jquery/#comments</comments>
		<pubDate>Tue, 22 Jun 2010 10:41:38 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Inne]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://blog.grzegorzpawlik.com/?p=1025</guid>
		<description><![CDATA[Wpadłem na to i koniecznie muszę Wam to pokazać. Może nie jakoś super zorganizowana prezentacja ale treść jest naprawdę interesująca. Polecam!]]></description>
			<content:encoded><![CDATA[<p>Wpadłem na to i koniecznie muszę Wam to pokazać. Może nie jakoś super zorganizowana prezentacja ale treść jest naprawdę interesująca. Polecam!</p>
<p><object width="601" height="338"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=12529436&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=12529436&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="601" height="338"></embed></object></p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.grzegorzpawlik.com/2010/06/10-rzeczy-ktorych-paul-irish-nauczyl-sie-z-kodu-zrodlowego-jquery/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tutorial: dashboard web 2.0 dla leniwych&#8230;</title>
		<link>http://blog.grzegorzpawlik.com/2010/02/tutorial_dashboard_web_2-0_dla_leniwyc/</link>
		<comments>http://blog.grzegorzpawlik.com/2010/02/tutorial_dashboard_web_2-0_dla_leniwyc/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 14:15:26 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[DRY]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://blog.grzegorzpawlik.com/?p=706</guid>
		<description><![CDATA[&#8230; czyli dobrych programistów ;) W moim pierwszym tutorialu napiszę jak wydajnie korzystać z tego co daje Ci cakePHP i jQuery. Aktualnie cake opiera się na współpracy z innym frameworkiem javascript &#8211; prototype. Ale już w wersji 1.3 core cake&#8217;a &#8230; <a href="http://blog.grzegorzpawlik.com/2010/02/tutorial_dashboard_web_2-0_dla_leniwyc/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><!--pagetitle:start--><br />
&#8230; <a href="/?p=29">czyli dobrych programistów</a> ;)</p>
<p>W moim pierwszym tutorialu napiszę jak wydajnie korzystać z tego co daje Ci cakePHP i jQuery. Aktualnie cake opiera się na współpracy z innym frameworkiem javascript &#8211; prototype. Ale już w wersji 1.3 <a href="http://cakephp.lighthouseapp.com/projects/42648-cakephp-1x/milestones/57813-130">core cake&#8217;a ma współpracować z jquery</a>. Już nie mogę się doczekać. Ten tutorial oparłem na wersji 1.3.0-beta dlatego, że przy okazji jego pisania chciałem rzucić okiem na kolejną wersję tego świetnego frameworka php. Jednak nie będę korzystał z żadnych helperów jquery, zatem większość z tych rad powinna pasować do wersji 1.2 (w razie problemów &#8211; <a href="#tab-1">chętnie służę pomocą</a>).<br />
Jest to mój pierwszy tutorial, więc proszę o wskazówki, <a href="#tab-1">komentarze</a> i odrobinę wyrozumiałości.</p>
<p>Efekt jaki chcemy osiągnąć można obejrzeć jako <a href="http://cakephp.grzegorzpawlik.com/tutorial1/">demo</a> oraz <a href="http://cakephp.grzegorzpawlik.com/tutorial1/src.tar.gz">źródła</a> na świetnym hostingu, który gorąco wszystkim <a href="/?p=324">webdeveloperom</a> i ich <a href="/?p=413">klientom</a> polecam: <a href="http://meta.vipserv.org/cakephp/tutorial1/">vipserv.org</a>.</p>
<p>W tym tekście zakładam, ze znasz podstawy cakePHP i javascript. Czyli przynajmniej zrobiłeś sławny <a href="http://book.cakephp.org/view/219/Blog">blog tutorial </a>, wiesz jak mniej więcej używać narzędzia bake, oraz potrafisz przynajmniej zniknąć element na stronie i zmienić jego kolor przy pomocy czystego javascript&#8217;u.</p>
<h3>Dashboard na zakładkach</h3>
<p>Zacznijmy od przygotowania przykładowej aplikacji. Wypiekamy (cake bake) aplikację złożoną z dwóch modeli Thing i Item (każda tabela składa się z id i pola tekstowego name).</p>
<p>Następnie tworzymy dla niej zbiorczy widok (tzw. dashboard, metoda all())</p>
<pre name="code" class="php">
// /app/controllers/items_controller.php
class ItemsController extends AppController {
 //...
 function all() {}
}
</pre>
<pre name="code" class="php">
// /app/views/items/all.ctp
&lt;?php echo $this-&gt;requestAction(
            array(
               "controller"=&gt; "items",
               "action"=&gt; "index"),
            array("return")
      ); ?&gt;
&lt;?php echo $this-&gt;requestAction(
            array(
               "controller"=&gt; "things",
               "action"=&gt; "index"),
            array("return")
      ); ?&gt;
</pre>
<p>Na razie nie przejmujcie się kwestią requestAction i wydajności. Zazwyczaj efekty requestAction należy umieszczać w cache&#8217;owanych elementach, ale w naszym przypadku już niedługo zrezygnujemy z samego requestAction.</p>
<div id="attachment_709" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.grzegorzpawlik.com/wp-content/uploads/2010/02/zbiorczy_widok1-e1266927750988.png" rel="lightbox[706]" title="zbiorczy_widok1"><img src="http://blog.grzegorzpawlik.com/wp-content/uploads/2010/02/zbiorczy_widok1-300x142.png" alt="widok zbiorczy - dashboard" title="zbiorczy_widok1" width="300" height="142" class="size-medium wp-image-709" /></a><p class="wp-caption-text">tak to wygląda teraz</p></div>
<p>Zróbmy z tego widoku zakładki modyfikując widok all.ctp w następujący sposób:</p>
<pre name="code" class="php">
&lt;script type="text/javascript"&gt;
   $(document).ready(function() {
      $("#tabs").tabs();
   });
&lt;/script&gt;

&lt;div id="tabs"&gt;
   &lt;ul&gt;
      &lt;li&gt;&lt;a href="#tabs-1"&gt;Items&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href="#tabs-2"&gt;Things&lt;/a&gt;&lt;/li&gt;
   &lt;/ul&gt;
   &lt;div id="tabs-1"&gt;
      &lt;?php echo $this-&gt;requestAction(
                  array(
                     "controller"=&gt; "items",
                     "action"=&gt; "index"),
                  array("return")
            ); ?&gt;
   &lt;/div&gt;
   &lt;div id="tabs-2"&gt;
      &lt;?php echo $this-&gt;requestAction(
                  array(
                     "controller"=&gt; "things",
                     "action"=&gt; "index"),
                  array("return")
            ); ?&gt;
   &lt;/div&gt;
&lt;/div&gt;
</pre>
<p>Żeby wypieczone widoki były &#8220;otoczone&#8221; ramką z zakładki &#8211; trzeba w nich dodać taki fragment na samym końcu plików index.ctp:</p>
<pre name="code" class="html">
&lt;div style="float: none; clear: both;"&gt;&amp;nbsp;&lt;/div&gt;
</pre>
<div id="attachment_718" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.grzegorzpawlik.com/wp-content/uploads/2010/02/zakładki_1-e1266927904106.png" rel="lightbox[706]" title="zakładki_1"><img src="http://blog.grzegorzpawlik.com/wp-content/uploads/2010/02/zakładki_1-300x91.png" alt="Widok zakładek" title="zakładki_1" width="300" height="91" class="size-medium wp-image-718" /></a><p class="wp-caption-text">tak wyglądają nasze zakładki</p></div>
<p>Dodajmy więcej elementów, żeby zobaczyć jak zachowuje się pagination&#8230;</p>
<pre name="code" class="sql">
insert into items(`name`) values ('Item 4'), ('Item 5'), ('Item 6'), ('Item 7')
</pre>
<p>i zmieńmy parametry stronicowania, żeby efekty stronicowania zobaczyć szybko ;)</p>
<pre name="code" class="php">
class ItemsController extends AppController {
//...
	var $paginate = array(
	  'limit'=> 5
	);
//...
</pre>
<p>Widzimy, że w naszym zbiorczym widoku link ciągle prowadzi do items/index. Wolelibyśmy, żeby stronicowanie odbyło się w zakładkach.</p>
<p>Można oczywiście próbować rozwiązania via php. Oprogramować obsługę parametrów w metodzie all(), zmienić cel linków stronicowania i sortowania w widokach. I ogólnie dużo napracować się nad tym, żeby nasz kod wyglądał źle ;). Już za chwilę <strong>moc javascript i w szczególności jQuery przyjdzie nam z pomocą</strong>. Zanim to nastąpi &#8211; zamieńmy nasze zakładki na Ajaxowe zmieniając widok all.ctp:</p>
<pre name="code" class="php">
// views/items/all.ctp
&lt;script type="text/javascript"&gt;
   $(document).ready(function() {
      $("#tabs").tabs();
   });
&lt;/script&gt;

&lt;div id="tabs"&gt;
   &lt;ul&gt;
      &lt;li&gt;
         &lt;?php echo $html-&gt;link(
                  "Items",
                  array(
                     "controller"=&gt; "items",
                     "action"=&gt; "index"
                  )
               );
         ?&gt;
      &lt;/li&gt;
      &lt;li&gt;
         &lt;?php echo $html-&gt;link(
                  "Things",
                  array(
                     "controller"=&gt; "things",
                     "action"=&gt; "index"
                  )
               );
         ?&gt;
      &lt;/li&gt;
   &lt;/ul&gt;
&lt;/div&gt;
</pre>
<p>&#8230;prościzna, prawda? Kwestię requestAction też już mamy z głowy. Jednak pojawił się problem &#8211; wnętrze zakładek pojawiło się w powtórzonym layoucie.<br />
Szybko naprawimy to w app_controller.php przy pomocy RequestHanlder:</p>
<pre name="code" class="php">
// /app/app_controller.php
var $components = array("RequestHandler");
function beforeFilter(){
    if($this->RequestHandler->isAjax()){
      $this->layout = "ajax";
    }
}
</pre>
<p>Wrócmy do kwestii stronicowania (i sortowania przy okazji). Chcemy, aby kolejne strony ładowały się w danej zakładce. Wykorzystajmy do tego potęgę jQuery.<br />
Dodajemy taki prosty skrypt </p>
<pre name="code" class="javascript">
// views/items/all.ctp
   $('#tabs a[href*=/sort:],#tabs a[href*=/page:]').live('click', function(){
       $('#tabs>div:visible').load($(this).attr('href'));
          return false;
   });
</pre>
<p>Jeśli interesuje Cię co się w tym fragmencie dzieje, zapraszam na <a href="/?p=591">do innego wpisu</a>. W dużym skrócie: łapiemy linki, które mają w adresie &#8220;sort:&#8221; i &#8220;page:&#8221; i zmuszamy je aby przeładowały zawartość zakładki, zamiast całej strony.</p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.grzegorzpawlik.com/2010/02/tutorial_dashboard_web_2-0_dla_leniwyc/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>CakePHP, pagination, jQuery i zakładki (tabs)</title>
		<link>http://blog.grzegorzpawlik.com/2010/01/cakephp-pagination-jquery-i-zakladki-tabs/</link>
		<comments>http://blog.grzegorzpawlik.com/2010/01/cakephp-pagination-jquery-i-zakladki-tabs/#comments</comments>
		<pubDate>Fri, 15 Jan 2010 15:31:48 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Inne]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[paginate]]></category>
		<category><![CDATA[paginator]]></category>

		<guid isPermaLink="false">http://blog.grzegorzpawlik.com/?p=591</guid>
		<description><![CDATA[Jakoś tak wyszło, że więcej bawię się ostatnio jQuery. Pojawił się kolejny problem: przerobić Pagination cake&#8217;a na taki, żeby działał po ajaxie w zakładkach jQuery (jquery.ui.tabs): Z pomocą przyszedł chankov.net z takim oto skryptem: $('a[href*=/sort:],a[href*=/page:]').livequery('click', function(){ $('#content').load($(this).attr('href')); return false; }); &#8230; <a href="http://blog.grzegorzpawlik.com/2010/01/cakephp-pagination-jquery-i-zakladki-tabs/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Jakoś tak wyszło, że więcej bawię się ostatnio jQuery. Pojawił się kolejny problem:<br />
przerobić Pagination cake&#8217;a na taki, żeby działał po ajaxie w zakładkach jQuery (jquery.ui.tabs):</p>
<p style="text-align: left;"><a href="http://blog.grzegorzpawlik.com/wp-content/uploads/2010/01/Cars_1263568001683.png" rel="lightbox[591]" title="Zakładki i pagination"><img class="aligncenter size-full wp-image-592" title="Zakładki i pagination" src="http://blog.grzegorzpawlik.com/wp-content/uploads/2010/01/Cars_1263568001683.png" alt="" width="650" height="137" /></a>Z pomocą przyszedł <a href="http://nik.chankov.net/2009/05/16/cakephp-ajaxed-pagination-and-sort/">chankov.net</a> z takim oto skryptem:</p>
<p style="text-align: left;">
<pre>
$('a[href*=/sort:],a[href*=/page:]').live<del datetime="2010-01-15T15:40:36+00:00">query</del>('click', function(){
    $('#content').load($(this).attr('href'));
    return false;
});
</pre>
</p>
<p>Niestety nie ma chyba kontroli nad tym jakie id jquery.ui nada div&#8217;om, które są zawartością dla danej zakładki. Jednak i na to jest sposób (dzięki pluginowi livequery), nalezy zamiast </p>
<pre>
$('#content').load($(this).attr('href'));
</pre>
<p>Użyć nieco bardziej skomplikowanego selektora. Zakładając, że #content to div przechowujący zakładki (wywołałeś jQuery(&#8220;#content&#8221;).tabs()), to nalezy zmienić powyższą linię na</p>
<pre>
jQuery('#contents>div:visible').load(jQuery(this).attr('href'));
</pre>
<p>Dzięki selektorowi &#8216;#contents>div:visible&#8217; znajdziesz w elemencie o id #contents pierwszego div&#8217;a (>div), który jest widzialny (:visible), a to właśnie jest element, którego zawartość należy uaktualnić nowymi danymi&#8230;</p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.grzegorzpawlik.com/2010/01/cakephp-pagination-jquery-i-zakladki-tabs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Jak wyczyścić cache dla zakładek (tabs) w jQuery?</title>
		<link>http://blog.grzegorzpawlik.com/2010/01/jak-wyczyscic-cache-dla-zakladek-tabs-w-jquery/</link>
		<comments>http://blog.grzegorzpawlik.com/2010/01/jak-wyczyscic-cache-dla-zakladek-tabs-w-jquery/#comments</comments>
		<pubDate>Thu, 14 Jan 2010 12:11:27 +0000</pubDate>
		<dc:creator>Greg</dc:creator>
				<category><![CDATA[Inne]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://blog.grzegorzpawlik.com/?p=588</guid>
		<description><![CDATA[Notka ku pamięci (żeby następnym razem nie szukać godzinę rozwiązania pt JQuery.tabs.disableCache). Jeśli używasz zakładek (jQuery.UI.tabs()) z włączonym keszowaniem (co jest dobrym pomysłem, ze względu na czas odpowiedzi) to możesz w końcu dojść do momentu, że należy wyczyścić cache dla &#8230; <a href="http://blog.grzegorzpawlik.com/2010/01/jak-wyczyscic-cache-dla-zakladek-tabs-w-jquery/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Notka ku pamięci (żeby następnym razem nie szukać godzinę rozwiązania pt JQuery.tabs.disableCache).</p>
<p>Jeśli używasz zakładek (jQuery.UI.tabs()) z włączonym keszowaniem (co jest dobrym pomysłem, ze względu na czas odpowiedzi) to możesz w końcu dojść do momentu, że należy wyczyścić cache dla konkretnej zakładki<br />
(dlatego, ze na przykład został wykonany ajaxowy submit formularza).</p>
<p>Nie znajdziesz niestety funkcji &#8220;clearCache&#8221;, którą ja bezskutecznie poszukiwałem (zakładałem, że najpierw muszę wyczyścić cache dla tej zakładki, a później obsłużyć załadowanie nowych elementów do zakładki). Okazuje się, że można to zrobić równocześnie za pomocą metody &#8220;load&#8221;:</p>
<p>jQuery(&#8220;#idKonteneraZakladek&#8221;).tabs(&#8220;load&#8221;, [id_zakłaki]); </p>
<p><a href="http://docs.jquery.com/UI/Tabs#method-load">Więcej szczegółów.</a></p>
<!-- PHP 5.x -->]]></content:encoded>
			<wfw:commentRss>http://blog.grzegorzpawlik.com/2010/01/jak-wyczyscic-cache-dla-zakladek-tabs-w-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

