summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/exe/js.php1
-rw-r--r--lib/scripts/edit.js176
-rw-r--r--lib/scripts/toolbar.js161
3 files changed, 211 insertions, 127 deletions
diff --git a/lib/exe/js.php b/lib/exe/js.php
index 7ba777928..26323e9b0 100644
--- a/lib/exe/js.php
+++ b/lib/exe/js.php
@@ -51,6 +51,7 @@ function js_out(){
);
if($edit){
if($write){
+ $files[] = DOKU_INC.'lib/scripts/toolbar.js';
$files[] = DOKU_INC.'lib/scripts/edit.js';
}
$files[] = DOKU_INC.'lib/scripts/media.js';
diff --git a/lib/scripts/edit.js b/lib/scripts/edit.js
index c3265c477..34305c53d 100644
--- a/lib/scripts/edit.js
+++ b/lib/scripts/edit.js
@@ -153,6 +153,8 @@ function initToolbar(tbid,edid,tb){
{
if(eval(actionFunc+"(btn, tb[i], edid, i)"))
toolbar.appendChild(btn);
+ }else{
+ alert('unknown type: '+tb[i]['type']);
}
} // end for
}
@@ -258,144 +260,64 @@ function addBtnActionMediapopup(btn, props)
return true;
}
+function addBtnActionAutohead(btn, props, edid, id)
+{
+ eval("btn.onclick = function(){"+
+ "insertHeadline('"+edid+"',"+props['mod']+",'"+jsEscape(props['text'])+"'); "+
+ "return false};");
+ return true;
+}
+
+
+
+
/**
- * Format selection
- *
- * Apply tagOpen/tagClose to selection in textarea, use sampleText instead
- * of selection if there is none. Copied and adapted from phpBB
+ * Determine the current section level while editing
*
- * @author phpBB development team
- * @author MediaWiki development team
- * @author Andreas Gohr <andi@splitbrain.org>
- * @author Jim Raynor <jim_raynor@web.de>
+ * @author Andreas Gohr <gohr@cosmocode.de>
*/
-function insertTags(edid,tagOpen, tagClose, sampleText) {
- var txtarea = document.getElementById(edid);
- // IE
- if(document.selection && !is_gecko) {
- var theSelection = document.selection.createRange().text;
- var replaced = true;
- if(!theSelection){
- replaced = false;
- theSelection=sampleText;
- }
- txtarea.focus();
-
- // This has change
- var text = theSelection;
- if(theSelection.charAt(theSelection.length - 1) == " "){// exclude ending space char, if any
- theSelection = theSelection.substring(0, theSelection.length - 1);
- r = document.selection.createRange();
- r.text = tagOpen + theSelection + tagClose + " ";
- } else {
- r = document.selection.createRange();
- r.text = tagOpen + theSelection + tagClose;
- }
- if(!replaced){
- r.moveStart('character',-text.length-tagClose.length);
- r.moveEnd('character',-tagClose.length);
- }
- r.select();
- // Mozilla
- } else if(txtarea.selectionStart || txtarea.selectionStart == '0') {
- replaced = false;
- var startPos = txtarea.selectionStart;
- var endPos = txtarea.selectionEnd;
- if(endPos - startPos){ replaced = true; }
- var scrollTop=txtarea.scrollTop;
- var myText = (txtarea.value).substring(startPos, endPos);
- if(!myText) { myText=sampleText;}
- if(myText.charAt(myText.length - 1) == " "){ // exclude ending space char, if any
- subst = tagOpen + myText.substring(0, (myText.length - 1)) + tagClose + " ";
- } else {
- subst = tagOpen + myText + tagClose;
- }
- txtarea.value = txtarea.value.substring(0, startPos) + subst +
- txtarea.value.substring(endPos, txtarea.value.length);
- txtarea.focus();
-
- //set new selection
- if(replaced){
- var cPos=startPos+(tagOpen.length+myText.length+tagClose.length);
- txtarea.selectionStart=cPos;
- txtarea.selectionEnd=cPos;
- }else{
- txtarea.selectionStart=startPos+tagOpen.length;
- txtarea.selectionEnd=startPos+tagOpen.length+myText.length;
- }
- txtarea.scrollTop=scrollTop;
- // All others
- } else {
- var copy_alertText=alertText;
- var re1=new RegExp("\\$1","g");
- var re2=new RegExp("\\$2","g");
- copy_alertText=copy_alertText.replace(re1,sampleText);
- copy_alertText=copy_alertText.replace(re2,tagOpen+sampleText+tagClose);
-
- if (sampleText) {
- text=prompt(copy_alertText);
- } else {
- text="";
- }
- if(!text) { text=sampleText;}
- text=tagOpen+text+tagClose;
- //append to the end
- txtarea.value += "\n"+text;
-
- // in Safari this causes scrolling
- if(!is_safari) {
- txtarea.focus();
+function currentHeadlineLevel(textboxId){
+ var field = $(textboxId);
+ var selection = getSelection(field);
+ var search = field.value.substr(0,selection.start);
+ var lasthl = search.lastIndexOf("\n==");
+ if(lasthl == -1 && field.form.prefix){
+ // we need to look in prefix context
+ search = field.form.prefix.value;
+ lasthl = search.lastIndexOf("\n==");
}
+ search = search.substr(lasthl+1,6);
- }
- // reposition cursor if possible
- if (txtarea.createTextRange){
- txtarea.caretPos = document.selection.createRange().duplicate();
- }
+ if(search == '======') return 1;
+ if(search.substr(0,5) == '=====') return 2;
+ if(search.substr(0,4) == '====') return 3;
+ if(search.substr(0,3) == '===') return 4;
+ if(search.substr(0,2) == '==') return 5;
+
+ return 0;
}
-/*
- * Insert the given value at the current cursor position
+/**
+ * Insert a new headline based on the current section level
*
- * @see http://www.alexking.org/index.php?content=software/javascript/content.php
+ * @param string textboxId - the edit field ID
+ * @param int mod - the headline modificator ( -1, 0, 1)
+ * @param string text - the sample text passed to insertTags
*/
-function insertAtCarret(edid,value){
- var field = document.getElementById(edid);
-
- //IE support
- if (document.selection) {
- field.focus();
- sel = document.selection.createRange();
- sel.text = value;
-
- //MOZILLA/NETSCAPE support
- }else if (field.selectionStart || field.selectionStart == '0') {
- var startPos = field.selectionStart;
- var endPos = field.selectionEnd;
- var scrollTop = field.scrollTop;
- field.value = field.value.substring(0, startPos) +
- value +
- field.value.substring(endPos, field.value.length);
-
- field.focus();
- var cPos=startPos+(value.length);
- field.selectionStart=cPos;
- field.selectionEnd=cPos;
- field.scrollTop=scrollTop;
- } else {
- field.value += "\n"+value;
- }
- // reposition cursor if possible
- if (field.createTextRange){
- field.caretPos = document.selection.createRange().duplicate();
- }
- if(value){
- window.textChanged = true;
- summaryCheck();
- }
-}
+function insertHeadline(textboxId,mod,text){
+ var lvl = currentHeadlineLevel(textboxId);
+ // determine new level
+ lvl += mod;
+ if(lvl < 1) lvl = 1;
+ if(lvl > 5) lvl = 5;
+
+ var tags = '=';
+ for(var i=0; i<=5-lvl; i++) tags += '=';
+ insertTags(textboxId, tags+' ', ' '+tags+"\n", text);
+}
+
/**
* global var used for not saved yet warning
*/
diff --git a/lib/scripts/toolbar.js b/lib/scripts/toolbar.js
new file mode 100644
index 000000000..f31e12887
--- /dev/null
+++ b/lib/scripts/toolbar.js
@@ -0,0 +1,161 @@
+/**
+ * selection prototype
+ *
+ * Object that capsulates the selection in a textarea. Returned by getSelection.
+ */
+function selection_class(){
+ this.start = 0;
+ this.end = 0;
+ this.obj = null;
+ this.rangeCopy = null;
+
+ this.getLength = function(){
+ return this.end - this.start;
+ };
+
+ this.getText = function(){
+ if(!this.obj) return '';
+ return this.obj.value.substring(this.start,this.end);
+ }
+}
+
+/**
+ * Get current selection/cursor position in a given textArea
+ *
+ * @link http://groups.drupal.org/node/1210
+ * @returns object - a selection object
+ */
+function getSelection(textArea) {
+ var sel = new selection_class();
+
+ sel.obj = textArea;
+ sel.start = textArea.value.length;
+ sel.end = textArea.value.length;
+
+ textArea.focus();
+ if(document.getSelection) { // Mozilla et al.
+ sel.start = textArea.selectionStart;
+ sel.end = textArea.selectionEnd;
+ } else if(document.selection) { // MSIE
+ // The current selection
+ var range = document.selection.createRange();
+ sel.rangeCopy = range.duplicate();
+ // Select all text
+ sel.rangeCopy.moveToElementText(textArea);
+ // Now move 'dummy' end point to end point of original range
+ sel.rangeCopy.setEndPoint( 'EndToEnd', range );
+ // Now we can calculate start and end points
+ sel.start = sel.rangeCopy.text.length - range.text.length;
+ sel.end = sel.start + range.text.length;
+ }
+ return sel;
+}
+
+/**
+ * Set the selection
+ *
+ * You need to get a selection object via getSelection() first, then modify the
+ * start and end properties and pass it back to this function.
+ *
+ * @link http://groups.drupal.org/node/1210
+ * @param object selection - a selection object as returned by getSelection()
+ */
+function setSelection(selection){
+ if(document.getSelection){ // FF
+ // what a pleasure in FF ;)
+ selection.obj.setSelectionRange(selection.start,selection.end);
+ } else if(document.selection) { // IE
+ // count number of newlines in str to work around stupid IE selection bug
+ var countNL = function(str) {
+ var m = str.split("\n");
+ if (!m || !m.length) return 0;
+ return m.length-1;
+ };
+ var fix = countNL(selection.obj.value.substring(0,selection.start));
+
+ selection.rangeCopy.collapse(true);
+ selection.rangeCopy.moveStart('character',selection.start - fix);
+ selection.rangeCopy.moveEnd('character',selection.end - selection.start);
+ selection.rangeCopy.select();
+ }
+}
+
+/**
+ * Inserts the given text at the current cursor position or replaces the current
+ * selection
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @param string text - the new text to be pasted
+ * @param objct selecttion - selection object returned by getSelection
+ * @param int opts.startofs - number of charcters at the start to skip from new selection
+ * @param int opts.endofs - number of charcters at the end to skip from new selection
+ * @param bool opts.ofs - set tru if new text should not be selected
+ */
+function pasteText(selection,text,opts){
+ if(!opts) opts = {};
+ // replace the content
+ selection.obj.value =
+ selection.obj.value.substring(0, selection.start) + text +
+ selection.obj.value.substring(selection.end, selection.obj.value.length);
+
+ // set new selection
+ selection.end = selection.start + text.length;
+
+ // modify the new selection if wanted
+ if(opts.startofs) selection.start += opts.startofs;
+ if(opts.endofs) selection.end -= opts.endofs;
+
+ // no selection wanted? set cursor to end position
+ if(opts.nosel) selection.start = selection.end;
+
+ setSelection(selection);
+}
+
+
+/**
+ * Format selection
+ *
+ * Apply tagOpen/tagClose to selection in textarea, use sampleText instead
+ * of selection if there is none.
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function insertTags(textAreaID, tagOpen, tagClose, sampleText){
+ var txtarea = document.getElementById(textAreaID);
+
+ var selection = getSelection(txtarea);
+ var text = selection.getText();
+
+ // don't include trailing space in selection
+ if(text.charAt(text.length - 1) == ' '){
+ selection.end--;
+ text = selection.getText();
+ }
+
+ // nothing selected, use the sample text
+ if(!text) text = sampleText;
+
+ // surround with tags
+ text = tagOpen + text + tagClose;
+
+ // prepare options
+ var opts = {
+ startofs: tagOpen.length,
+ endofs: tagClose.length
+ };
+
+ // do it
+ pasteText(selection,text,opts);
+}
+
+/**
+ * Wraps around pasteText() for backward compatibility
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function insertAtCarret(textAreaID, text){
+ var txtarea = document.getElementById(textAreaID);
+ var selection = getSelection(txtarea);
+ pasteText(selection,text,{nosel: true});
+}
+