summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ajax.php47
-rw-r--r--inc/search.php32
-rw-r--r--inc/template.php20
-rw-r--r--tpl/default/design.css11
-rw-r--r--tw-sack.js91
5 files changed, 200 insertions, 1 deletions
diff --git a/ajax.php b/ajax.php
new file mode 100644
index 000000000..7af88d835
--- /dev/null
+++ b/ajax.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * DokuWiki AJAX call handler
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+
+if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__)).'/');
+require_once(DOKU_INC.'inc/init.php');
+require_once(DOKU_INC.'inc/common.php');
+require_once(DOKU_INC.'inc/pageutils.php');
+require_once(DOKU_INC.'lang/en/lang.php');
+require_once(DOKU_INC.'lang/'.$conf['lang'].'/lang.php');
+require_once(DOKU_INC.'inc/auth.php');
+
+
+//call the requested function
+$call = 'ajax_'.$_REQUEST['call'];
+if(function_exists($call)){
+ $call();
+}else{
+ print "The called function does not exist!";
+}
+
+/**
+ * Searches for matching pagenames
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function ajax_qsearch(){
+ global $conf;
+
+ $query = cleanID($_REQUEST['q']);
+ if(empty($query)) return;
+
+ $nsdir = str_replace(':','/',getNS($query));
+ require_once(DOKU_INC.'inc/search.php');
+ require_once(DOKU_INC.'inc/html.php');
+
+ $data = array();
+ search($data,$conf['datadir'],'search_qsearch',array(query => $query),$nsdir);
+
+ print html_buildlist($data,'qsearch','html_list_index');
+}
+
+?>
diff --git a/inc/search.php b/inc/search.php
index 0b2e26c67..b368f6756 100644
--- a/inc/search.php
+++ b/inc/search.php
@@ -71,6 +71,38 @@ function search(&$data,$base,$func,$opts,$dir='',$lvl=1){
*/
/**
+ * Searches for pages beginning with the given query
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function search_qsearch(&$data,$base,$file,$type,$lvl,$opts){
+ $item = array();
+
+ if($type == 'd'){
+ return false; //no handling yet
+ }
+
+ //get id
+ $id = pathID($file);
+
+ //check if it matches the query
+ if(!preg_match('/^'.preg_quote($opts['query'],'/').'/u',$id)){
+ return false;
+ }
+
+ //check ACL
+ if(auth_quickaclcheck($id) < AUTH_READ){
+ return false;
+ }
+
+ $data[]=array( 'id' => $id,
+ 'type' => $type,
+ 'level' => 1,
+ 'open' => true);
+ return true;
+}
+
+/**
* Build the browsable index of pages
*
* $opts['ns'] is the current namespace
diff --git a/inc/template.php b/inc/template.php
index 4c782ace9..0720a12f6 100644
--- a/inc/template.php
+++ b/inc/template.php
@@ -332,9 +332,27 @@ function tpl_actionlink($type,$pre='',$suf=''){
function tpl_searchform(){
global $lang;
print '<form action="'.wl().'" accept-charset="utf-8" class="search" onsubmit="return svchk()">';
+
+//FIXME this should be moved somewhere else
+?>
+<script type="text/javascript" src="<?=DOKU_BASE?>tw-sack.js"></script>
+<script type="text/javascript">
+ ajax = new sack('<?=DOKU_BASE?>ajax.php');
+ ajax.AjaxFailedAlert = '';
+
+ function ajax_qsearch(value){
+ ajax.element = 'ajax_qsearch';
+ ajax.encodeURIString = false;
+ var call = 'call=qsearch&q=';
+ call += encodeURI(value);
+ ajax.runAJAX(call);
+ }
+</script>
+<?php
print '<input type="hidden" name="do" value="search" />';
- print '<input type="text" accesskey="f" name="id" class="edit" />';
+ print '<input type="text" accesskey="f" name="id" class="edit" onkeyup="ajax_qsearch(this.value)" />';
print '<input type="submit" value="'.$lang['btn_search'].'" class="button" />';
+ print '<div id="ajax_qsearch" class="ajax_qsearch"></div>';
print '</form>';
}
diff --git a/tpl/default/design.css b/tpl/default/design.css
index 685b7eeb4..73914d3f9 100644
--- a/tpl/default/design.css
+++ b/tpl/default/design.css
@@ -591,3 +591,14 @@ div.acladmin table{
margin-left: 10%;
width: 80%;
}
+
+/* ---------- AJAX quicksearch ----------- */
+
+div.ajax_qsearch {
+ position:absolute;
+ text-align:left;
+ width: 200px;
+ background-color: #ff9;
+ opacity: 0.9;
+ -moz-border-radius: 15px;
+}
diff --git a/tw-sack.js b/tw-sack.js
new file mode 100644
index 000000000..42e9322ed
--- /dev/null
+++ b/tw-sack.js
@@ -0,0 +1,91 @@
+// ====== Simple Ajax Code Kit =======
+// code by Gregory Wild-Smith (c)2005
+// http://twilightuniverse.com
+// If you use this code please keep this credit intact.
+// A link or email would be nice, but is not required.
+// v1.01
+
+function sack(file){
+ this.AjaxFailedAlert = "Your browser doesn't support the extended functionality of this website, and therefore you have have an experience that differs from the intended one.\n";
+ this.requestFile = file;
+ this.method = "POST";
+ this.URLString = "";
+ this.encodeURIString = true;
+ this.execute = false;
+
+ this.onLoading = function() { };
+ this.onLoaded = function() { };
+ this.onInteractive = function() { };
+ this.onCompletion = function() { };
+
+ this.createAJAX = function() {
+ try {
+ this.xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
+ } catch (e) {
+ try {
+ this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
+ } catch (oc) {
+ this.xmlhttp = null;
+ }
+ }
+ if(!this.xmlhttp && typeof XMLHttpRequest != "undefined")
+ this.xmlhttp = new XMLHttpRequest();
+ if (!this.xmlhttp){
+ // no XMLHttpRequest support, so no AJAX.
+ this.failed = true;
+ }
+ };
+
+ this.encodeURLString = function(string){
+ varArray = string.split('&');
+ for (i = 0; i < varArray.length; i++){
+ urlVars = varArray[i].split('=');
+ if (urlVars[0].indexOf('amp;') != -1){
+ urlVars[0] = urlVars[0].substring(4);
+ }
+ urlVars[0] = encodeURIComponent(urlVars[0]);
+ urlVars[1] = encodeURIComponent(urlVars[1]);
+ varArray[i] = urlVars.join("=");
+ }
+ return varArray.join('&');
+ }
+
+ this.runResponse = function(){
+ eval(this.response);
+ }
+
+ this.runAJAX = function(urlstring){
+ if (urlstring){ this.URLString = urlstring; }
+ if (this.element) { this.elementObj = document.getElementById(this.element); }
+ if (this.xmlhttp) {
+ var self = this; // wierd fix for odd behavior where "this" wouldn't work in the readystate function.
+ this.xmlhttp.open(this.method, this.requestFile ,true);
+ if (this.method == "POST") { this.xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') }
+ if (this.encodeURIString){ this.URLString = this.encodeURLString(this.URLString); }
+ this.xmlhttp.send(this.URLString);
+ this.xmlhttp.onreadystatechange = function() {
+ switch (self.xmlhttp.readyState){
+ case 1: // Loading.
+ self.onLoading();
+ break;
+ case 2: // Loaded.
+ self.onLoaded();
+ break;
+ case 3: // Interactive - is called every 4096 bytes.. pretty much just tells you it's downloading data.
+ self.onInteractive();
+ break;
+ case 4: // Completed.
+ self.response = self.xmlhttp.responseText
+ self.onCompletion();
+ if(self.execute){ self.runResponse(); }
+ if (self.elementObj) {
+ self.elementObj.innerHTML = self.response;
+ }
+ break;
+ }
+ };
+ }
+ };
+this.createAJAX();
+if(this.failed && this.AjaxFailedAlert){ alert(this.AjaxFailedAlert); }
+}