package Kwiki::LiveSearch;
use Kwiki::Plugin -Base;
use mixin 'Kwiki::Installer';
use Kwiki ':char_classes';
our $VERSION = '0.07';

const class_id => 'livesearch';
const class_title => 'LiveSearch';
const cgi_class => 'Kwiki::LiveSearch::CGI';
const result_template => 'livesearch_result.xml';
const css_file => 'livesearch.css';

sub register {
    my $registry = shift;
    $registry->add(action => 'livesearch');
    $registry->add(widget => 'livesearch_box', 
                   template => 'livesearch_box.html',
		   show_for => 'display',
                  );
}

sub livesearch {
    $self->template_process($self->result_template,
			    pages => $self->perform_livesearch);
}

sub perform_livesearch {
    my $livesearch = $self->cgi->s;
    $livesearch =~ s/[^$WORD\ \-\.\^\$\*\|\:]//g;
    [ 
        grep {
            $_->content =~ m{$livesearch}i and 
            $_->active
        } $self->pages->all 
    ]
}

package Kwiki::LiveSearch::CGI;
use Kwiki::CGI -base;

cgi 's';

package Kwiki::LiveSearch;

__DATA__

__template/tt2/livesearch_box.html__
<!-- BEGIN livesearch_box.html -->
<link rel="stylesheet" type="text/css" href="css/livesearch.css" />
<form onsubmit="return liveSearchSubmit()" style="margin: 0px;" name="searchform" method="get" action="[% script_name%]" enctype="application/x-www-form-urlencoded" >
<span>Live Search</span>
<input type="hidden" name="action" value="livesearch" />
<input name="s" id="livesearch" size="8" autocomplete="off" onkeypress="liveSearchStart();" type="text"/>
<div id="LSResult" style="display: none;"><div id="LSShadow"></div></div>
</form>
<script type="text/javascript" src="javascript/livesearch.js"></script>
<script type="text/javascript"> liveSearchInit() </script>
<!-- END livesearch_box.html -->
__template/tt2/livesearch_result.xml__
<?xml version='1.0' encoding='utf-8'  ?><div class='LSRes'>[% IF pages.0
 %][% FOR page = pages %]<div class="LSRow">[% page.kwiki_link %]</div>[% END %][%
 ELSE %]<div class="LSRow"><a>No Pages Found</a></div>[% END %]</div>
__css/livesearch.css__
  #livesearch {
  display: block;
  }
  
  #LSHighlight {
      background-color: lightgreen;
  }

  .LSRow a:hover {
	text-decoration: underline;
  }

  .LSRow {
    margin: 0px;
    line-height: 1.2em;
	padding-top: 0.2em;
	padding-bottom: 0.2em;
    text-indent: -1em; 
    padding-left: 1em; 
    line-height: 1.2em; 
    padding-right: 1em;
  }
 
  .LSRow:before {
    content: '>';
  }
  #LSResult {    
      position: absolute;
      background-color: #ccc; 
      min-width: 96px; 
      margin-left: 4px;
      margin-top: 4px;
  }
  
  #LSShadow {
      position: relative;
      bottom: 2px;
      right: 2px;
      background-color: #666; /*shadow color*/
      color: inherit;
  }
  
  .LSRes {
      position: relative;
      bottom: 2px;
	  right: 2px;
      background-color: white;
      border: black 1px dotted;
  }

__javascript/livesearch.js__
/*
// +----------------------------------------------------------------------+
// | Copyright (c) 2004 Bitflux GmbH                                      |
// +----------------------------------------------------------------------+
// | Licensed under the Apache License, Version 2.0 (the "License");      |
// | you may not use this file except in compliance with the License.     |
// | You may obtain a copy of the License at                              |
// | http://www.apache.org/licenses/LICENSE-2.0                           |
// | Unless required by applicable law or agreed to in writing, software  |
// | distributed under the License is distributed on an "AS IS" BASIS,    |
// | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or      |
// | implied. See the License for the specific language governing         |
// | permissions and limitations under the License.                       |
// +----------------------------------------------------------------------+
// | Author: Bitflux GmbH <devel@bitflux.ch>                              |
// +----------------------------------------------------------------------+

*/
var liveSearchReq = false;
var t = null;
var liveSearchLast = "";
var isIE = false;
// on !IE we only have to initialize it once
if (window.XMLHttpRequest) {
	liveSearchReq = new XMLHttpRequest();
}

