<?php
$plugin['name'] = 'ful_ajax_gallery';
$plugin['author'] = 'Francesco Fullone';
$plugin['author_uri'] = 'http://www.fullo.net/blog/progetti/textpattern-plugins/';
$plugin['version'] = '0.7';
$plugin['description'] = 'this plugin helps to create a dynamic archive browsing using ajax';
$plugin['type'] = 0;

@include_once('zem_tpl.php');

if (0) {
?>
# --- BEGIN PLUGIN HELP ---

<h1>ful_ajax_gallery</h1>
<h3>Description</h3>
This plugin helps to create a dynamic archive browsing using ajax, it uses ajax to query the textpattern db and to retrieve post information such title, text and whatever.
The plugin is strongly ispired on the cbs_live_search but it doesn't use hardcoded query. So you can choose how to display your results simply creating a new layout form.

<h3>Release</h3>
v0.7

<h3>Download</h3>
<ul>
	<li><a href="http://www.fullo.net/progetti/textpattern/ful_ajax_gallery.phps">ful_ajax_gallery.phps</a> plugin template file not compiled</li>
	<li><a href="http://www.fullo.net/progetti/textpattern/ful_ajax_gallery.txt">ful_ajax_gallery.txt</a> compiled plugin</li>
</ul>

<h3>Demo</h3>
<a href="http://php.fullo.net/textpattern/">http://php.fullo.net/textpattern/</a> click on "next" to start the demo

<h3>Reference</h3>
<div>   
<ul>
	<li>add in the &lt;head&gt; section of the page template the<br/> 
	<code>&lt;txp:ful_ajax_gallery_js /&gt;</code> 
	it will add the necessaries javascript function to call ajax with prototype and scriptacoulus</li>
	<li>the <code>&lt;txp:ful_ajax_gallery /&gt;</code> tag is the main tag of the plugin. <br/> 
		This tag uses those attributes:
		<ul>
			<li>section: the section where to search data, note that is the same of custom_article</li>
			<li>category: the category where to search data, note that is the same of custom_article</li>
			<li>form: the form layout for the results</li>
			<li>limit: how many articles are retrieved, note that is the same of custom_article</li>
			<li>offset: the offset from which the data is retrieved, note that is the same of custom_article</li>
			<li>label: show the menubar label</li>
			<li>menu (true/false): show the menubar</li>
			<li>sortby (posted): how to sort the results, note that is the same of custom_article</li>
			<li>spinner (true/false): add the spinner div directly</li>
			<li>top (true/false): add the top div directly</li>
			<li>label_menu_next: the label for the 'next' link</li>
			<li>label_menu_prev: the label for the 'prev' link</li>
		</ul>
	</li>
	<li>
		if you want to add the menu bar in another position you can use the tag  <code>&lt;txp:ful_ajax_menu&gt;</code> 
		it uses a limited sets of the attributes of <code>&lt;txp:ful_ajax_gallery /&gt;</code>
		<ul>
			<li>section: the section where to search data, note that is the same of custom_article</li>
			<li>category: the category where to search data, note that is the same of custom_article</li>
			<li>form: the form layout for the results</li>
			<li>limit: how many articles are retrieved, note that is the same of custom_article</li>
			<li>offset: the offset from which the data is retrieved, note that is the same of custom_article</li>
			<li>label (next/prev): used to create the link to previous o next articles</li>
		</ul>
		and it need also a nested text as the label
	</li>
	<li>
		if you want to add the ajax container for the article in another position you have to set the attribute top=false for 
		<code>&lt;txp:ful_ajax_gallery /&gt;</code> and then you can use <code>&lt;txp:ful_ajax_top /&gt;</code>.
		This tag accept 2 attributes and can manage text.
		<ul>
			<li>tag (div): the type of tag for the ajax container</li>
			<li>class: the css class for the tag</li>
		<ul>
	</li>
	<li>
		as before if you want to add the ajax spinner in another position you have to set the attribute spinner=false for 
		<code>&lt;txp:ful_ajax_gallery /&gt;</code> and then you can use <code>&lt;txp:ful_ajax_spinner /&gt;</code>.
		This tag accept 2 attributes and can manage text.
		<ul>
			<li>tag (div): the type of tag for the ajax container</li>
			<li>class: the css class for the tag</li>
		<ul> 
	</li>	
	<li>
		you can configure the default value for all the plugin changing the <code>ful_ajax_config()</code> array. 
	</li>
</ul>
</div>

<h3>css style</h3>
<div>
	Every object created by the plugin has its own css ID:
	<ul>
		<li>menu and menu links: ajax-menu, ajax-menu-next, ajax-menu-prev</li>
		<li>title browsing (bottom interface): ful-ajax-bottom</li>
		<li>article content: ful-ajax-top</li>
		<li>spinner: ful-ajax-spinner</li>
	</ul>
</div>

<h3>usage example</h3>
<div>
	create a layout page, cloning the default template. Add then in the html head section the calling for the js libraries. 
	<em>note that I\'ve installed prototype and scriptaculous in the /js directory</em><br/>
	<blockquote><code>
		&lt;script type="text/javascript" src="&lt;txp:site_url/&gt;js/prototype.js" &gt;&lt;/script&gt;
		&lt;script type="text/javascript" src="&lt;txp:site_url/&gt;js/scriptaculous.js" &gt;&lt;/script&gt;
		&lt;txp:full_ajax_gallery_js /&gt;
	</code></blockquote>

	then in the body of the page I add the tag to create the ajax gallery
	<blockquote><code>	
		&lt;h1&gt; ajax article gallery &lt;/h1&gt;
		&lt;txp:ful_ajax_gallery limit="5" category="mycat" form="myform" /&gt;
	</code></blockquote>

	now an archive gallery for the category <em>mycat</em> is created by textpattern, and I have also a 5 title pagination. 
	The archive uses a generic article form <em>myform</em> 
	<blockquote><code>
			&lt;div class="articolo"&gt;
			&lt;txp:ful_ajax_show_link form="myTopForm"&gt;##&lt;txp:article_id /&gt;##&lt;txp:title /&gt;&lt;/txp:ful_ajax_show_link&gt;
			&lt;/div&gt;
	</code></blockquote>	    
	<strong>it is very important</strong> that the value inserted in the <em>ful_ajax_show_link</em> tag start with ##ID-OF-THE-POST## This is due a 
	textpattern limitation which cannot permit to use a txp:tag inside another txp:tag as attribute. After that pattern you can add anything.
	Here I use a article form called <em>myTopForm</em>.
	<blockquote><code>
		&lt;h2&gt;&lt;txp:permlink&gt;&lt;txp:title /&gt;&lt;/txp:permlink>&lt;/h2&gt;
		&lt;txp:body /&gt;
	</code></blockquote>

	if you want to add the spinner or the top container in another place you can change the page layout as follow:
	<blockquote><code>	
	
		&lt;txp:ful_ajax_spinner&gt;&lt;img src="path.to/spinner.img" alt="my ajax spinner" /&gt;&lt;/txp:ful_ajax_spinner&gt;
		
		&lt;txp:ful_ajax_menu label="prev" limit="5" category="mycat" form="myform" menu="false" /&gt;
		&lt;txp:ful_ajax_menu label="next" limit="5" category="mycat" form="myform" menu="false" /&gt;	
		
		// some html code here
	
		&lt;h1&gt; ajax article gallery &lt;/h1&gt;
		&lt;txp:ful_ajax_gallery limit="5" category="mycat" form="myform" spinner="false" top="false" menu="false"/&gt;
		
		// some html code here
		
		&lt;txp:ful_ajax_top class="myCSS" tag="p"&gt;SOME TEXT HERE&lt;/txp:ful_ajax_top&gt;
		
	</code></blockquote>
	note that is <strong>very important</strong> to add the same attributes to the ful_ajax_menu and ful_ajax_gallery tags.
</div>
	 	 
<p><strong>note:</strong> This plugin need the scriptacoulus and prototype js libraries loaded in the head of your site template</p>

# --- END PLUGIN HELP ---
<?php
}

