123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852 |
- /*
- * OpenSearch ajax suggestion engine for MediaWiki
- *
- * uses core MediaWiki open search support to fetch suggestions
- * and show them below search boxes and other inputs
- *
- * by Robert Stojnic (April 2008)
- */
- // search_box_id -> Results object
- var os_map = {};
- // cached data, url -> json_text
- var os_cache = {};
- // global variables for suggest_keypress
- var os_cur_keypressed = 0;
- var os_last_keypress = 0;
- var os_keypressed_count = 0;
- // type: Timer
- var os_timer = null;
- // tie mousedown/up events
- var os_mouse_pressed = false;
- var os_mouse_num = -1;
- // if true, the last change was made by mouse (and not keyboard)
- var os_mouse_moved = false;
- // delay between keypress and suggestion (in ms)
- var os_search_timeout = 250;
- // these pairs of inputs/forms will be autoloaded at startup
- var os_autoload_inputs = new Array('searchInput', 'searchInput2', 'powerSearchText', 'searchText');
- var os_autoload_forms = new Array('searchform', 'searchform2', 'powersearch', 'search' );
- // if we stopped the service
- var os_is_stopped = false;
- // max lines to show in suggest table
- var os_max_lines_per_suggest = 7;
- // number of steps to animate expansion/contraction of container width
- var os_animation_steps = 6;
- // num of pixels of smallest step
- var os_animation_min_step = 2;
- // delay between steps (in ms)
- var os_animation_delay = 30;
- // max width of container in percent of normal size (1 == 100%)
- var os_container_max_width = 2;
- // currently active animation timer
- var os_animation_timer = null;
- /** Timeout timer class that will fetch the results */
- function os_Timer(id,r,query){
- this.id = id;
- this.r = r;
- this.query = query;
- }
- /** Timer user to animate expansion/contraction of container width */
- function os_AnimationTimer(r, target){
- this.r = r;
- var current = document.getElementById(r.container).offsetWidth;
- this.inc = Math.round((target-current) / os_animation_steps);
- if(this.inc < os_animation_min_step && this.inc >=0)
- this.inc = os_animation_min_step; // minimal animation step
- if(this.inc > -os_animation_min_step && this.inc <0)
- this.inc = -os_animation_min_step;
- this.target = target;
- }
- /** Property class for single search box */
- function os_Results(name, formname){
- this.searchform = formname; // id of the searchform
- this.searchbox = name; // id of the searchbox
- this.container = name+"Suggest"; // div that holds results
- this.resultTable = name+"Result"; // id base for the result table (+num = table row)
- this.resultText = name+"ResultText"; // id base for the spans within result tables (+num)
- this.toggle = name+"Toggle"; // div that has the toggle (enable/disable) link
- this.query = null; // last processed query
- this.results = null; // parsed titles
- this.resultCount = 0; // number of results
- this.original = null; // query that user entered
- this.selected = -1; // which result is selected
- this.containerCount = 0; // number of results visible in container
- this.containerRow = 0; // height of result field in the container
- this.containerTotal = 0; // total height of the container will all results
- this.visible = false; // if container is visible
- }
- /** Hide results div */
- function os_hideResults(r){
- var c = document.getElementById(r.container);
- if(c != null)
- c.style.visibility = "hidden";
- r.visible = false;
- r.selected = -1;
- }
- /** Show results div */
- function os_showResults(r){
- if(os_is_stopped)
- return;
- os_fitContainer(r);
- var c = document.getElementById(r.container);
- r.selected = -1;
- if(c != null){
- c.scrollTop = 0;
- c.style.visibility = "visible";
- r.visible = true;
- }
- }
- function os_operaWidthFix(x){
- // TODO: better css2 incompatibility detection here
- if(is_opera || is_khtml || navigator.userAgent.toLowerCase().indexOf('firefox/1')!=-1){
- return 30; // opera&konqueror & old firefox don't understand overflow-x, estimate scrollbar width
- }
- return 0;
- }
- function os_encodeQuery(value){
- if (encodeURIComponent) {
- return encodeURIComponent(value);
- }
- if(escape) {
- return escape(value);
- }
- return null;
- }
- function os_decodeValue(value){
- if (decodeURIComponent) {
- return decodeURIComponent(value);
- }
- if(unescape){
- return unescape(value);
- }
- return null;
- }
- /** Brower-dependent functions to find window inner size, and scroll status */
- function f_clientWidth() {
- return f_filterResults (
- window.innerWidth ? window.innerWidth : 0,
- document.documentElement ? document.documentElement.clientWidth : 0,
- document.body ? document.body.clientWidth : 0
- );
- }
- function f_clientHeight() {
- return f_filterResults (
- window.innerHeight ? window.innerHeight : 0,
- document.documentElement ? document.documentElement.clientHeight : 0,
- document.body ? document.body.clientHeight : 0
- );
- }
- function f_scrollLeft() {
- return f_filterResults (
- window.pageXOffset ? window.pageXOffset : 0,
- document.documentElement ? document.documentElement.scrollLeft : 0,
- document.body ? document.body.scrollLeft : 0
- );
- }
- function f_scrollTop() {
- return f_filterResults (
- window.pageYOffset ? window.pageYOffset : 0,
- document.documentElement ? document.documentElement.scrollTop : 0,
- document.body ? document.body.scrollTop : 0
- );
- }
- function f_filterResults(n_win, n_docel, n_body) {
- var n_result = n_win ? n_win : 0;
- if (n_docel && (!n_result || (n_result > n_docel)))
- n_result = n_docel;
- return n_body && (!n_result || (n_result > n_body)) ? n_body : n_result;
- }
- /** Get the height available for the results container */
- function os_availableHeight(r){
- var absTop = document.getElementById(r.container).style.top;
- var px = absTop.lastIndexOf("px");
- if(px > 0)
- absTop = absTop.substring(0,px);
- return f_clientHeight() - (absTop - f_scrollTop());
- }
- /** Get element absolute position {left,top} */
- function os_getElementPosition(elemID){
- var offsetTrail = document.getElementById(elemID);
- var offsetLeft = 0;
- var offsetTop = 0;
- while (offsetTrail){
- offsetLeft += offsetTrail.offsetLeft;
- offsetTop += offsetTrail.offsetTop;
- offsetTrail = offsetTrail.offsetParent;
- }
- if (navigator.userAgent.indexOf('Mac') != -1 && typeof document.body.leftMargin != 'undefined'){
- offsetLeft += document.body.leftMargin;
- offsetTop += document.body.topMargin;
- }
- return {left:offsetLeft,top:offsetTop};
- }
- /** Create the container div that will hold the suggested titles */
- function os_createContainer(r){
- var c = document.createElement("div");
- var s = document.getElementById(r.searchbox);
- var pos = os_getElementPosition(r.searchbox);
- var left = pos.left;
- var top = pos.top + s.offsetHeight;
- c.className = "os-suggest";
- c.setAttribute("id", r.container);
- document.body.appendChild(c);
- // dynamically generated style params
- // IE workaround, cannot explicitely set "style" attribute
- c = document.getElementById(r.container);
- c.style.top = top+"px";
- c.style.left = left+"px";
- c.style.width = s.offsetWidth+"px";
- // mouse event handlers
- c.onmouseover = function(event) { os_eventMouseover(r.searchbox, event); };
- c.onmousemove = function(event) { os_eventMousemove(r.searchbox, event); };
- c.onmousedown = function(event) { return os_eventMousedown(r.searchbox, event); };
- c.onmouseup = function(event) { os_eventMouseup(r.searchbox, event); };
- return c;
- }
- /** change container height to fit to screen */
- function os_fitContainer(r){
- var c = document.getElementById(r.container);
- var h = os_availableHeight(r) - 20;
- var inc = r.containerRow;
- h = parseInt(h/inc) * inc;
- if(h < (2 * inc) && r.resultCount > 1) // min: two results
- h = 2 * inc;
- if((h/inc) > os_max_lines_per_suggest )
- h = inc * os_max_lines_per_suggest;
- if(h < r.containerTotal){
- c.style.height = h +"px";
- r.containerCount = parseInt(Math.round(h/inc));
- } else{
- c.style.height = r.containerTotal+"px";
- r.containerCount = r.resultCount;
- }
- }
- /** If some entries are longer than the box, replace text with "..." */
- function os_trimResultText(r){
- // find max width, first see if we could expand the container to fit it
- var maxW = 0;
- for(var i=0;i<r.resultCount;i++){
- var e = document.getElementById(r.resultText+i);
- if(e.offsetWidth > maxW)
- maxW = e.offsetWidth;
- }
- var w = document.getElementById(r.container).offsetWidth;
- var fix = 0;
- if(r.containerCount < r.resultCount){
- fix = 20; // give 20px for scrollbar
- } else
- fix = os_operaWidthFix(w);
- if(fix < 4)
- fix = 4; // basic padding
- maxW += fix;
- // resize container to fit more data if permitted
- var normW = document.getElementById(r.searchbox).offsetWidth;
- var prop = maxW / normW;
- if(prop > os_container_max_width)
- prop = os_container_max_width;
- else if(prop < 1)
- prop = 1;
- var newW = Math.round( normW * prop );
- if( w != newW ){
- w = newW;
- if( os_animation_timer != null )
- clearInterval(os_animation_timer.id)
- os_animation_timer = new os_AnimationTimer(r,w);
- os_animation_timer.id = setInterval("os_animateChangeWidth()",os_animation_delay);
- w -= fix; // this much is reserved
- }
- // trim results
- if(w < 10)
- return;
- for(var i=0;i<r.resultCount;i++){
- var e = document.getElementById(r.resultText+i);
- var replace = 1;
- var lastW = e.offsetWidth+1;
- var iteration = 0;
- var changedText = false;
- while(e.offsetWidth > w && (e.offsetWidth < lastW || iteration<2)){
- changedText = true;
- lastW = e.offsetWidth;
- var l = e.innerHTML;
- e.innerHTML = l.substring(0,l.length-replace)+"...";
- iteration++;
- replace = 4; // how many chars to replace
- }
- if(changedText){
- // show hint for trimmed titles
- document.getElementById(r.resultTable+i).setAttribute("title",r.results[i]);
- }
- }
- }
- /** Invoked on timer to animate change in container width */
- function os_animateChangeWidth(){
- var r = os_animation_timer.r;
- var c = document.getElementById(r.container);
- var w = c.offsetWidth;
- var normW = document.getElementById(r.searchbox).offsetWidth;
- var normL = os_getElementPosition(r.searchbox).left;
- var inc = os_animation_timer.inc;
- var target = os_animation_timer.target;
- var nw = w + inc;
- if( (inc > 0 && nw >= target) || (inc <= 0 && nw <= target) ){
- // finished !
- c.style.width = target+"px";
- clearInterval(os_animation_timer.id)
- os_animation_timer = null;
- } else{
- // in-progress
- c.style.width = nw+"px";
- if(document.documentElement.dir == "rtl")
- c.style.left = (normL + normW + (target - nw) - os_animation_timer.target - 1)+"px";
- }
- }
- /** Handles data from XMLHttpRequest, and updates the suggest results */
- function os_updateResults(r, query, text, cacheKey){
- os_cache[cacheKey] = text;
- r.query = query;
- r.original = query;
- if(text == ""){
- r.results = null;
- r.resultCount = 0;
- os_hideResults(r);
- } else{
- try {
- var p = eval('('+text+')'); // simple json parse, could do a safer one
- if(p.length<2 || p[1].length == 0){
- r.results = null;
- r.resultCount = 0;
- os_hideResults(r);
- return;
- }
- var c = document.getElementById(r.container);
- if(c == null)
- c = os_createContainer(r);
- c.innerHTML = os_createResultTable(r,p[1]);
- // init container table sizes
- var t = document.getElementById(r.resultTable);
- r.containerTotal = t.offsetHeight;
- r.containerRow = t.offsetHeight / r.resultCount;
- os_fitContainer(r);
- os_trimResultText(r);
- os_showResults(r);
- } catch(e){
- // bad response from server or such
- os_hideResults(r);
- os_cache[cacheKey] = null;
- }
- }
- }
- /** Create the result table to be placed in the container div */
- function os_createResultTable(r, results){
- var c = document.getElementById(r.container);
- var width = c.offsetWidth - os_operaWidthFix(c.offsetWidth);
- var html = "<table class=\"os-suggest-results\" id=\""+r.resultTable+"\" style=\"width: "+width+"px;\">";
- r.results = new Array();
- r.resultCount = results.length;
- for(i=0;i<results.length;i++){
- var title = os_decodeValue(results[i]);
- r.results[i] = title;
- html += "<tr><td class=\"os-suggest-result\" id=\""+r.resultTable+i+"\"><span id=\""+r.resultText+i+"\">"+title+"</span></td></tr>";
- }
- html+="</table>"
- return html;
- }
- /** Fetch namespaces from checkboxes or hidden fields in the search form,
- if none defined use wgSearchNamespaces global */
- function os_getNamespaces(r){
- var namespaces = "";
- var elements = document.forms[r.searchform].elements;
- for(i=0; i < elements.length; i++){
- var name = elements[i].name;
- if(typeof name != 'undefined' && name.length > 2
- && name[0]=='n' && name[1]=='s'
- && ((elements[i].type=='checkbox' && elements[i].checked)
- || (elements[i].type=='hidden' && elements[i].value=="1")) ){
- if(namespaces!="")
- namespaces+="|";
- namespaces+=name.substring(2);
- }
- }
- if(namespaces == "")
- namespaces = wgSearchNamespaces.join("|");
- return namespaces;
- }
- /** Update results if user hasn't already typed something else */
- function os_updateIfRelevant(r, query, text, cacheKey){
- var t = document.getElementById(r.searchbox);
- if(t != null && t.value == query){ // check if response is still relevant
- os_updateResults(r, query, text, cacheKey);
- }
- r.query = query;
- }
- /** Fetch results after some timeout */
- function os_delayedFetch(){
- if(os_timer == null)
- return;
- var r = os_timer.r;
- var query = os_timer.query;
- os_timer = null;
- var path = wgMWSuggestTemplate.replace("{namespaces}",os_getNamespaces(r))
- .replace("{dbname}",wgDBname)
- .replace("{searchTerms}",os_encodeQuery(query));
- // try to get from cache, if not fetch using ajax
- var cached = os_cache[path];
- if(cached != null){
- os_updateIfRelevant(r, query, cached, path);
- } else{
- var xmlhttp = sajax_init_object();
- if(xmlhttp){
- try {
- xmlhttp.open("GET", path, true);
- xmlhttp.onreadystatechange=function(){
- if (xmlhttp.readyState==4 && typeof os_updateIfRelevant == 'function') {
- os_updateIfRelevant(r, query, xmlhttp.responseText, path);
- }
- };
- xmlhttp.send(null);
- } catch (e) {
- if (window.location.hostname == "localhost") {
- alert("Your browser blocks XMLHttpRequest to 'localhost', try using a real hostname for development/testing.");
- }
- throw e;
- }
- }
- }
- }
- /** Init timed update via os_delayedUpdate() */
- function os_fetchResults(r, query, timeout){
- if(query == ""){
- os_hideResults(r);
- return;
- } else if(query == r.query)
- return; // no change
- os_is_stopped = false; // make sure we're running
- /* var cacheKey = wgDBname+":"+query;
- var cached = os_cache[cacheKey];
- if(cached != null){
- os_updateResults(r,wgDBname,query,cached);
- return;
- } */
- // cancel any pending fetches
- if(os_timer != null && os_timer.id != null)
- clearTimeout(os_timer.id);
- // schedule delayed fetching of results
- if(timeout != 0){
- os_timer = new os_Timer(setTimeout("os_delayedFetch()",timeout),r,query);
- } else{
- os_timer = new os_Timer(null,r,query);
- os_delayedFetch(); // do it now!
- }
- }
- /** Change the highlighted row (i.e. suggestion), from position cur to next */
- function os_changeHighlight(r, cur, next, updateSearchBox){
- if (next >= r.resultCount)
- next = r.resultCount-1;
- if (next < -1)
- next = -1;
- r.selected = next;
- if (cur == next)
- return; // nothing to do.
- if(cur >= 0){
- var curRow = document.getElementById(r.resultTable + cur);
- if(curRow != null)
- curRow.className = "os-suggest-result";
- }
- var newText;
- if(next >= 0){
- var nextRow = document.getElementById(r.resultTable + next);
- if(nextRow != null)
- nextRow.className = os_HighlightClass();
- newText = r.results[next];
- } else
- newText = r.original;
- // adjust the scrollbar if any
- if(r.containerCount < r.resultCount){
- var c = document.getElementById(r.container);
- var vStart = c.scrollTop / r.containerRow;
- var vEnd = vStart + r.containerCount;
- if(next < vStart)
- c.scrollTop = next * r.containerRow;
- else if(next >= vEnd)
- c.scrollTop = (next - r.containerCount + 1) * r.containerRow;
- }
- // update the contents of the search box
- if(updateSearchBox){
- os_updateSearchQuery(r,newText);
- }
- }
- function os_HighlightClass() {
- var match = navigator.userAgent.match(/AppleWebKit\/(\d+)/);
- if (match) {
- var webKitVersion = parseInt(match[1]);
- if (webKitVersion < 523) {
- // CSS system highlight colors broken on old Safari
- // https://bugs.webkit.org/show_bug.cgi?id=6129
- // Safari 3.0.4, 3.1 known ok
- return "os-suggest-result-hl-webkit";
- }
- }
- return "os-suggest-result-hl";
- }
- function os_updateSearchQuery(r,newText){
- document.getElementById(r.searchbox).value = newText;
- r.query = newText;
- }
- /** Find event target */
- function os_getTarget(e){
- if (!e) e = window.event;
- if (e.target) return e.target;
- else if (e.srcElement) return e.srcElement;
- else return null;
- }
- /********************
- * Keyboard events
- ********************/
- /** Event handler that will fetch results on keyup */
- function os_eventKeyup(e){
- var targ = os_getTarget(e);
- var r = os_map[targ.id];
- if(r == null)
- return; // not our event
- // some browsers won't generate keypressed for arrow keys, catch it
- if(os_keypressed_count == 0){
- os_processKey(r,os_cur_keypressed,targ);
- }
- var query = targ.value;
- os_fetchResults(r,query,os_search_timeout);
- }
- /** catch arrows up/down and escape to hide the suggestions */
- function os_processKey(r,keypressed,targ){
- if (keypressed == 40){ // Arrow Down
- if (r.visible) {
- os_changeHighlight(r, r.selected, r.selected+1, true);
- } else if(os_timer == null){
- // user wants to get suggestions now
- r.query = "";
- os_fetchResults(r,targ.value,0);
- }
- } else if (keypressed == 38){ // Arrow Up
- if (r.visible){
- os_changeHighlight(r, r.selected, r.selected-1, true);
- }
- } else if(keypressed == 27){ // Escape
- document.getElementById(r.searchbox).value = r.original;
- r.query = r.original;
- os_hideResults(r);
- } else if(r.query != document.getElementById(r.searchbox).value){
- // os_hideResults(r); // don't show old suggestions
- }
- }
- /** When keys is held down use a timer to output regular events */
- function os_eventKeypress(e){
- var targ = os_getTarget(e);
- var r = os_map[targ.id];
- if(r == null)
- return; // not our event
- var keypressed = os_cur_keypressed;
- if(keypressed == 38 || keypressed == 40){
- var d = new Date()
- var now = d.getTime();
- if(now - os_last_keypress < 120){
- os_last_keypress = now;
- return;
- }
- }
- os_keypressed_count++;
- os_processKey(r,keypressed,targ);
- }
- /** Catch the key code (Firefox bug) */
- function os_eventKeydown(e){
- if (!e) e = window.event;
- var targ = os_getTarget(e);
- var r = os_map[targ.id];
- if(r == null)
- return; // not our event
- os_mouse_moved = false;
- os_cur_keypressed = (e.keyCode == undefined) ? e.which : e.keyCode;
- os_last_keypress = 0;
- os_keypressed_count = 0;
- }
- /** Event: loss of focus of input box */
- function os_eventBlur(e){
- var targ = os_getTarget(e);
- var r = os_map[targ.id];
- if(r == null)
- return; // not our event
- if(!os_mouse_pressed)
- os_hideResults(r);
- }
- /** Event: focus (catch only when stopped) */
- function os_eventFocus(e){
- // nothing happens here?
- }
- /********************
- * Mouse events
- ********************/
- /** Mouse over the container */
- function os_eventMouseover(srcId, e){
- var targ = os_getTarget(e);
- var r = os_map[srcId];
- if(r == null || !os_mouse_moved)
- return; // not our event
- var num = os_getNumberSuffix(targ.id);
- if(num >= 0)
- os_changeHighlight(r,r.selected,num,false);
- }
- /* Get row where the event occured (from its id) */
- function os_getNumberSuffix(id){
- var num = id.substring(id.length-2);
- if( ! (num.charAt(0) >= '0' && num.charAt(0) <= '9') )
- num = num.substring(1);
- if(os_isNumber(num))
- return parseInt(num);
- else
- return -1;
- }
- /** Save mouse move as last action */
- function os_eventMousemove(srcId, e){
- os_mouse_moved = true;
- }
- /** Mouse button held down, register possible click */
- function os_eventMousedown(srcId, e){
- var targ = os_getTarget(e);
- var r = os_map[srcId];
- if(r == null)
- return; // not our event
- var num = os_getNumberSuffix(targ.id);
- os_mouse_pressed = true;
- if(num >= 0){
- os_mouse_num = num;
- // os_updateSearchQuery(r,r.results[num]);
- }
- // keep the focus on the search field
- document.getElementById(r.searchbox).focus();
- return false; // prevents selection
- }
- /** Mouse button released, check for click on some row */
- function os_eventMouseup(srcId, e){
- var targ = os_getTarget(e);
- var r = os_map[srcId];
- if(r == null)
- return; // not our event
- var num = os_getNumberSuffix(targ.id);
- if(num >= 0 && os_mouse_num == num){
- os_updateSearchQuery(r,r.results[num]);
- os_hideResults(r);
- document.getElementById(r.searchform).submit();
- }
- os_mouse_pressed = false;
- // keep the focus on the search field
- document.getElementById(r.searchbox).focus();
- }
- /** Check if x is a valid integer */
- function os_isNumber(x){
- if(x == "" || isNaN(x))
- return false;
- for(var i=0;i<x.length;i++){
- var c = x.charAt(i);
- if( ! (c >= '0' && c <= '9') )
- return false;
- }
- return true;
- }
- /** When the form is submitted hide everything, cancel updates... */
- function os_eventOnsubmit(e){
- var targ = os_getTarget(e);
- os_is_stopped = true;
- // kill timed requests
- if(os_timer != null && os_timer.id != null){
- clearTimeout(os_timer.id);
- os_timer = null;
- }
- // Hide all suggestions
- for(i=0;i<os_autoload_inputs.length;i++){
- var r = os_map[os_autoload_inputs[i]];
- if(r != null){
- var b = document.getElementById(r.searchform);
- if(b != null && b == targ){
- // set query value so the handler won't try to fetch additional results
- r.query = document.getElementById(r.searchbox).value;
- }
- os_hideResults(r);
- }
- }
- return true;
- }
- function os_hookEvent(element, hookName, hookFunct) {
- if (element.addEventListener) {
- element.addEventListener(hookName, hookFunct, false);
- } else if (window.attachEvent) {
- element.attachEvent("on" + hookName, hookFunct);
- }
- }
- /** Init Result objects and event handlers */
- function os_initHandlers(name, formname, element){
- var r = new os_Results(name, formname);
- // event handler
- os_hookEvent(element, "keyup", function(event) { os_eventKeyup(event); });
- os_hookEvent(element, "keydown", function(event) { os_eventKeydown(event); });
- os_hookEvent(element, "keypress", function(event) { os_eventKeypress(event); });
- os_hookEvent(element, "blur", function(event) { os_eventBlur(event); });
- os_hookEvent(element, "focus", function(event) { os_eventFocus(event); });
- element.setAttribute("autocomplete","off");
- // stopping handler
- os_hookEvent(document.getElementById(formname), "submit", function(event){ return os_eventOnsubmit(event); });
- os_map[name] = r;
- // toggle link
- if(document.getElementById(r.toggle) == null){
- // TODO: disable this while we figure out a way for this to work in all browsers
- /* if(name=='searchInput'){
- // special case: place above the main search box
- var t = os_createToggle(r,"os-suggest-toggle");
- var searchBody = document.getElementById('searchBody');
- var first = searchBody.parentNode.firstChild.nextSibling.appendChild(t);
- } else{
- // default: place below search box to the right
- var t = os_createToggle(r,"os-suggest-toggle-def");
- var top = element.offsetTop + element.offsetHeight;
- var left = element.offsetLeft + element.offsetWidth;
- t.style.position = "absolute";
- t.style.top = top + "px";
- t.style.left = left + "px";
- element.parentNode.appendChild(t);
- // only now width gets calculated, shift right
- left -= t.offsetWidth;
- t.style.left = left + "px";
- t.style.visibility = "visible";
- } */
- }
- }
- /** Return the span element that contains the toggle link */
- function os_createToggle(r,className){
- var t = document.createElement("span");
- t.className = className;
- t.setAttribute("id", r.toggle);
- var link = document.createElement("a");
- link.setAttribute("href","javascript:void(0);");
- link.onclick = function(){ os_toggle(r.searchbox,r.searchform) };
- var msg = document.createTextNode(wgMWSuggestMessages[0]);
- link.appendChild(msg);
- t.appendChild(link);
- return t;
- }
- /** Call when user clicks on some of the toggle links */
- function os_toggle(inputId,formName){
- r = os_map[inputId];
- var msg = '';
- if(r == null){
- os_enableSuggestionsOn(inputId,formName);
- r = os_map[inputId];
- msg = wgMWSuggestMessages[0];
- } else{
- os_disableSuggestionsOn(inputId,formName);
- msg = wgMWSuggestMessages[1];
- }
- // change message
- var link = document.getElementById(r.toggle).firstChild;
- link.replaceChild(document.createTextNode(msg),link.firstChild);
- }
- /** Call this to enable suggestions on input (id=inputId), on a form (name=formName) */
- function os_enableSuggestionsOn(inputId, formName){
- os_initHandlers( inputId, formName, document.getElementById(inputId) );
- }
- /** Call this to disable suggestios on input box (id=inputId) */
- function os_disableSuggestionsOn(inputId){
- r = os_map[inputId];
- if(r != null){
- // cancel/hide results
- os_timer = null;
- os_hideResults(r);
- // turn autocomplete on !
- document.getElementById(inputId).setAttribute("autocomplete","on");
- // remove descriptor
- os_map[inputId] = null;
- }
- }
- /** Initialization, call upon page onload */
- function os_MWSuggestInit() {
- for(i=0;i<os_autoload_inputs.length;i++){
- var id = os_autoload_inputs[i];
- var form = os_autoload_forms[i];
- element = document.getElementById( id );
- if(element != null)
- os_initHandlers(id,form,element);
- }
- }
- hookEvent("load", os_MWSuggestInit);
|