1/** 2 * The Link Wizard 3 * 4 * @author Andreas Gohr <gohr@cosmocode.de> 5 */ 6linkwiz = { 7 wiz: null, 8 entry: null, 9 result: null, 10 timer: null, 11 sack: null, 12 textArea: null, 13 selected: -1, 14 15 /** 16 * Initialize the linkwizard by creating the needed HTML 17 * and attaching the eventhandlers 18 */ 19 init: function(textArea){ 20 // prepare AJAX object 21 linkwiz.sack = new sack(DOKU_BASE + 'lib/exe/ajax.php'); 22 linkwiz.sack.AjaxFailedAlert = ''; 23 linkwiz.sack.encodeURIString = false; 24 25 // create HTML Structure 26 linkwiz.wiz = document.createElement('div'); 27 linkwiz.wiz.id = 'link__wiz'; 28 linkwiz.wiz.className = 'picker'; 29 linkwiz.wiz.style.top = (findPosY(textArea)+20)+'px'; 30 linkwiz.wiz.style.left = (findPosX(textArea)+80)+'px'; 31 linkwiz.wiz.style.display = 'none'; 32 33 linkwiz.wiz.innerHTML = 34 '<div id="link__wiz_header">'+ 35 '<img src="'+DOKU_BASE+'lib/images/close.png" width="16" height="16" align="right" alt="" id="link__wiz_close" />'+ 36 'Link Wizard</div>'+ 37 '<div>Link: <input type="text" class="edit" id="link__wiz_entry" autocomplete="off" /></div>'+ 38 '<div id="link__wiz_result"></div>'; 39 textArea.form.parentNode.appendChild(linkwiz.wiz); 40 linkwiz.textArea = textArea; 41 linkwiz.result = $('link__wiz_result'); 42 linkwiz.entry = $('link__wiz_entry'); 43 44 // attach event handlers 45 var obj; 46 obj = $('link__wiz_close'); 47 obj.onclick = linkwiz.hide; 48 49 linkwiz.sack.elementObj = linkwiz.result; 50 addEvent(linkwiz.entry,'keyup',linkwiz.onEntry); 51 addEvent(linkwiz.result,'click',linkwiz.onResultClick); 52 drag.attach(linkwiz.wiz,$('link__wiz_header')); 53 }, 54 55 /** 56 * handle all keyup events in the entry field 57 */ 58 onEntry: function(e){ 59 if(e.keyCode == 37 || e.keyCode == 39){ //left/right 60 return true; //ignore 61 } 62 if(e.keyCode == 38){ //Up 63 linkwiz.select(linkwiz.selected -1); 64 e.preventDefault(); 65 e.stopPropagation(); 66 return false; 67 } 68 if(e.keyCode == 40){ //Down 69 linkwiz.select(linkwiz.selected +1); 70 e.preventDefault(); 71 e.stopPropagation(); 72 return false; 73 } 74 if(e.keyCode == 13){ //Enter 75 if(linkwiz.selected > -1){ 76 var obj = linkwiz.getResult(linkwiz.selected); 77 if(obj){ 78 var a = obj.getElementsByTagName('A')[0]; 79 linkwiz.resultClick(a); 80 } 81 }else if(linkwiz.entry.value){ 82 linkwiz.insertLink(linkwiz.entry.value); 83 } 84 85 e.preventDefault(); 86 e.stopPropagation(); 87 return false; 88 } 89 linkwiz.autocomplete(); 90 }, 91 92 /** 93 * Get one of the result by index 94 * 95 * @param int result div to return 96 * @returns DOMObject or null 97 */ 98 getResult: function(num){ 99 var obj; 100 var childs = linkwiz.result.getElementsByTagName('DIV'); 101 obj = childs[num]; 102 if(obj){ 103 return obj; 104 }else{ 105 return null; 106 } 107 }, 108 109 /** 110 * Select the given result 111 */ 112 select: function(num){ 113 if(num < 0){ 114 linkwiz.deselect(); 115 return; 116 } 117 118 var obj = linkwiz.getResult(num); 119 if(obj){ 120 linkwiz.deselect(); 121 obj.className += ' selected'; 122 linkwiz.selected = num; 123 } 124 }, 125 126 /** 127 * deselect a result if any is selected 128 */ 129 deselect: function(){ 130 if(linkwiz.selected > -1){ 131 var obj = linkwiz.getResult(linkwiz.selected); 132 if(obj){ 133 obj.className = obj.className.replace(/ ?selected/,''); 134 } 135 } 136 linkwiz.selected = -1; 137 }, 138 139 /** 140 * Handle clicks in the result set an dispatch them to 141 * resultClick() 142 */ 143 onResultClick: function(e){ 144 if(e.target.tagName != 'A') return; 145 e.stopPropagation(); 146 e.preventDefault(); 147 linkwiz.resultClick(e.target); 148 return false; 149 }, 150 151 /** 152 * Handles the "click" on a given result anchor 153 */ 154 resultClick: function(a){ 155 var id = a.title; 156 if(id == '' || id.substr(id.length-1) == ':'){ 157 linkwiz.entry.value = id; 158 linkwiz.autocomplete_exec(); 159 }else{ 160 linkwiz.entry.value = id; 161 if(a.nextSibling && a.nextSibling.tagName == 'SPAN'){ 162 linkwiz.insertLink(a.nextSibling.innerHTML); 163 }else{ 164 linkwiz.insertLink(''); 165 } 166 } 167 }, 168 169 /** 170 * Insert the id currently in the entry box to the textarea, 171 * replacing the current selection or at the curso postion. 172 * When no selection is available the given title will be used 173 * as link title instead 174 */ 175 insertLink: function(title){ 176 if(!linkwiz.entry.value) return; 177 var sel = getSelection(linkwiz.textArea); 178 var stxt = sel.getText(); 179 if(!stxt) stxt=title; 180 181 var link = '[['+linkwiz.entry.value; 182 if(stxt) link += '|'+stxt; 183 link += ']]'; 184 185 var so = linkwiz.entry.value.length+3; 186 var eo = 2; 187 188 pasteText(sel,link,{startofs: so, endofs: eo}); 189 linkwiz.hide(); 190 }, 191 192 /** 193 * Start the page/namespace lookup timer 194 * 195 * Calls autocomplete_exec when the timer runs out 196 */ 197 autocomplete: function(){ 198 if(linkwiz.timer !== null){ 199 window.clearTimeout(linkwiz.timer); 200 linkwiz.timer = null; 201 } 202 203 linkwiz.timer = window.setTimeout(linkwiz.autocomplete_exec,350); 204 }, 205 206 /** 207 * Executes the AJAX call for the page/namespace lookup 208 */ 209 autocomplete_exec: function(){ 210 linkwiz.deselect(); 211 linkwiz.result.innerHTML = '<img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="" width="16" height="16" />'; 212 linkwiz.sack.runAJAX('call=linkwiz&q='+encodeURI(linkwiz.entry.value)); 213 }, 214 215 /** 216 * Clears the result area 217 */ 218 clear: function(){ 219 linkwiz.result.innerHTML = 'Search for a matching page name above, or browse through the pages on the right'; 220 linkwiz.entry.value = ''; 221 }, 222 223 /** 224 * Show the linkwizard 225 */ 226 show: function(){ 227 linkwiz.wiz.style['display'] = ''; 228 linkwiz.entry.focus(); 229 linkwiz.autocomplete(); 230 }, 231 232 /** 233 * Hide the link wizard 234 */ 235 hide: function(){ 236 linkwiz.wiz.style['display'] = 'none'; 237 }, 238 239 /** 240 * Toggle the link wizard 241 */ 242 toggle: function(){ 243 if(linkwiz.wiz.style['display'] == 'none'){ 244 linkwiz.show(); 245 }else{ 246 linkwiz.hide(); 247 } 248 }, 249}; 250 251