# --- BEGIN PLUGIN CODE ---

register_callback('ful_ajax_next', 'textpattern');
register_callback('ful_ajax_show', 'textpattern');
register_callback('ful_ajax_next_menu', 'textpattern');

// this function is called from the ajax script , calling it from a txp tag isn't a good idea
function ful_ajax_show() {

	if((ps('ful_show')) == '')
		return;

	$id = (int)ps('id');
	$form = ps('form');

	header('Content-Type: application/x-javascript; charset=ISO-8859-1');

	global $prefs;

	$args = array (
				'id'=> $id,
				'form'=> $form
		);

	$o = array();
	$o[] = article_custom($args);

	exit(doWrap($o, $wraptag, $break));
}

// this function is called from the ajax script , calling it from a txp tag isn't a good idea
function ful_ajax_next() {

	if((ps('ful_next')) == '')
		return;

	$limit = (int)ps('limit');
	$original_offset = (int)ps('offset') - $limits ;
	$offset = (int)ps('offset') + $limits;
	$section = ps('section');
	$category = ps('category');
	$form = ps('form');
	$menu = ps('menu');
	$break= "";

	header('Content-Type: application/x-javascript; charset=ISO-8859-1');

	global $prefs;

	$args = array (
				'limit' => $limit,
				'form'=> $form,
				'offset'=> $offset,
				'sortby'=> 'posted',
				'section'=> $section,
				'category'=> $category,
				'menu' => $menu
			);

	$o = array();
	$o[] = article_custom($args);

	if ($menu == 'true')
	{
		$o[] = '<div id="ajax-menu">';

		if ($original_offset >= 0)
			$o[] = ful_ajax_menu(array_merge($args, array('label'=>'prev')),'prev');

		$o[] = ful_ajax_menu(array_merge($args, array('label'=>'next')),'next');

		$o[]= '</div>';
	}

	exit(doWrap($o, $wraptag, $break));
}