function liveSearchInit() {
	
	if (navigator.userAgent.indexOf("Safari") > 0) {
		document.getElementById('livesearch').addEventListener("keydown",liveSearchKeyPress,false);
	} else if (navigator.product == "Gecko") {
		document.getElementById('livesearch').addEventListener("keypress",liveSearchKeyPress,false);
		
	} else {
		document.getElementById('livesearch').attachEvent('onkeydown',liveSearchKeyPress);
		isIE = true;
	}

}

function liveSearchKeyPress(event) {
	if (event.keyCode == 40 )
	//KEY DOWN
	{
		highlight = document.getElementById("LSHighlight");
		if (!highlight) {
			highlight = document.getElementById("LSResult").firstChild.firstChild.firstChild;
		} else {
			highlight.removeAttribute("id");
			highlight = highlight.nextSibling;
		}
		if (highlight) {
			highlight.setAttribute("id","LSHighlight");
		} 
		if (!isIE) { event.preventDefault(); }
	} 
	//KEY UP
	else if (event.keyCode == 38 ) {
		highlight = document.getElementById("LSHighlight");
		if (!highlight) {
			highlight = document.getElementById("LSResult").firstChild.firstChild.lastChild;
		} 
		else {
			highlight.removeAttribute("id");
			highlight = highlight.previousSibling;
		}
		if (highlight) {
				highlight.setAttribute("id","LSHighlight");
		}
		if (isGecko) 
		if (!isIE) { event.preventDefault(); }
	} 
	//ESC
	else if (event.keyCode == 27) {
		highlight = document.getElementById("LSHighlight");
		if (highlight) {
			highlight.removeAttribute("id");
		}
		document.getElementById("LSResult").style.display = "none";
	} 
}
function liveSearchStart() {
	if (t) {
		window.clearTimeout(t);
	}
	t = window.setTimeout("liveSearchDoSearch()",200);
}

function liveSearchDoSearch() {
	if (liveSearchLast != document.forms.searchform.s.value) {
	if (liveSearchReq && liveSearchReq.readyState < 4) {
		liveSearchReq.abort();
	}
	if ( document.forms.searchform.s.value == "") {
		document.getElementById("LSResult").style.display = "none";
		highlight = document.getElementById("LSHighlight");
		if (highlight) {
			highlight.removeAttribute("id");
		}
		return false;
	}
	if (window.XMLHttpRequest) {
	// branch for IE/Windows ActiveX version
	} else if (window.ActiveXObject) {
		liveSearchReq = new ActiveXObject("Microsoft.XMLHTTP");
	}
	liveSearchReq.onreadystatechange= liveSearchProcessReqChange;
	liveSearchReq.open("GET", "?action=livesearch&s=" + document.forms.searchform.s.value);
	liveSearchLast = document.forms.searchform.s.value;
	liveSearchReq.send(null);
	}
}

function liveSearchProcessReqChange() {
	
	if (liveSearchReq.readyState == 4) {
		var  res = document.getElementById("LSResult");
		res.style.display = "block";
		res.firstChild.innerHTML = liveSearchReq.responseText;
		 
	}
}

function liveSearchSubmit() {
	var highlight = document.getElementById("LSHighlight");
	if (highlight && highlight.firstChild) {
		window.location = highlight.firstChild.getAttribute("href");
		return false;
	} 
	else {
		return true;
	}
}
