summaryrefslogtreecommitdiff
path: root/lib/scripts/linkwiz.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/scripts/linkwiz.js')
-rw-r--r--lib/scripts/linkwiz.js292
1 files changed, 153 insertions, 139 deletions
diff --git a/lib/scripts/linkwiz.js b/lib/scripts/linkwiz.js
index fec43ad5e..cc4c19e0d 100644
--- a/lib/scripts/linkwiz.js
+++ b/lib/scripts/linkwiz.js
@@ -2,57 +2,60 @@
* The Link Wizard
*
* @author Andreas Gohr <gohr@cosmocode.de>
+ * @author Pierre Spring <pierre.spring@caillou.ch>
*/
-var linkwiz = {
- wiz: null,
- entry: null,
+var dw_linkwiz = {
+ $wiz: null,
+ $entry: null,
result: null,
- timer: null,
- sack: null,
+ timer: null,
textArea: null,
- selected: -1,
+ selected: null,
selection: null,
/**
- * Initialize the linkwizard by creating the needed HTML
+ * Initialize the dw_linkwizard by creating the needed HTML
* and attaching the eventhandlers
*/
- init: function(textArea){
- // prepare AJAX object
- linkwiz.sack = new sack(DOKU_BASE + 'lib/exe/ajax.php');
- linkwiz.sack.AjaxFailedAlert = '';
- linkwiz.sack.encodeURIString = false;
+ init: function($editor){
+ // position relative to the text area
+ var pos = $editor.position();
// create HTML Structure
- linkwiz.wiz = document.createElement('div');
- linkwiz.wiz.id = 'link__wiz';
- linkwiz.wiz.className = 'picker';
- linkwiz.wiz.style.top = (findPosY(textArea)+20)+'px';
- linkwiz.wiz.style.left = (findPosX(textArea)+80)+'px';
- linkwiz.wiz.style.marginLeft = '-10000px';
- linkwiz.wiz.style.marginTop = '-10000px';
- linkwiz.wiz.style.position = 'absolute';
-
- linkwiz.wiz.innerHTML =
- '<div id="link__wiz_header">'+
- '<img src="'+DOKU_BASE+'lib/images/close.png" width="16" height="16" align="right" alt="" id="link__wiz_close" />'+
- LANG['linkwiz']+'</div>'+
- '<div>'+LANG['linkto']+' <input type="text" class="edit" id="link__wiz_entry" autocomplete="off" /></div>'+
- '<div id="link__wiz_result"></div>';
- $('dw__editform').parentNode.appendChild(linkwiz.wiz);
- linkwiz.textArea = textArea;
- linkwiz.result = $('link__wiz_result');
- linkwiz.entry = $('link__wiz_entry');
+ dw_linkwiz.$wiz = jQuery(document.createElement('div'))
+ .dialog({
+ autoOpen: false,
+ draggable: true,
+ title: LANG.linkwiz,
+ resizable: false
+ })
+ .html(
+ '<div>'+LANG.linkto+' <input type="text" class="edit" id="link__wiz_entry" autocomplete="off" /></div>'+
+ '<div id="link__wiz_result"></div>'
+ )
+ .parent()
+ .attr('id','link__wiz')
+ .addClass('a11y')
+ .css({
+ 'position': 'absolute',
+ 'top': (pos.top+20)+'px',
+ 'left': (pos.left+80)+'px'
+ })
+ .show()
+ .appendTo('div.dokuwiki');
+
+ dw_linkwiz.textArea = $editor[0];
+ dw_linkwiz.result = jQuery('#link__wiz_result')[0];
+
+ // scrollview correction on arrow up/down gets easier
+ jQuery(dw_linkwiz.result).css('position', 'relative');
+
+ dw_linkwiz.$entry = jQuery('#link__wiz_entry');
// attach event handlers
- var obj;
- obj = $('link__wiz_close');
- obj.onclick = linkwiz.hide;
-
- linkwiz.sack.elementObj = linkwiz.result;
- addEvent(linkwiz.entry,'keyup',linkwiz.onEntry);
- addEvent(linkwiz.result,'click',linkwiz.onResultClick);
- drag.attach(linkwiz.wiz,$('link__wiz_header'));
+ jQuery('#link__wiz_close').click(dw_linkwiz.hide);
+ dw_linkwiz.$entry.keyup(dw_linkwiz.onEntry);
+ jQuery(dw_linkwiz.result).delegate('a', 'click', dw_linkwiz.onResultClick);
},
/**
@@ -63,56 +66,59 @@ var linkwiz = {
return true; //ignore
}
if(e.keyCode == 27){
- linkwiz.hide();
+ dw_linkwiz.hide();
e.preventDefault();
e.stopPropagation();
return false;
}
if(e.keyCode == 38){ //Up
- linkwiz.select(linkwiz.selected -1);
+ dw_linkwiz.select(dw_linkwiz.selected -1);
e.preventDefault();
e.stopPropagation();
return false;
}
if(e.keyCode == 40){ //Down
- linkwiz.select(linkwiz.selected +1);
+ dw_linkwiz.select(dw_linkwiz.selected +1);
e.preventDefault();
e.stopPropagation();
return false;
}
if(e.keyCode == 13){ //Enter
- if(linkwiz.selected > -1){
- var obj = linkwiz.getResult(linkwiz.selected);
- if(obj){
- var a = obj.getElementsByTagName('A')[0];
- linkwiz.resultClick(a);
+ if(dw_linkwiz.selected > -1){
+ var $obj = dw_linkwiz.$getResult(dw_linkwiz.selected);
+ if($obj.length > 0){
+ dw_linkwiz.resultClick($obj.find('a')[0]);
}
- }else if(linkwiz.entry.value){
- linkwiz.insertLink(linkwiz.entry.value);
+ }else if(dw_linkwiz.$entry.val()){
+ dw_linkwiz.insertLink(dw_linkwiz.$entry.val());
}
e.preventDefault();
e.stopPropagation();
return false;
}
- linkwiz.autocomplete();
+ dw_linkwiz.autocomplete();
},
/**
- * Get one of the result by index
+ * Get one of the results by index
*
* @param int result div to return
* @returns DOMObject or null
*/
getResult: function(num){
- var obj;
- var childs = linkwiz.result.getElementsByTagName('DIV');
- obj = childs[num];
- if(obj){
- return obj;
- }else{
- return null;
- }
+ DEPRECATED('use dw_linkwiz.$getResult()[0] instead');
+ return dw_linkwiz.$getResult()[0] || null;
+ },
+
+ /**
+ * Get one of the results by index
+ *
+ * @param int result div to return
+ * @returns jQuery object
+ */
+ $getResult: function(num) {
+ return jQuery(dw_linkwiz.result).find('div').eq(num);
},
/**
@@ -120,43 +126,45 @@ var linkwiz = {
*/
select: function(num){
if(num < 0){
- linkwiz.deselect();
+ dw_linkwiz.deselect();
return;
}
- var obj = linkwiz.getResult(num);
- if(obj){
- linkwiz.deselect();
- obj.className += ' selected';
-
- // make sure the item is viewable in the scroll view
- // FIXME check IE compatibility
- if(obj.offsetTop > linkwiz.result.scrollTop + linkwiz.result.clientHeight){
- linkwiz.result.scrollTop += obj.clientHeight;
- }else if(obj.offsetTop - linkwiz.result.clientHeight < linkwiz.result.scrollTop){ // this works but isn't quite right, fixes welcome
- linkwiz.result.scrollTop -= obj.clientHeight;
- }
- // now recheck - if still not in view, the user used the mouse to scroll
- if( (obj.offsetTop > linkwiz.result.scrollTop + linkwiz.result.clientHeight) ||
- (obj.offsetTop < linkwiz.result.scrollTop) ){
- obj.scrollIntoView();
- }
+ var $obj = dw_linkwiz.$getResult(num);
+ if ($obj.length === 0) {
+ return;
+ }
- linkwiz.selected = num;
+ dw_linkwiz.deselect();
+ $obj.addClass('selected');
+
+ // make sure the item is viewable in the scroll view
+
+ //getting child position within the parent
+ var childPos = $obj.position().top;
+ //getting difference between the childs top and parents viewable area
+ var yDiff = childPos + $obj.outerHeight() - jQuery(dw_linkwiz.result).innerHeight();
+
+ if (childPos < 0) {
+ //if childPos is above viewable area (that's why it goes negative)
+ jQuery(dw_linkwiz.result)[0].scrollTop += childPos;
+ } else if(yDiff > 0) {
+ // if difference between childs top and parents viewable area is
+ // greater than the height of a childDiv
+ jQuery(dw_linkwiz.result)[0].scrollTop += yDiff;
}
+
+ dw_linkwiz.selected = num;
},
/**
* deselect a result if any is selected
*/
deselect: function(){
- if(linkwiz.selected > -1){
- var obj = linkwiz.getResult(linkwiz.selected);
- if(obj){
- obj.className = obj.className.replace(/ ?selected/,'');
- }
+ if(dw_linkwiz.selected > -1){
+ dw_linkwiz.$getResult(dw_linkwiz.selected).removeClass('selected');
}
- linkwiz.selected = -1;
+ dw_linkwiz.selected = -1;
},
/**
@@ -164,10 +172,12 @@ var linkwiz = {
* resultClick()
*/
onResultClick: function(e){
- if(e.target.tagName != 'A') return;
+ if(!jQuery(this).is('a')) {
+ return;
+ }
e.stopPropagation();
e.preventDefault();
- linkwiz.resultClick(e.target);
+ dw_linkwiz.resultClick(this);
return false;
},
@@ -175,33 +185,37 @@ var linkwiz = {
* Handles the "click" on a given result anchor
*/
resultClick: function(a){
- var id = a.title;
- if(id == '' || id.substr(id.length-1) == ':'){
- linkwiz.entry.value = id;
- linkwiz.autocomplete_exec();
+ dw_linkwiz.$entry.val(a.title);
+ if(a.title == '' || a.title.substr(-1) == ':'){
+ dw_linkwiz.autocomplete_exec();
}else{
- linkwiz.entry.value = id;
- if(a.nextSibling && a.nextSibling.tagName == 'SPAN'){
- linkwiz.insertLink(a.nextSibling.innerHTML);
+ if (jQuery(a.nextSibling).is('span')) {
+ dw_linkwiz.insertLink(a.nextSibling.innerHTML);
}else{
- linkwiz.insertLink('');
+ dw_linkwiz.insertLink('');
}
}
},
/**
* Insert the id currently in the entry box to the textarea,
- * replacing the current selection or at the curso postion.
+ * replacing the current selection or at the cursor position.
* When no selection is available the given title will be used
* as link title instead
*/
insertLink: function(title){
- if(!linkwiz.entry.value) return;
+ var link = dw_linkwiz.$entry.val(),
+ sel, stxt;
+ if(!link) {
+ return;
+ }
- var sel = getSelection(linkwiz.textArea);
- if(sel.start == 0 && sel.end == 0) sel = linkwiz.selection;
+ sel = getSelection(dw_linkwiz.textArea);
+ if(sel.start == 0 && sel.end == 0) {
+ sel = dw_linkwiz.selection;
+ }
- var stxt = sel.getText();
+ stxt = sel.getText();
// don't include trailing space in selection
if(stxt.charAt(stxt.length - 1) == ' '){
@@ -209,25 +223,29 @@ var linkwiz = {
stxt = sel.getText();
}
- if(!stxt && !DOKU_UHC) stxt=title;
+ if(!stxt && !DOKU_UHC) {
+ stxt=title;
+ }
// prepend colon inside namespaces for non namespace pages
- if(linkwiz.textArea.form['id'].value.indexOf(':') != -1 &&
- linkwiz.entry.value.indexOf(':') == -1){
- linkwiz.entry.value = ':'+linkwiz.entry.value;
+ if(dw_linkwiz.textArea.form.id.value.indexOf(':') != -1 &&
+ link.indexOf(':') == -1){
+ link = ':' + link;
}
- var link = '[['+linkwiz.entry.value+'|';
- if(stxt) link += stxt;
+ var so = link.length+3;
+
+ link = '[['+link+'|';
+ if(stxt) {
+ link += stxt;
+ }
link += ']]';
- var so = linkwiz.entry.value.length+3;
- var eo = 2;
+ pasteText(sel,link,{startofs: so, endofs: 2});
+ dw_linkwiz.hide();
- pasteText(sel,link,{startofs: so, endofs: eo});
- linkwiz.hide();
- // reset the entry to the parent namespace and remove : at the beginning
- linkwiz.entry.value = linkwiz.entry.value.replace(/(^:)?[^:]*$/, '');
+ // reset the entry to the parent namespace
+ dw_linkwiz.$entry.val(dw_linkwiz.$entry.val().replace(/[^:]*$/, ''));
},
/**
@@ -236,60 +254,56 @@ var linkwiz = {
* Calls autocomplete_exec when the timer runs out
*/
autocomplete: function(){
- if(linkwiz.timer !== null){
- window.clearTimeout(linkwiz.timer);
- linkwiz.timer = null;
+ if(dw_linkwiz.timer !== null){
+ window.clearTimeout(dw_linkwiz.timer);
+ dw_linkwiz.timer = null;
}
- linkwiz.timer = window.setTimeout(linkwiz.autocomplete_exec,350);
+ dw_linkwiz.timer = window.setTimeout(dw_linkwiz.autocomplete_exec,350);
},
/**
* Executes the AJAX call for the page/namespace lookup
*/
autocomplete_exec: function(){
- linkwiz.deselect();
- linkwiz.result.innerHTML = '<img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="" width="16" height="16" />';
- linkwiz.sack.runAJAX('call=linkwiz&q='+encodeURI(linkwiz.entry.value));
- },
-
- /**
- * Clears the result area
- */
- clear: function(){
- linkwiz.result.innerHTML = 'Search for a matching page name above, or browse through the pages on the right';
- linkwiz.entry.value = '';
+ var $res = jQuery(dw_linkwiz.result);
+ dw_linkwiz.deselect();
+ $res.html('<img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="" width="16" height="16" />')
+ .load(
+ DOKU_BASE + 'lib/exe/ajax.php',
+ {
+ call: 'linkwiz',
+ q: dw_linkwiz.$entry.val()
+ }
+ );
},
/**
- * Show the linkwizard
+ * Show the link wizard
*/
show: function(){
- linkwiz.selection = getSelection(linkwiz.textArea);
- linkwiz.wiz.style.marginLeft = '0px';
- linkwiz.wiz.style.marginTop = '0px';
- linkwiz.entry.focus();
- linkwiz.autocomplete();
+ dw_linkwiz.selection = getSelection(dw_linkwiz.textArea);
+ dw_linkwiz.$wiz.removeClass('a11y');
+ dw_linkwiz.$entry.focus();
+ dw_linkwiz.autocomplete();
},
/**
* Hide the link wizard
*/
hide: function(){
- linkwiz.wiz.style.marginLeft = '-10000px';
- linkwiz.wiz.style.marginTop = '-10000px';
- linkwiz.textArea.focus();
+ dw_linkwiz.$wiz.addClass('a11y');
+ dw_linkwiz.textArea.focus();
},
/**
* Toggle the link wizard
*/
toggle: function(){
- if(linkwiz.wiz.style.marginLeft == '-10000px'){
- linkwiz.show();
+ if(dw_linkwiz.$wiz.hasClass('a11y')){
+ dw_linkwiz.show();
}else{
- linkwiz.hide();
+ dw_linkwiz.hide();
}
}
};
-