// this function is called from the ajax script , calling it from a txp tag isn't a good idea
function ful_ajax_next_menu() {

	if((ps('ful_next_menu')) == '')
		return;

	$limit = (int)ps('limit');
	$original_offset = (int)ps('offset') - $limits ;
	$offset = (int)ps('offset') + $limits;
	$section = ps('section');
	$category = ps('category');
	$form = ps('form');
	$menu = ps('menu');
	$break= "";

	header('Content-Type: application/x-javascript; charset=ISO-8859-1');

	global $prefs;

	$args = array (
				'limit' => $limit,
				'form'=> $form,
				'offset'=> $offset,
				'sortby'=> 'posted',
				'section'=> $section,
				'category'=> $category,
				'menu' => $menu
			);

	$o = array();

	if ($original_offset >= 0)
		$o[] = ful_ajax_menu(array_merge($args, array('label'=>'prev')),'prev');

	$o[] = ful_ajax_menu(array_merge($args, array('label'=>'next')),'next');


	exit(doWrap($o, $wraptag, $break));
}

// add the js function to call the ajax script, add this in the header of your template
function ful_ajax_gallery_js(){

	return '
	<script type="text/javascript">

	function ful_Next(limit,offset,section,category,form,menu)
	{
		var url = window.location.href;
		var params = "ful_next=true&limit="+limit+"&offset="+offset+"&section="+section+"&category="+category+"&form="+form+"&menu="+menu;
		var ajax = new Ajax.Updater(
			{success: "ful-ajax-bottom"},
			url,
			{
			asynchronous:true,
			evalScripts:true,
			method: "post",
			parameters: params,
			onFailure: reportError,
			onComplete:function(request) {new Effect.Highlight("ful-ajax-bottom"); Element.hide("ful-ajax-spinner"); if (menu == "false") ful_Next_Menu(limit,offset,section,category,form)},
			onLoading:function(request) {new Effect.Highlight("ful-ajax-spinner"); new Effect.Appear("ful-ajax-spinner"); }
			});
	}

	function ful_Next_Menu(limit,offset,section,category,form)
	{
		var url = window.location.href;
		var params = "ful_next_menu=true&limit="+limit+"&offset="+offset+"&section="+section+"&category="+category+"&form="+form+"&menu=false";
		var ajax = new Ajax.Updater(
			{success: "ajax-menu"},
			url,
			{
			asynchronous:true,
			evalScripts:true,
			method: "post",
			parameters: params,
			onFailure: reportError,
			onComplete:function(request) {new Effect.Highlight("ajax-menu"); }
			});
	}


	function ful_Show(id,form)
	{
		var url = window.location.href;
		var params = "ful_show=true&id="+id+"&form="+form;
		var ajax = new Ajax.Updater(
			{success: "ful-ajax-top"},
			url,
			{
			asynchronous:true,
			evalScripts:true,
			method: "post",
			parameters: params,
			onFailure: reportError,
			onComplete:function(request) {new Effect.Highlight("ful-ajax_top"); Element.hide("ful-ajax-spinner"); },
			onLoading:function(request) { new Effect.Appear("ful-ajax-spinner"); }
			});
	}


	function reportError(request)
	{
		$(ful-ajax-top).innerHTML = "Error "+request;
	}

	</script>
	';

}

//generate the next, prev menu link button
function ful_ajax_menu($atts) {

	extract(lAtts(ful_ajax_config(),$atts));

	if (!in_array(strtolower($label),array('next','prev'))) $label='next';
	if (strtolower($label) == 'next') $offset = $offset + $limit;
	if (strtolower($label) == 'prev') $offset = $offset - $limit;


	if ($offset < 0) return '';
	else return '
					<a href="#" rel="nofollow" id="ajax-menu-'.$label.'">'.${'label_menu_'.$label}.'</a>
					<script type="text/javascript">Event.observe($("ajax-menu-'.$label.'"),"click",function(){ful_Next(\''.$limit.'\',\''.$offset.'\',\''.$section.'\',\''.$category.'\',\''.$form.'\',\''.$menu.'\');}, false);</script>
				';
}

function ful_ajax_show_link($atts,$value){
	
	$string = parse($value);
	extract(lAtts(ful_ajax_config(),$atts));
	
	if ($id == '')
	{
		ereg('^##[0-9]+##',$string,$newid);
		$id = ereg_replace('##','',$newid[0]);
		$string = ereg_replace('^##[0-9]+##','',$string);
	}
	
	return  '
				<a href="#" rel="nofollow" id="ajax-post-'.$id.'">'.$string.'</a>
				<script type="text/javascript">Event.observe($("ajax-post-'.$id.'"),"click",function(){ful_Show(\''.$id.'\',\''.$form.'\');},false);</script>				
			';
	
}

// main function to show the divs for the ajax gallery
function ful_ajax_gallery($atts) {

	extract(lAtts(ful_ajax_config(),$atts));

        if ($category != '') $add_category = 'category='.$category;
        if ($section != '') $add_section = 'section ='.$section ;

	if ($spinner == 'true') $show_spinner = '<txp:ful_ajax_spinner>spinner</txp:ful_ajax_spinner>';
	else $show_spinner = '';

	if ($top == 'true') $show_top = '<div id="ful-ajax-top"></div>';
	else $show_top = '';

	if ($menu == 'true') $show_menu = '<div id="ajax-menu"><txp:ful_ajax_menu  limit="'.$limit.'" form="'.$form.'" '.$add_section.' '.$add_category.' offset="'.$offset.'" label="next">'.$label_menu_next.'</txp:ful_ajax_menu></div>';
	else $show_menu = '';

	return '
		'.$show_top.'

		'.$show_spinner.'

		<div id="ful-ajax-bottom">
			<txp:article_custom limit="'.$limit.'" form="'.$form.'" '.$add_section.'  '.$add_category.' offset="'.$offset.'" sortby="posted" />

			'.$show_menu.'

			</div>
		</div>';

}

// create the ajax top divs
function ful_ajax_top($atts,$value='') {
	extract(lAtts(array(
		'tag'   => 'div',
		'class'   => '',
	),$atts));

	return '<'.$tag.' id="ful-ajax-top" class="'.$class.'">'.parse($value).'</'.$tag.'>';
}

// create the ajax spinner
function ful_ajax_spinner($atts,$value='spinner') {
	extract(lAtts(array(
		'tag'   => 'div',
		'class'   => '',
	),$atts));

	return '<'.$tag.' id="ful-ajax-spinner" style="display:none" class="'.$class.'">'.parse($value).'</'.$tag.'>';
}

// write here your default config value
function ful_ajax_config()
{
	return array(
		'section'   => '',
		'category'=> 'archive',
		'form' => 'article',
		'limit' => '3',
		'offset'     => '0',
		'label' => 'next',
		'spinner' => 'true',
		'menu' => 'true',
		'sortby' => 'posted',
		'top' => 'true',
		'label_menu_next' => 'next &gt;',
		'label_menu_prev' => '&lt; prev',
		'class' => ''
	);
}



# --- END PLUGIN CODE ---

?>
