summaryrefslogtreecommitdiff
path: root/lib/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/scripts')
-rw-r--r--lib/scripts/ajax.js104
-rw-r--r--lib/scripts/delay.js69
-rw-r--r--lib/scripts/drag.js72
-rw-r--r--lib/scripts/edit.js150
-rw-r--r--lib/scripts/events.js21
-rw-r--r--lib/scripts/helpers.js4
-rw-r--r--lib/scripts/hotkeys.js304
-rw-r--r--lib/scripts/linkwiz.js5
-rw-r--r--lib/scripts/media.js490
-rw-r--r--lib/scripts/pngbehavior.htc53
-rw-r--r--lib/scripts/script.js134
-rw-r--r--lib/scripts/subscriptions.js46
-rw-r--r--lib/scripts/textselection.js20
-rw-r--r--lib/scripts/toolbar.js23
-rw-r--r--lib/scripts/tw-sack.js5
15 files changed, 1134 insertions, 366 deletions
diff --git a/lib/scripts/ajax.js b/lib/scripts/ajax.js
index a2a48a996..de009d448 100644
--- a/lib/scripts/ajax.js
+++ b/lib/scripts/ajax.js
@@ -1,68 +1,48 @@
/**
* AJAX functions for the pagename quicksearch
*
- * We're using a global object with self referencing methods
- * here to make callbacks work
- *
* @license GPL2 (http://www.gnu.org/licenses/gpl.html)
* @author Andreas Gohr <andi@splitbrain.org>
+ * @author Adrian Lang <lang@cosmocode.de>
*/
-
-//prepare class
-function ajax_qsearch_class(){
- this.sack = null;
- this.inObj = null;
- this.outObj = null;
- this.timer = null;
-}
-
-//create global object and add functions
-var ajax_qsearch = new ajax_qsearch_class();
-ajax_qsearch.sack = new sack(DOKU_BASE + 'lib/exe/ajax.php');
-ajax_qsearch.sack.AjaxFailedAlert = '';
-ajax_qsearch.sack.encodeURIString = false;
-
-ajax_qsearch.init = function(inID,outID){
- ajax_qsearch.inObj = document.getElementById(inID);
- ajax_qsearch.outObj = document.getElementById(outID);
-
- // objects found?
- if(ajax_qsearch.inObj === null){ return; }
- if(ajax_qsearch.outObj === null){ return; }
-
- // attach eventhandler to search field
- addEvent(ajax_qsearch.inObj,'keyup',ajax_qsearch.call);
-
- // attach eventhandler to output field
- addEvent(ajax_qsearch.outObj,'click',function(){ ajax_qsearch.outObj.style.display='none'; });
-};
-
-ajax_qsearch.clear = function(){
- ajax_qsearch.outObj.style.display = 'none';
- ajax_qsearch.outObj.innerHTML = '';
- if(ajax_qsearch.timer !== null){
- window.clearTimeout(ajax_qsearch.timer);
- ajax_qsearch.timer = null;
- }
-};
-
-ajax_qsearch.exec = function(){
- ajax_qsearch.clear();
- var value = ajax_qsearch.inObj.value;
- if(value === ''){ return; }
- ajax_qsearch.sack.runAJAX('call=qsearch&q='+encodeURI(value));
-};
-
-ajax_qsearch.sack.onCompletion = function(){
- var data = ajax_qsearch.sack.response;
- if(data === ''){ return; }
-
- ajax_qsearch.outObj.innerHTML = data;
- ajax_qsearch.outObj.style.display = 'block';
-};
-
-ajax_qsearch.call = function(){
- ajax_qsearch.clear();
- ajax_qsearch.timer = window.setTimeout("ajax_qsearch.exec()",500);
-};
-
+addInitEvent(function () {
+
+ var inID = 'qsearch__in';
+ var outID = 'qsearch__out';
+
+ var inObj = document.getElementById(inID);
+ var outObj = document.getElementById(outID);
+
+ // objects found?
+ if (inObj === null){ return; }
+ if (outObj === null){ return; }
+
+ function clear_results(){
+ outObj.style.display = 'none';
+ outObj.innerHTML = '';
+ }
+
+ var sack_obj = new sack(DOKU_BASE + 'lib/exe/ajax.php');
+ sack_obj.AjaxFailedAlert = '';
+ sack_obj.encodeURIString = false;
+ sack_obj.onCompletion = function () {
+ var data = sack_obj.response;
+ if (data === '') { return; }
+
+ outObj.innerHTML = data;
+ outObj.style.display = 'block';
+ };
+
+ // attach eventhandler to search field
+ var delay = new Delay(function () {
+ clear_results();
+ var value = inObj.value;
+ if(value === ''){ return; }
+ sack_obj.runAJAX('call=qsearch&q=' + encodeURI(value));
+ });
+
+ addEvent(inObj, 'keyup', function () {clear_results(); delay.start(); });
+
+ // attach eventhandler to output field
+ addEvent(outObj, 'click', function () {outObj.style.display = 'none'; });
+});
diff --git a/lib/scripts/delay.js b/lib/scripts/delay.js
new file mode 100644
index 000000000..2ef9f8846
--- /dev/null
+++ b/lib/scripts/delay.js
@@ -0,0 +1,69 @@
+/**
+ * Manage delayed and timed actions
+ *
+ * @license GPL2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Adrian Lang <lang@cosmocode.de>
+ */
+
+/**
+ * Provide a global callback for window.setTimeout
+ *
+ * To get a timeout for non-global functions, just call
+ * delay.add(func, timeout).
+ */
+var timer = {
+ _cur_id: 0,
+ _handlers: {},
+
+ execDispatch: function (id) {
+ timer._handlers[id]();
+ },
+
+ add: function (func, timeout) {
+ var id = ++timer._cur_id;
+ timer._handlers[id] = func;
+ return window.setTimeout('timer.execDispatch(' + id + ')', timeout);
+ }
+};
+
+/**
+ * Provide a delayed start
+ *
+ * To call a function with a delay, just create a new Delay(func, timeout) and
+ * call that object’s method “start”.
+ */
+function Delay (func, timeout) {
+ this.func = func;
+ if (timeout) {
+ this.timeout = timeout;
+ }
+}
+
+Delay.prototype = {
+ func: null,
+ timeout: 500,
+
+ delTimer: function () {
+ if (this.timer !== null) {
+ window.clearTimeout(this.timer);
+ this.timer = null;
+ }
+ },
+
+ start: function () {
+ this.delTimer();
+ var _this = this;
+ this.timer = timer.add(function () { _this.exec.call(_this); },
+ this.timeout);
+
+ this._data = {
+ _this: arguments[0],
+ _params: Array.prototype.slice.call(arguments, 2)
+ };
+ },
+
+ exec: function () {
+ this.delTimer();
+ this.func.call(this._data._this, this._data._params);
+ }
+};
diff --git a/lib/scripts/drag.js b/lib/scripts/drag.js
index 4726b77de..2212fb6c1 100644
--- a/lib/scripts/drag.js
+++ b/lib/scripts/drag.js
@@ -1,8 +1,9 @@
/**
* Makes a DOM object draggable
*
- * This is currently for movable DOM dialogs only. If needed it could be
- * extended to execute callbacks on special events...
+ * If you just want to move objects around, use drag.attach. For full
+ * customization, drag can be used as a javascript prototype, it is
+ * inheritance-aware.
*
* @link http://nofunc.org/Drag_Drop/
*/
@@ -26,36 +27,37 @@ var drag = {
attach: function (obj,handle) {
if(handle){
handle.dragobject = obj;
- addEvent($(handle),'mousedown',drag.start);
}else{
- addEvent($(obj),'mousedown',drag.start);
+ handle = obj;
}
+ var _this = this;
+ addEvent($(handle),'mousedown',function (e) {return _this.start(e); });
},
/**
* Starts the dragging operation
*/
start: function (e){
- drag.handle = e.target;
- if(drag.handle.dragobject){
- drag.obj = drag.handle.dragobject;
+ this.handle = e.target;
+ if(this.handle.dragobject){
+ this.obj = this.handle.dragobject;
}else{
- drag.obj = drag.handle;
+ this.obj = this.handle;
}
- drag.handle.className += ' ondrag';
- drag.obj.className += ' ondrag';
+ this.handle.className += ' ondrag';
+ this.obj.className += ' ondrag';
- drag.oX = parseInt(drag.obj.style.left);
- drag.oY = parseInt(drag.obj.style.top);
- drag.eX = drag.evX(e);
- drag.eY = drag.evY(e);
+ this.oX = parseInt(this.obj.style.left);
+ this.oY = parseInt(this.obj.style.top);
+ this.eX = e.pageX;
+ this.eY = e.pageY;
- addEvent(document,'mousemove',drag.drag);
- addEvent(document,'mouseup',drag.stop);
+ var _this = this;
+ this.mousehandlers = [function (e) {return _this.drag(e);}, function (e) {return _this.stop(e);}];
+ addEvent(document,'mousemove', this.mousehandlers[0]);
+ addEvent(document,'mouseup', this.mousehandlers[1]);
- e.preventDefault();
- e.stopPropagation();
return false;
},
@@ -63,37 +65,21 @@ var drag = {
* Ends the dragging operation
*/
stop: function(){
- drag.handle.className = drag.handle.className.replace(/ ?ondrag/,'');
- drag.obj.className = drag.obj.className.replace(/ ?ondrag/,'');
- removeEvent(document,'mousemove',drag.drag);
- removeEvent(document,'mouseup',drag.stop);
- drag.obj = null;
- drag.handle = null;
+ this.handle.className = this.handle.className.replace(/ ?ondrag/,'');
+ this.obj.className = this.obj.className.replace(/ ?ondrag/,'');
+ removeEvent(document,'mousemove', this.mousehandlers[0]);
+ removeEvent(document,'mouseup', this.mousehandlers[1]);
+ this.obj = null;
+ this.handle = null;
},
/**
* Moves the object during the dragging operation
*/
drag: function(e) {
- if(drag.obj) {
- drag.obj.style.top = (drag.evY(e)+drag.oY-drag.eY+'px');
- drag.obj.style.left = (drag.evX(e)+drag.oX-drag.eX+'px');
+ if(this.obj) {
+ this.obj.style.top = (e.pageY+this.oY-this.eY+'px');
+ this.obj.style.left = (e.pageX+this.oX-this.eX+'px');
}
- },
-
- /**
- * Returns the X position of the given event.
- */
- evX: function(e){
- return (e.pageX) ? e.pageX : e.clientX + document.body.scrollTop; //fixme shouldn't this be scrollLeft?
- },
-
- /**
- * Returns the Y position of the given event.
- */
- evY: function(e){
- return (e.pageY) ? e.pageY : e.clientY + document.body.scrollTop;
}
-
};
-
diff --git a/lib/scripts/edit.js b/lib/scripts/edit.js
index ef0a9a106..01262bcef 100644
--- a/lib/scripts/edit.js
+++ b/lib/scripts/edit.js
@@ -12,12 +12,15 @@
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
-function createToolButton(icon,label,key,id){
+function createToolButton(icon,label,key,id,classname){
var btn = document.createElement('button');
var ico = document.createElement('img');
// preapare the basic button stuff
btn.className = 'toolbutton';
+ if(classname){
+ btn.className += ' '+classname;
+ }
btn.title = label;
if(key){
btn.title += ' ['+key.toUpperCase()+']';
@@ -68,6 +71,7 @@ function createPicker(id,props,edid){
picker.id = id;
picker.style.position = 'absolute';
picker.style.marginLeft = '-10000px'; // no display:none, to keep access keys working
+ picker.style.marginTop = '-10000px';
for(var key in list){
if (!list.hasOwnProperty(key)) continue;
@@ -151,6 +155,7 @@ function keyHandler(e){
e.keyCode != 32) return;
var field = e.target;
var selection = getSelection(field);
+ if(selection.getLength()) return; //there was text selected, keep standard behavior
var search = "\n"+field.value.substr(0,selection.start);
var linestart = Math.max(search.lastIndexOf("\n"),
search.lastIndexOf("\r")); //IE workaround
@@ -162,7 +167,17 @@ function keyHandler(e){
var match = search.match(/(\n +([\*-] ?)?)/);
if(match){
var scroll = field.scrollHeight;
- insertAtCarret(field.id,match[1]);
+ var match2 = search.match(/^\n +[\*-]\s*$/);
+ // Cancel list if the last item is empty (i. e. two times enter)
+ if (match2 && field.value.substr(selection.start).match(/^($|\r?\n)/)) {
+ field.value = field.value.substr(0, linestart) + "\n" +
+ field.value.substr(selection.start);
+ selection.start = linestart + 1;
+ selection.end = linestart + 1;
+ setSelection(selection);
+ } else {
+ insertAtCarret(field.id,match[1]);
+ }
field.scrollTop += (field.scrollHeight - scroll);
e.preventDefault(); // prevent enter key
return false;
@@ -207,7 +222,13 @@ function keyHandler(e){
addInitEvent(function(){
var field = $('wiki__text');
if(!field) return;
- addEvent(field,'keydown',keyHandler);
+ // in Firefox, keypress doesn't send the correct keycodes,
+ // in Opera, the default of keydown can't be prevented
+ if (is_opera) {
+ addEvent(field,'keypress',keyHandler);
+ } else {
+ addEvent(field,'keydown',keyHandler);
+ }
});
/**
@@ -243,88 +264,68 @@ function currentHeadlineLevel(textboxId){
var textChanged = false;
/**
- * Check for changes before leaving the page
+ * Delete the draft before leaving the page
*/
-function changeCheck(msg){
- if(textChanged){
- var ok = confirm(msg);
- if(ok){
- // remove a possibly saved draft using ajax
- var dwform = $('dw__editform');
- if(dwform){
- var params = 'call=draftdel';
- params += '&id='+encodeURIComponent(dwform.elements.id.value);
-
- var sackobj = new sack(DOKU_BASE + 'lib/exe/ajax.php');
- sackobj.AjaxFailedAlert = '';
- sackobj.encodeURIString = false;
- sackobj.runAJAX(params);
- // we send this request blind without waiting for
- // and handling the returned data
- }
+function deleteDraft() {
+ if (is_opera) return;
+
+ // remove a possibly saved draft using ajax
+ var dwform = $('dw__editform');
+ if(dwform){
+ var params = 'call=draftdel';
+ params += '&id='+encodeURIComponent(dwform.elements.id.value);
+
+ var sackobj = new sack(DOKU_BASE + 'lib/exe/ajax.php');
+ // this needs to be synchronous and GET to not be aborted upon page unload
+ sackobj.asynchronous = false;
+ sackobj.method = 'GET';
+ sackobj.AjaxFailedAlert = '';
+ sackobj.encodeURIString = false;
+ sackobj.runAJAX(params);
}
- return ok;
- }else{
- return true;
- }
}
/**
- * Add changeCheck to all Links and Forms (except those with a
- * JSnocheck class), add handlers to monitor changes
+ * Activate "not saved" dialog, add draft deletion to page unload,
+ * add handlers to monitor changes
*
* Sets focus to the editbox as well
- *
- * @fixme this is old and crappy code. needs to be redone
*/
-function initChangeCheck(msg){
- var edit_text = document.getElementById('wiki__text');
- if(!edit_text) return;
- if(edit_text.readOnly) return;
- if(!$('dw__editform')) return;
-
- // add change check for links
- var links = document.getElementsByTagName('a');
- for(var i=0; i < links.length; i++){
- if(links[i].className.indexOf('JSnocheck') == -1){
- links[i].onclick = function(){
- var rc = changeCheck(msg);
- if(window.event) window.event.returnValue = rc;
- return rc;
- };
- }
- }
- // add change check for forms
- var forms = document.forms;
- for(i=0; i < forms.length; i++){
- if(forms[i].className.indexOf('JSnocheck') == -1){
- forms[i].onsubmit = function(){
- var rc = changeCheck(msg);
- if(window.event) window.event.returnValue = rc;
- return rc;
- };
- }
- }
+addInitEvent(function (){
+ var editform = $('dw__editform');
+ if (!editform) return;
- // reset change memory var on submit
- var btn_save = document.getElementById('edbtn__save');
- btn_save.onclick = function(){ textChanged = false; };
- var btn_prev = document.getElementById('edbtn__preview');
- btn_prev.onclick = function(){ textChanged = false; };
+ var edit_text = $('wiki__text');
+ if(edit_text) {
+ if(edit_text.readOnly) return;
- // add change memory setter
- edit_text.onchange = function(){
+ // set focus
+ edit_text.focus();
+ }
+
+ var checkfunc = function(){
textChanged = true; //global var
summaryCheck();
};
- var summary = document.getElementById('edit__summary');
+ addEvent(editform, 'change', checkfunc);
+ addEvent(editform, 'keydown', checkfunc);
+
+ window.onbeforeunload = function(){
+ if(textChanged) {
+ return LANG.notsavedyet;
+ }
+ };
+ window.onunload = deleteDraft;
+
+ // reset change memory var on submit
+ addEvent($('edbtn__save'), 'click', function(){ textChanged = false; });
+ addEvent($('edbtn__preview'), 'click', function(){ textChanged = false; });
+
+ var summary = $('edit__summary');
addEvent(summary, 'change', summaryCheck);
addEvent(summary, 'keyup', summaryCheck);
if (textChanged) summaryCheck();
-
- // set focus
- edit_text.focus();
-}
+});
/**
* Checks if a summary was entered - if not the style is changed
@@ -371,8 +372,7 @@ var locktimer = new locktimer_class();
locktimer.sack.onCompletion = locktimer.refreshed;
// register refresh event
- addEvent($('dw__editform').elements.wikitext,'keypress',function(){locktimer.refresh();});
-
+ addEvent($('dw__editform'),'keypress',function(){locktimer.refresh();});
// start timer
locktimer.reset();
};
@@ -413,12 +413,14 @@ var locktimer = new locktimer_class();
// refresh every minute only
if(now.getTime() - locktimer.lasttime.getTime() > 30*1000){ //FIXME decide on time
var params = 'call=lock&id='+encodeURIComponent(locktimer.pageid);
- if(locktimer.draft){
- var dwform = $('dw__editform');
+ var dwform = $('dw__editform');
+ if(locktimer.draft && dwform.elements.wikitext){
params += '&prefix='+encodeURIComponent(dwform.elements.prefix.value);
params += '&wikitext='+encodeURIComponent(dwform.elements.wikitext.value);
params += '&suffix='+encodeURIComponent(dwform.elements.suffix.value);
- params += '&date='+encodeURIComponent(dwform.elements.date.value);
+ if(dwform.elements.date){
+ params += '&date='+encodeURIComponent(dwform.elements.date.value);
+ }
}
locktimer.sack.runAJAX(params);
locktimer.lasttime = now;
diff --git a/lib/scripts/events.js b/lib/scripts/events.js
index e7526ced7..a1fcac718 100644
--- a/lib/scripts/events.js
+++ b/lib/scripts/events.js
@@ -35,26 +35,31 @@ function removeEvent(element, type, handler) {
function handleEvent(event) {
var returnValue = true;
// grab the event object (IE uses a global event object)
- event = event || fixEvent(window.event);
+ event = event || fixEvent(window.event, this);
// get a reference to the hash table of event handlers
var handlers = this.events[event.type];
// execute each event handler
for (var i in handlers) {
if (!handlers.hasOwnProperty(i)) continue;
- this.$$handleEvent = handlers[i];
- if (this.$$handleEvent(event) === false) {
+ if (handlers[i].call(this, event) === false) {
returnValue = false;
}
}
return returnValue;
};
-function fixEvent(event) {
+function fixEvent(event, _this) {
// add W3C standard event methods
event.preventDefault = fixEvent.preventDefault;
event.stopPropagation = fixEvent.stopPropagation;
// fix target
event.target = event.srcElement;
+ event.currentTarget = _this;
+ // fix coords
+ var base = (document.documentElement.scrollTop?document.documentElement:document.body);
+ event.pageX = (typeof event.pageX !== 'undefined') ? event.pageX : event.clientX + base.scrollLeft;
+ event.pageY = (typeof event.pageY !== 'undefined') ? event.pageY : event.clientY + base.scrollTop;
+
return event;
};
fixEvent.preventDefault = function() {
@@ -103,8 +108,8 @@ window.fireoninit = function() {
}
// for Internet Explorer (using conditional comments)
- /*@cc_on @*/
- /*@if (@_win32)
+ /*@cc_on
+ @if (@_win32)
document.write("<scr" + "ipt id=\"__ie_init\" defer=\"true\" src=\"//:\"><\/script>");
var script = document.getElementById("__ie_init");
script.onreadystatechange = function() {
@@ -112,7 +117,7 @@ window.fireoninit = function() {
window.fireoninit(); // call the onload handler
}
};
- /*@end @*/
+ @end @*/
// for Safari
if (/WebKit/i.test(navigator.userAgent)) { // sniff
@@ -172,5 +177,5 @@ function bind (fnc) {
var args = Array.prototype.slice.call(arguments, 1);
return function() {
return fnc.apply(this, args);
- }
+ };
}
diff --git a/lib/scripts/helpers.js b/lib/scripts/helpers.js
index 8d4f3ea78..129964d29 100644
--- a/lib/scripts/helpers.js
+++ b/lib/scripts/helpers.js
@@ -109,7 +109,7 @@ function isEmpty (prop /* :Object */) /* :Boolean */ {
if (isRegExp(prop) && new RegExp("").toString() == prop.toString()) return true;
if (isString(prop) || isNumber(prop)) return !prop;
if (Boolean(prop)&&false != prop) {
- for (var i in prop) if(prop.hasOwnProperty(i)) return false
+ for (var i in prop) if(prop.hasOwnProperty(i)) return false;
}
return true;
}
@@ -124,7 +124,7 @@ function isEmpty (prop /* :Object */) /* :Boolean */ {
if ('undefined' == typeof Object.hasOwnProperty) {
Object.prototype.hasOwnProperty = function (prop) {
return !('undefined' == typeof this[prop] || this.constructor && this.constructor.prototype[prop] && this[prop] === this.constructor.prototype[prop]);
- }
+ };
}
/**
diff --git a/lib/scripts/hotkeys.js b/lib/scripts/hotkeys.js
new file mode 100644
index 000000000..356b691ea
--- /dev/null
+++ b/lib/scripts/hotkeys.js
@@ -0,0 +1,304 @@
+/**
+ * Some of these scripts were taken from TinyMCE (http://tinymce.moxiecode.com/) and were modified for DokuWiki
+ *
+ * Class handles accesskeys using javascript and also provides ability
+ * to register and use other hotkeys as well.
+ *
+ * @author Marek Sacha <sachamar@fel.cvut.cz>
+ */
+function Hotkeys() {
+
+ this.shortcuts = new Array();
+
+ /**
+ * Set modifier keys, for instance:
+ * this.modifier = 'ctrl';
+ * this.modifier = 'ctrl+shift';
+ * this.modifier = 'ctrl+alt+shift';
+ * this.modifier = 'alt';
+ * this.modifier = 'alt+shift';
+ *
+ * overwritten in intitialize (see below)
+ */
+ this.modifier = 'ctrl+alt';
+
+ /**
+ * Initialization
+ *
+ * This function looks up all the accesskeys used in the current page
+ * (at anchor elements and input elements [type="submit"]) and registers
+ * appropriate shortcuts.
+ *
+ * Secondly, initialization registers listeners on document to catch all
+ * keyboard events.
+ *
+ * @author Marek Sacha <sachamar@fel.cvut.cz>
+ */
+ this.initialize = function() {
+ var t = this;
+
+ //switch modifier key based on OS FS#1958
+ if(is_macos){
+ t.modifier = 'ctrl+alt';
+ }else{
+ t.modifier = 'alt';
+ }
+
+ /**
+ * Lookup all anchors with accesskey and register event - go to anchor
+ * target.
+ */
+ var anchors = document.getElementsByTagName("a");
+ t.each(anchors, function(a) {
+ if (a.accessKey != "") {
+ t.addShortcut(t.modifier + '+' + a.accessKey, function() {
+ a.click();
+ });
+ a.accessKey = '';
+ }
+ });
+
+ /**
+ * Lookup all input [type="submit"] with accesskey and register event -
+ * perform "click" on a button.
+ */
+ var inputs = document.getElementsByTagName("input");
+ t.each(inputs, function(i) {
+ if (i.type == "submit" && i.accessKey != "") {
+ t.addShortcut(t.modifier + '+' + i.accessKey, function() {
+ i.click();
+ });
+ i.accessKey = '';
+ }
+ });
+
+ /**
+ * Lookup all buttons with accesskey and register event -
+ * perform "click" on a button.
+ */
+ var buttons = document.getElementsByTagName("button");
+ t.each(buttons, function(b) {
+ if (b.accessKey != "") {
+ t.addShortcut(t.modifier + '+' + b.accessKey, function() {
+ b.click();
+ });
+ b.accessKey = '';
+ }
+ });
+
+ /**
+ * Register listeners on document to catch keyboard events.
+ */
+
+ addEvent(document,'keyup',function (e) {
+ return t.onkeyup.call(t,e);
+ });
+
+ addEvent(document,'keypress',function (e) {
+ return t.onkeypress.call(t,e);
+ });
+
+ addEvent(document,'keydown',function (e) {
+ return t.onkeydown.call(t,e);
+ });
+ };
+
+ /**
+ * Keyup processing function
+ * Function returns true if keyboard event has registered handler, and
+ * executes the handler function.
+ *
+ * @param e KeyboardEvent
+ * @author Marek Sacha <sachamar@fel.cvut.cz>
+ * @return b boolean
+ */
+ this.onkeyup = function(e) {
+ var t = this;
+ var v = t.findShortcut(e);
+ if (v != null && v != false) {
+ v.func.call(t);
+ return false;
+ }
+ return true;
+ };
+
+ /**
+ * Keydown processing function
+ * Function returns true if keyboard event has registered handler
+ *
+ * @param e KeyboardEvent
+ * @author Marek Sacha <sachamar@fel.cvut.cz>
+ * @return b boolean
+ */
+ this.onkeydown = function(e) {
+ var t = this;
+ var v = t.findShortcut(e);
+ if (v != null && v != false) {
+ return false;
+ }
+ return true;
+ };
+
+ /**
+ * Keypress processing function
+ * Function returns true if keyboard event has registered handler
+ *
+ * @param e KeyboardEvent
+ * @author Marek Sacha <sachamar@fel.cvut.cz>
+ * @return b
+ */
+ this.onkeypress = function(e) {
+ var t = this;
+ var v = t.findShortcut(e);
+ if (v != null && v != false) {
+ return false;
+ }
+ return true;
+ };
+
+ /**
+ * Register new shortcut
+ *
+ * This function registers new shortcuts, each shortcut is defined by its
+ * modifier keys and a key (with + as delimiter). If shortcut is pressed
+ * cmd_function is performed.
+ *
+ * For example:
+ * pa = "ctrl+alt+p";
+ * pa = "shift+alt+s";
+ *
+ * Full example of method usage:
+ * hotkeys.addShortcut('ctrl+s',function() {
+ * document.getElementByID('form_1').submit();
+ * });
+ *
+ * @param pa String description of the shortcut (ctrl+a, ctrl+shift+p, .. )
+ * @param cmd_func Function to be called if shortcut is pressed
+ * @author Marek Sacha <sachamar@fel.cvut.cz>
+ */
+ this.addShortcut = function(pa, cmd_func) {
+ var t = this;
+
+ var o = {
+ func : cmd_func,
+ alt : false,
+ ctrl : false,
+ shift : false
+ };
+
+ t.each(t.explode(pa, '+'), function(v) {
+ switch (v) {
+ case 'alt':
+ case 'ctrl':
+ case 'shift':
+ o[v] = true;
+ break;
+
+ default:
+ o.charCode = v.charCodeAt(0);
+ o.keyCode = v.toUpperCase().charCodeAt(0);
+ }
+ });
+
+ t.shortcuts.push((o.ctrl ? 'ctrl' : '') + ',' + (o.alt ? 'alt' : '') + ',' + (o.shift ? 'shift' : '') + ',' + o.keyCode, o);
+
+ return true;
+ };
+
+ /**
+ * @property isMac
+ */
+ this.isMac = (navigator.userAgent.indexOf('Mac') != -1);
+
+ /**
+ * Apply function cb on each element of o in the namespace of s
+ * @param o Array of objects
+ * @param cb Function to be called on each object
+ * @param s Namespace to be used during call of cb (default namespace is o)
+ * @author Marek Sacha <sachamar@fel.cvut.cz>
+ */
+ this.each = function(o, cb, s) {
+ var n, l;
+
+ if (!o)
+ return 0;
+
+ s = s || o;
+
+ if (o.length !== undefined) {
+ // Indexed arrays, needed for Safari
+ for (n=0, l = o.length; n < l; n++) {
+ if (cb.call(s, o[n], n, o) === false)
+ return 0;
+ }
+ } else {
+ // Hashtables
+ for (n in o) {
+ if (o.hasOwnProperty(n)) {
+ if (cb.call(s, o[n], n, o) === false)
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+ };
+
+ /**
+ * Explode string according to delimiter
+ * @param s String
+ * @param d Delimiter (default ',')
+ * @author Marek Sacha <sachamar@fel.cvut.cz>
+ * @return a Array of tokens
+ */
+ this.explode = function(s, d) {
+ return s.split(d || ',');
+ };
+
+ /**
+ * Find if the shortcut was registered
+ *
+ * @param e KeyboardEvent
+ * @author Marek Sacha <sachamar@fel.cvut.cz>
+ * @return v Shortcut structure or null if not found
+ */
+ this.findShortcut = function (e) {
+ var t = this;
+ var v = null;
+
+ /* No modifier key used - shortcut does not exist */
+ if (!e.altKey && !e.ctrlKey && !e.metaKey) {
+ return v;
+ }
+
+ t.each(t.shortcuts, function(o) {
+ if (t.isMac && o.ctrl != e.metaKey)
+ return;
+ else if (!t.isMac && o.ctrl != e.ctrlKey)
+ return;
+
+ if (o.alt != e.altKey)
+ return;
+
+ if (o.shift != e.shiftKey)
+ return;
+
+ if (e.keyCode == o.keyCode || (e.charCode && e.charCode == o.charCode)) {
+ v = o;
+ return;
+ }
+ });
+ return v;
+ };
+}
+
+/**
+ * Init function for hotkeys. Called from js.php, to ensure hotkyes are initialized after toolbar.
+ * Call of addInitEvent(initializeHotkeys) is unnecessary now.
+ *
+ * @author Marek Sacha <sachamar@fel.cvut.cz>
+ */
+function initializeHotkeys() {
+ var hotkeys = new Hotkeys();
+ hotkeys.initialize();
+}
diff --git a/lib/scripts/linkwiz.js b/lib/scripts/linkwiz.js
index d687ebbeb..225868592 100644
--- a/lib/scripts/linkwiz.js
+++ b/lib/scripts/linkwiz.js
@@ -30,6 +30,7 @@ var linkwiz = {
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.innerHTML =
'<div id="link__wiz_header">'+
@@ -37,7 +38,7 @@ var linkwiz = {
LANG['linkwiz']+'</div>'+
'<div>'+LANG['linkto']+' <input type="text" class="edit" id="link__wiz_entry" autocomplete="off" /></div>'+
'<div id="link__wiz_result"></div>';
- textArea.form.parentNode.appendChild(linkwiz.wiz);
+ $('dw__editform').parentNode.appendChild(linkwiz.wiz);
linkwiz.textArea = textArea;
linkwiz.result = $('link__wiz_result');
linkwiz.entry = $('link__wiz_entry');
@@ -256,6 +257,7 @@ var linkwiz = {
show: function(){
linkwiz.selection = getSelection(linkwiz.textArea);
linkwiz.wiz.style.marginLeft = '0px';
+ linkwiz.wiz.style.marginTop = '0px';
linkwiz.entry.focus();
linkwiz.autocomplete();
},
@@ -265,6 +267,7 @@ var linkwiz = {
*/
hide: function(){
linkwiz.wiz.style.marginLeft = '-10000px';
+ linkwiz.wiz.style.marginTop = '-10000px';
linkwiz.textArea.focus();
},
diff --git a/lib/scripts/media.js b/lib/scripts/media.js
index 3e4213f19..95b1ab69e 100644
--- a/lib/scripts/media.js
+++ b/lib/scripts/media.js
@@ -6,6 +6,13 @@
var media_manager = {
keepopen: false,
hide: false,
+ align: false,
+ popup: false,
+ id: false,
+ display: false,
+ link: false,
+ size: false,
+ ext: false,
/**
* Attach event handlers to all "folders" below the given element
@@ -141,33 +148,6 @@ var media_manager = {
},
/**
- * Opens the searchfield
- *
- * @author Tobias Sarnowski <sarnowski@cosmocode.de>
- */
- showsearchfield: function(event,link){
- // prepare an AJAX call to fetch the search
- var ajax = new sack(DOKU_BASE + 'lib/exe/ajax.php');
- ajax.AjaxFailedAlert = '';
- ajax.encodeURIString = false;
- if(ajax.failed) return true;
-
- cleanMsgArea();
-
- var content = $('media__content');
- content.innerHTML = '<img src="'+DOKU_BASE+'lib/images/loading.gif" alt="..." class="load" />';
-
- ajax.elementObj = content;
- ajax.afterCompletion = function(){
- media_manager.selectorattach(content);
- media_manager.confirmattach(content);
- media_manager.updatehide();
- };
- ajax.runAJAX(link.search.substr(1)+'&call=mediasearchlist');
- return false;
- },
-
- /**
* Toggles the keep open state
*
* @author Andreas Gohr <andi@splitbrain.org>
@@ -218,24 +198,359 @@ var media_manager = {
},
/**
- * Insert the clicked image into the opener's textarea
- *
- * @author Andreas Gohr <andi@splitbrain.org>
+ * shows the popup for a image link
*/
select: function(event,link){
var id = link.name.substr(2);
+ media_manager.id = id;
if(!opener){
// if we don't run in popup display example
var ex = $('ex_'+id.replace(/:/g,'_'));
if(ex.style.display == ''){
ex.style.display = 'none';
- }else{
+ } else {
ex.style.display = '';
}
return false;
}
- opener.insertTags('wiki__text','{{'+id+'|','}}','');
+
+ media_manager.ext = false;
+ var dot = id.lastIndexOf(".");
+ if (dot != -1) {
+ var ext = id.substr(dot,id.length);
+
+ if (ext != '.jpg' && ext != '.jpeg' && ext != '.png' && ext != '.gif' && ext != '.swf') {
+ media_manager.insert(null);
+ return false;
+ }
+ } else {
+ media_manager.insert(null);
+ return false;
+ }
+
+ media_manager.popup.style.display = 'inline';
+ media_manager.popup.style.left = event.pageX + 'px';
+ media_manager.popup.style.top = event.pageY + 'px';
+
+ // set all buttons to outset
+ media_manager.outSet('media__linkbtn1');
+ media_manager.outSet('media__linkbtn2');
+ media_manager.outSet('media__linkbtn3');
+ media_manager.outSet('media__linkbtn4');
+
+ media_manager.outSet('media__alignbtn0');
+ media_manager.outSet('media__alignbtn1');
+ media_manager.outSet('media__alignbtn2');
+ media_manager.outSet('media__alignbtn3');
+
+ media_manager.outSet('media__sizebtn1');
+ media_manager.outSet('media__sizebtn2');
+ media_manager.outSet('media__sizebtn3');
+ media_manager.outSet('media__sizebtn4');
+
+
+ if (ext == '.swf') {
+ media_manager.ext = 'swf';
+
+ // disable display buttons for detail and linked image
+ $('media__linkbtn1').style.display = 'none';
+ $('media__linkbtn2').style.display = 'none';
+
+ // set the link button to default
+ if (media_manager.link != false) {
+ if ( media_manager.link == '2' || media_manager.link == '1') {
+ media_manager.inSet('media__linkbtn3');
+ media_manager.link = '3';
+ DokuCookie.setValue('link','3');
+ } else {
+ media_manager.inSet('media__linkbtn'+media_manager.link);
+ }
+ } else if (DokuCookie.getValue('link')) {
+ if ( DokuCookie.getValue('link') == '2' || DokuCookie.getValue('link') == '1') {
+ // this options are not availible
+ media_manager.inSet('media__linkbtn3');
+ media_manager.link = '3';
+ DokuCookie.setValue('link','3');
+ } else {
+ media_manager.inSet('media__linkbtn'+DokuCookie.getValue('link'));
+ media_manager.link = DokuCookie.getValue('link');
+ }
+ } else {
+ // default case
+ media_manager.link = '3';
+ media_manager.inSet('media__linkbtn3');
+ DokuCookie.setValue('link','3');
+ }
+
+ // disable button for original size
+ $('media__sizebtn4').style.display = 'none';
+
+ } else {
+ media_manager.ext = 'img';
+
+ // ensure that the display buttons are there
+ $('media__linkbtn1').style.display = 'inline';
+ $('media__linkbtn2').style.display = 'inline';
+ $('media__sizebtn4').style.display = 'inline';
+
+ // set the link button to default
+ if (DokuCookie.getValue('link')) {
+ media_manager.link = DokuCookie.getValue('link');
+ }
+ if (media_manager.link == false) {
+ // default case
+ media_manager.link = '1';
+ DokuCookie.setValue('link','1');
+ }
+ media_manager.inSet('media__linkbtn'+media_manager.link);
+ }
+
+ if (media_manager.link == '4') {
+ media_manager.align = false;
+ media_manager.size = false;
+ $('media__align').style.display = 'none';
+ $('media__size').style.display = 'none';
+ } else {
+ $('media__align').style.display = 'block';
+ $('media__size').style.display = 'block';
+
+ // set the align button to default
+ if (media_manager.align != false) {
+ media_manager.inSet('media__alignbtn'+media_manager.align);
+ } else if (DokuCookie.getValue('align')) {
+ media_manager.inSet('media__alignbtn'+DokuCookie.getValue('align'));
+ media_manager.align = DokuCookie.getValue('align');
+ } else {
+ // default case
+ media_manager.align = '0';
+ media_manager.inSet('media__alignbtn0');
+ DokuCookie.setValue('align','0');
+ }
+
+ // set the size button to default
+ if (DokuCookie.getValue('size')) {
+ media_manager.size = DokuCookie.getValue('size');
+ }
+ if (media_manager.size == false || (media_manager.size === '4' && ext === '.swf')) {
+ // default case
+ media_manager.size = '2';
+ DokuCookie.setValue('size','2');
+ }
+ media_manager.inSet('media__sizebtn'+media_manager.size);
+
+ $('media__sendbtn').focus();
+ }
+
+ return false;
+ },
+
+ /**
+ * build the popup window
+ *
+ * @author Dominik Eckelmann <eckelmann@cosmocode.de>
+ */
+ initpopup: function() {
+
+ media_manager.popup = document.createElement('div');
+ media_manager.popup.setAttribute('id','media__popup');
+
+ var root = document.getElementById('media__manager');
+ if (root == null) return;
+ root.appendChild(media_manager.popup);
+
+ var headline = document.createElement('h1');
+ headline.innerHTML = LANG.mediatitle;
+ var headlineimg = document.createElement('img');
+ headlineimg.src = DOKU_BASE + 'lib/images/close.png';
+ headlineimg.id = 'media__closeimg';
+ addEvent(headlineimg,'click',function(event){ return media_manager.closePopup(event,this); });
+ headline.insertBefore(headlineimg, headline.firstChild);
+ media_manager.popup.appendChild(headline);
+ drag.attach(media_manager.popup,headline);
+
+ // link
+
+ var linkp = document.createElement('p');
+
+ linkp.id = "media__linkstyle";
+ if (media_manager.display == "2") {
+ linkp.style.display = "none";
+ }
+
+ var linkl = document.createElement('label');
+ linkl.innerHTML = LANG.mediatarget;
+ linkp.appendChild(linkl);
+
+ var linkbtns = ['lnk', 'direct', 'nolnk', 'displaylnk'];
+ for (var i = 0 ; i < linkbtns.length ; ++i) {
+ var linkbtn = document.createElement('button');
+ linkbtn.className = 'button';
+ linkbtn.value = i + 1;
+ linkbtn.id = "media__linkbtn" + (i + 1);
+ linkbtn.title = LANG['media' + linkbtns[i]];
+ linkbtn.style.borderStyle = 'outset';
+ addEvent(linkbtn,'click',function(event){ return media_manager.setlink(event,this); });
+
+ var linkimg = document.createElement('img');
+ linkimg.src = DOKU_BASE + 'lib/images/media_link_' + linkbtns[i] + '.png';
+
+ linkbtn.appendChild(linkimg);
+ linkp.appendChild(linkbtn);
+ }
+
+ media_manager.popup.appendChild(linkp);
+
+ // align
+
+ var alignp = document.createElement('p');
+ var alignl = document.createElement('label');
+
+ alignp.appendChild(alignl);
+ alignp.id = 'media__align';
+ if (media_manager.display == "2") {
+ alignp.style.display = "none";
+ }
+ alignl.innerHTML = LANG['mediaalign'];
+
+ var alignbtns = ['noalign', 'left', 'center', 'right'];
+ for (var n = 0 ; n < alignbtns.length ; ++n) {
+ var alignbtn = document.createElement('button');
+ var alignimg = document.createElement('img');
+ alignimg.src = DOKU_BASE + 'lib/images/media_align_' + alignbtns[n] + '.png';
+
+ alignbtn.id = "media__alignbtn" + n;
+ alignbtn.value = n;
+ alignbtn.title = LANG['media' + alignbtns[n]];
+ alignbtn.className = 'button';
+ alignbtn.appendChild(alignimg);
+ alignbtn.style.borderStyle = 'outset';
+ addEvent(alignbtn,'click',function(event){ return media_manager.setalign(event,this); });
+
+ alignp.appendChild(alignbtn);
+ }
+
+ media_manager.popup.appendChild(alignp);
+
+ // size
+
+ var sizep = document.createElement('p');
+ var sizel = document.createElement('label');
+
+ sizep.id = 'media__size';
+ if (media_manager.display == "2") {
+ sizep.style.display = "none";
+ }
+ sizep.appendChild(sizel);
+ sizel.innerHTML = LANG['mediasize'];
+
+ var sizebtns = ['small', 'medium', 'large', 'original'];
+ for (var size = 0 ; size < sizebtns.length ; ++size) {
+ var sizebtn = document.createElement('button');
+ var sizeimg = document.createElement('img');
+
+ sizep.appendChild(sizebtn);
+ sizeimg.src = DOKU_BASE + 'lib/images/media_size_' + sizebtns[size] + '.png';
+
+ sizebtn.className = 'button';
+ sizebtn.appendChild(sizeimg);
+ sizebtn.value = size + 1;
+ sizebtn.id = 'media__sizebtn' + (size + 1);
+ sizebtn.title = LANG['media' + sizebtns[size]];
+ sizebtn.style.borderStyle = 'outset';
+ addEvent(sizebtn,'click',function(event){ return media_manager.setsize(event,this); });
+ }
+
+ media_manager.popup.appendChild(sizep);
+
+ // send and close button
+
+ var btnp = document.createElement('p');
+ media_manager.popup.appendChild(btnp);
+ btnp.setAttribute('class','btnlbl');
+
+ var cls = document.createElement('input');
+ cls.type = 'button';
+ cls.setAttribute('class','button');
+ cls.value = LANG['mediaclose'];
+ btnp.appendChild(cls);
+ addEvent(cls,'click',function(event){ return media_manager.closePopup(event,this); });
+
+ var btn = document.createElement('input');
+ btn.type = 'button';
+ btn.id = 'media__sendbtn';
+ btn.setAttribute('class','button');
+ btn.value = LANG['mediainsert'];
+ btnp.appendChild(btn);
+ addEvent(btn,'click',function(event){ return media_manager.insert(event); });
+ },
+
+ /**
+ * Insert the clicked image into the opener's textarea
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Dominik Eckelmann <eckelmann@cosmocode.de>
+ */
+ insert: function(event){
+ var id = media_manager.id;
+ // set syntax options
+ $('media__popup').style.display = 'none';
+
+ var opts = '';
+ var optsstart = '';
+ var alignleft = '';
+ var alignright = '';
+
+ if (media_manager.ext == 'img' || media_manager.ext == 'swf') {
+
+ if (media_manager.link == '4') {
+ opts = '?linkonly';
+ } else {
+
+ if (media_manager.link == "3" && media_manager.ext == 'img') {
+ opts = '?nolink';
+ optsstart = true;
+ } else if (media_manager.link == "2" && media_manager.ext == 'img') {
+ opts = '?direct';
+ optsstart = true;
+ }
+
+ var s = parseInt(media_manager.size);
+
+ if (s && s >= 1) {
+ opts += (optsstart)?'&':'?';
+ if (s=="1") {
+ opts += '100';
+ if (media_manager.ext == 'swf') {
+ opts += 'x62';
+ }
+ } else if (s=="2") {
+ opts += '200';
+ if (media_manager.ext == 'swf') {
+ opts += 'x123';
+ }
+ } else if (s=="3"){
+ opts += '300';
+ if (media_manager.ext == 'swf') {
+ opts += 'x185';
+ }
+ }
+ }
+ if (media_manager.align == '1') {
+ alignleft = '';
+ alignright = ' ';
+ }
+ if (media_manager.align == '2') {
+ alignleft = ' ';
+ alignright = ' ';
+ }
+ if (media_manager.align == '3') {
+ alignleft = ' ';
+ alignright = '';
+ }
+ }
+ }
+ opener.insertTags('wiki__text','{{'+alignleft+id+opts+alignright+'|','}}','');
if(!media_manager.keepopen) window.close();
opener.focus();
@@ -340,6 +655,116 @@ var media_manager = {
oflash.style.display = '';
};
oform.appendChild(clicky);
+ },
+
+ /**
+ * closes the link type popup
+ */
+ closePopup: function(event) {
+ $('media__popup').style.display = 'none';
+ },
+
+ /**
+ * set the align
+ *
+ * @author Dominik Eckelmann <eckelmann@cosmocode.de>
+ */
+ setalign: function(event,cb){
+ if(cb.value){
+ DokuCookie.setValue('align',cb.value);
+ media_manager.align = cb.value;
+ media_manager.outSet("media__alignbtn0");
+ media_manager.outSet("media__alignbtn1");
+ media_manager.outSet("media__alignbtn2");
+ media_manager.outSet("media__alignbtn3");
+ media_manager.inSet("media__alignbtn"+cb.value);
+ }else{
+ DokuCookie.setValue('align','');
+ media_manager.align = false;
+ }
+ },
+ /**
+ * set the link type
+ *
+ * @author Dominik Eckelmann <eckelmann@cosmocode.de>
+ */
+ setlink: function(event,cb){
+ if(cb.value){
+ DokuCookie.setValue('link',cb.value);
+ media_manager.link = cb.value;
+ media_manager.outSet("media__linkbtn1");
+ media_manager.outSet("media__linkbtn2");
+ media_manager.outSet("media__linkbtn3");
+ media_manager.outSet("media__linkbtn4");
+ media_manager.inSet("media__linkbtn"+cb.value);
+ var size = document.getElementById("media__size");
+ var align = document.getElementById("media__align");
+ if (cb.value != '4') {
+ size.style.display = "block";
+ align.style.display = "block";
+ } else {
+ size.style.display = "none";
+ align.style.display = "none";
+ }
+ }else{
+ DokuCookie.setValue('link','');
+ media_manager.link = false;
+ }
+ },
+
+ /**
+ * set the display type
+ *
+ * @author Dominik Eckelmann <eckelmann@cosmocode.de>
+ */
+ setdisplay: function(event,cb){
+ if(cb.value){
+ DokuCookie.setValue('display',cb.value);
+ media_manager.display = cb.value;
+ media_manager.outSet("media__displaybtn1");
+ media_manager.outSet("media__displaybtn2");
+ media_manager.inSet("media__displaybtn"+cb.value);
+
+ }else{
+ DokuCookie.setValue('display','');
+ media_manager.align = false;
+ }
+ },
+
+ /**
+ * sets the border to outset
+ */
+ outSet: function(id) {
+ var ele = document.getElementById(id);
+ if (ele == null) return;
+ ele.style.borderStyle = "outset";
+ },
+ /**
+ * sets the border to inset
+ */
+ inSet: function(id) {
+ var ele = document.getElementById(id);
+ if (ele == null) return;
+ ele.style.borderStyle = "inset";
+ },
+
+ /**
+ * set the image size
+ *
+ * @author Dominik Eckelmann <eckelmann@cosmocode.de>
+ */
+ setsize: function(event,cb){
+ if (cb.value) {
+ DokuCookie.setValue('size',cb.value);
+ media_manager.size = cb.value;
+ for (var i = 1 ; i <= 4 ; ++i) {
+ media_manager.outSet("media__sizebtn" + i);
+ }
+ media_manager.inSet("media__sizebtn"+cb.value);
+ } else {
+ DokuCookie.setValue('size','');
+ media_manager.width = false;
+ }
}
};
@@ -348,5 +773,6 @@ addInitEvent(function(){
media_manager.selectorattach($('media__content'));
media_manager.confirmattach($('media__content'));
media_manager.attachoptions($('media__opts'));
+ media_manager.initpopup();
media_manager.initFlashUpload();
});
diff --git a/lib/scripts/pngbehavior.htc b/lib/scripts/pngbehavior.htc
deleted file mode 100644
index d1db8e765..000000000
--- a/lib/scripts/pngbehavior.htc
+++ /dev/null
@@ -1,53 +0,0 @@
-// this is an ugly fix to make Internet Explorer work with transparent
-// PNG images - do your self a favour and use a real browser!
-
-<public:component>
-<public:attach event="onpropertychange" onevent="propertyChanged()" />
-<script>
-
-var supported = /MSIE (5\.5)|[6789]/.test(navigator.userAgent) && navigator.platform == "Win32";
-var realSrc;
-var blankSrc = DOKU_BASE+"lib/images/blank.gif";
-
-if (supported) fixImage();
-
-function propertyChanged() {
- if (!supported) return;
-
- var pName = event.propertyName;
- if (pName != "src") return;
- // if not set to blank
- if ( ! new RegExp(blankSrc).test(src))
- fixImage();
-};
-
-function fixImage() {
- // get src
- var src = element.src;
-
- // check for real change
- if (src == realSrc) {
- element.src = blankSrc;
- return;
- }
-
- if ( ! new RegExp(blankSrc).test(src)) {
- // backup old src
- realSrc = src;
- }
-
- // test for png
- if ( /\.png$/.test( realSrc.toLowerCase() ) ) {
- // set blank image
- element.src = blankSrc;
- // set filter
- element.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "',sizingMethod='scale')";
- }
- else {
- // remove filter
- element.runtimeStyle.filter = "";
- }
-}
-
-</script>
-</public:component>
diff --git a/lib/scripts/script.js b/lib/scripts/script.js
index ccba82144..57917aeb5 100644
--- a/lib/scripts/script.js
+++ b/lib/scripts/script.js
@@ -9,7 +9,7 @@ var clientPC = navigator.userAgent.toLowerCase(); // Get client info
var is_macos = navigator.appVersion.indexOf('Mac') != -1;
var is_gecko = ((clientPC.indexOf('gecko')!=-1) && (clientPC.indexOf('spoofer')==-1) &&
(clientPC.indexOf('khtml') == -1) && (clientPC.indexOf('netscape/7.0')==-1));
-var is_safari = ((clientPC.indexOf('AppleWebKit')!=-1) && (clientPC.indexOf('spoofer')==-1));
+var is_safari = ((clientPC.indexOf('applewebkit')!=-1) && (clientPC.indexOf('spoofer')==-1));
var is_khtml = (navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled ));
if (clientPC.indexOf('opera')!=-1) {
var is_opera = true;
@@ -78,16 +78,15 @@ function getElementsByClass(searchClass,node,tag) {
/**
* Get the X offset of the top left corner of the given object
*
- * @link http://www.quirksmode.org/index.html?/js/findpos.html
+ * @link http://www.quirksmode.org/js/findpos.html
*/
function findPosX(object){
var curleft = 0;
var obj = $(object);
if (obj.offsetParent){
- while (obj.offsetParent){
+ do {
curleft += obj.offsetLeft;
- obj = obj.offsetParent;
- }
+ } while (obj = obj.offsetParent);
}
else if (obj.x){
curleft += obj.x;
@@ -98,16 +97,15 @@ function findPosX(object){
/**
* Get the Y offset of the top left corner of the given object
*
- * @link http://www.quirksmode.org/index.html?/js/findpos.html
+ * @link http://www.quirksmode.org/js/findpos.html
*/
function findPosY(object){
var curtop = 0;
var obj = $(object);
if (obj.offsetParent){
- while (obj.offsetParent){
+ do {
curtop += obj.offsetTop;
- obj = obj.offsetParent;
- }
+ } while (obj = obj.offsetParent);
}
else if (obj.y){
curtop += obj.y;
@@ -215,10 +213,7 @@ function addTocToggle() {
prependChild(header,obj);
obj.parentNode.onclick = toggleToc;
- try {
- obj.parentNode.style.cursor = 'pointer';
- obj.parentNode.style.cursor = 'hand';
- }catch(e){}
+ obj.parentNode.style.cursor = 'pointer';
}
/**
@@ -239,57 +234,51 @@ function toggleToc() {
}
/**
- * Display an insitu footnote popup
- *
- * @author Andreas Gohr <andi@splitbrain.org>
- * @author Chris Smith <chris@jalakai.co.uk>
+ * Create JavaScript mouseover popup
*/
-function footnote(e){
- var obj = e.target;
- var id = obj.id.substr(5);
+function insitu_popup(target, popup_id) {
- // get or create the footnote popup div
- var fndiv = $('insitu__fn');
+ // get or create the popup div
+ var fndiv = $(popup_id);
if(!fndiv){
fndiv = document.createElement('div');
- fndiv.id = 'insitu__fn';
+ fndiv.id = popup_id;
fndiv.className = 'insitu-footnote JSpopup dokuwiki';
// autoclose on mouseout - ignoring bubbled up events
addEvent(fndiv,'mouseout',function(e){
- if(e.target != fndiv){
- e.stopPropagation();
- return;
+ var p = e.relatedTarget || e.toElement;
+ while (p && p !== this) {
+ p = p.parentNode;
}
- // check if the element was really left
- if(e.pageX){ // Mozilla
- var bx1 = findPosX(fndiv);
- var bx2 = bx1 + fndiv.offsetWidth;
- var by1 = findPosY(fndiv);
- var by2 = by1 + fndiv.offsetHeight;
- var x = e.pageX;
- var y = e.pageY;
- if(x > bx1 && x < bx2 && y > by1 && y < by2){
- // we're still inside boundaries
- e.stopPropagation();
- return;
- }
- }else{ // IE
- if(e.offsetX > 0 && e.offsetX < fndiv.offsetWidth-1 &&
- e.offsetY > 0 && e.offsetY < fndiv.offsetHeight-1){
- // we're still inside boundaries
- e.stopPropagation();
- return;
- }
+ if (p === this) {
+ return;
}
// okay, hide it
- fndiv.style.display='none';
+ this.style.display='none';
});
- document.body.appendChild(fndiv);
+ getElementsByClass('dokuwiki', document.body, 'div')[0].appendChild(fndiv);
}
+ // position the div and make it visible
+ fndiv.style.position = 'absolute';
+ fndiv.style.left = findPosX(target)+'px';
+ fndiv.style.top = (findPosY(target)+target.offsetHeight * 1.5) + 'px';
+ fndiv.style.display = '';
+ return fndiv;
+}
+
+/**
+ * Display an insitu footnote popup
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Chris Smith <chris@jalakai.co.uk>
+ */
+function footnote(e){
+ var fndiv = insitu_popup(e.target, 'insitu__fn');
+
// locate the footnote anchor element
- var a = $( "fn__"+id );
+ var a = $("fn__" + e.target.id.substr(5));
if (!a){ return; }
// anchor parent is the footnote container, get its innerHTML
@@ -300,24 +289,10 @@ function footnote(e){
content = content.replace(/^\s+(,\s+)+/,'');
// prefix ids on any elements with "insitu__" to ensure they remain unique
- content = content.replace(/\bid=\"(.*?)\"/gi,'id="insitu__$1');
+ content = content.replace(/\bid=(['"])([^"']+)\1/gi,'id="insitu__$2');
// now put the content into the wrapper
fndiv.innerHTML = content;
-
- // position the div and make it visible
- var x; var y;
- if(e.pageX){ // Mozilla
- x = e.pageX;
- y = e.pageY;
- }else{ // IE
- x = e.offsetX;
- y = e.offsetY;
- }
- fndiv.style.position = 'absolute';
- fndiv.style.left = (x+2)+'px';
- fndiv.style.top = (y+2)+'px';
- fndiv.style.display = '';
}
/**
@@ -507,14 +482,14 @@ addInitEvent(function(){
*/
function checkWindowsShares() {
if(!LANG['nosmblinks']) return true;
+ if(document.all != null) return true;
+
var elems = getElementsByClass('windows',document,'a');
if(elems){
for(var i=0; i<elems.length; i++){
var share = elems[i];
addEvent(share,'click',function(){
- if(document.all == null) {
- alert(LANG['nosmblinks']);
- }
+ alert(LANG['nosmblinks']);
});
}
}
@@ -535,27 +510,30 @@ addInitEvent(function(){
* @author Andreas Gohr <andi@splitbrain.org>
*/
addInitEvent(function(){
- var break_classes = new RegExp('secedit|toc|page');
var btns = getElementsByClass('btn_secedit',document,'form');
for(var i=0; i<btns.length; i++){
addEvent(btns[i],'mouseover',function(e){
- var tgt = e.target;
- if(tgt.form) tgt = tgt.form;
- tgt = tgt.parentNode.previousSibling;
- if(tgt.nodeName != "DIV") tgt = tgt.previousSibling;
- while(!break_classes.test(tgt.className)) {
- tgt.className += ' section_highlight';
- if (tgt.tagName == 'H1') break;
- tgt = (tgt.previousSibling != null) ? tgt.previousSibling : tgt.parentNode;
+ var tgt = this.parentNode;
+ var nr = tgt.className.match(/(\s+|^)editbutton_(\d+)(\s+|$)/)[2];
+ do {
+ tgt = tgt.previousSibling;
+ } while (tgt !== null && typeof tgt.tagName === 'undefined');
+ if (tgt === null) return;
+ while(typeof tgt.className === 'undefined' ||
+ tgt.className.match('(\\s+|^)sectionedit' + nr + '(\\s+|$)') === null) {
+ if (typeof tgt.className !== 'undefined') {
+ tgt.className += ' section_highlight';
+ }
+ tgt = (tgt.previousSibling !== null) ? tgt.previousSibling : tgt.parentNode;
}
+ if (typeof tgt.className !== 'undefined') tgt.className += ' section_highlight';
});
addEvent(btns[i],'mouseout',function(e){
var secs = getElementsByClass('section_highlight');
for(var j=0; j<secs.length; j++){
- secs[j].className = secs[j].className.replace(/section_highlight/,'');
+ secs[j].className = secs[j].className.replace(/section_highlight/g,'');
}
- var secs = getElementsByClass('section_highlight');
});
}
});
diff --git a/lib/scripts/subscriptions.js b/lib/scripts/subscriptions.js
new file mode 100644
index 000000000..d701f258f
--- /dev/null
+++ b/lib/scripts/subscriptions.js
@@ -0,0 +1,46 @@
+/**
+ * Hide list subscription style if target is a page
+ *
+ * @author Adrian Lang <lang@cosmocode.de>
+ */
+
+addInitEvent(function () {
+ var form = $('subscribe__form');
+ if (!form) {
+ return;
+ }
+
+ var styleradios = {};
+
+ function update_state() {
+ if (!this.checked) {
+ return;
+ }
+ if (this.value.match(/:$/)) {
+ styleradios.list.parentNode.style.display = '';
+ } else {
+ styleradios.list.parentNode.style.display = 'none';
+ if (styleradios.list.checked) {
+ styleradios.digest.checked = 'checked';
+ }
+ }
+ }
+
+ var cur_sel = null;
+
+ var inputs = form.getElementsByTagName('input');
+ for (var i = 0; i < inputs.length ; ++i) {
+ switch (inputs[i].name) {
+ case 'sub_target':
+ addEvent(inputs[i], 'click', update_state);
+ if (inputs[i].checked) {
+ cur_sel = inputs[i];
+ }
+ break;
+ case 'sub_style':
+ styleradios[inputs[i].value] = inputs[i];
+ break;
+ }
+ }
+ update_state.call(cur_sel);
+});
diff --git a/lib/scripts/textselection.js b/lib/scripts/textselection.js
index 76cc6bcbb..742338785 100644
--- a/lib/scripts/textselection.js
+++ b/lib/scripts/textselection.js
@@ -24,7 +24,7 @@ function selection_class(){
this.getText = function(){
if(!this.obj) return '';
return this.obj.value.substring(this.start,this.end);
- }
+ };
}
/**
@@ -41,7 +41,6 @@ function getSelection(textArea) {
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;
@@ -57,9 +56,13 @@ function getSelection(textArea) {
// The current selection
sel.rangeCopy = document.selection.createRange().duplicate();
-
- var before_range = document.body.createTextRange();
- before_range.moveToElementText(textArea); // Selects all the text
+ if (textArea.tagName === 'INPUT') {
+ var before_range = textArea.createTextRange();
+ before_range.expand('textedit'); // Selects all the text
+ } else {
+ var before_range = document.body.createTextRange();
+ before_range.moveToElementText(textArea); // Selects all the text
+ }
before_range.setEndPoint("EndToStart", sel.rangeCopy); // Moves the end where we need it
var before_finished = false, selection_finished = false;
@@ -158,7 +161,12 @@ function pasteText(selection,text,opts){
selection.obj.value.substring(selection.end, selection.obj.value.length);
// set new selection
- selection.end = selection.start + text.length;
+ if (is_opera) {
+ // Opera replaces \n by \r\n when inserting text.
+ selection.end = selection.start + text.replace(/\r?\n/g, '\r\n').length;
+ } else {
+ selection.end = selection.start + text.length;
+ }
// modify the new selection if wanted
if(opts.startofs) selection.start += opts.startofs;
diff --git a/lib/scripts/toolbar.js b/lib/scripts/toolbar.js
index eacfc7cad..3f967448c 100644
--- a/lib/scripts/toolbar.js
+++ b/lib/scripts/toolbar.js
@@ -5,29 +5,39 @@ var pickercounter=0;
/**
* Create a toolbar
*
- * @param string tbid ID of the element where to insert the toolbar
- * @param string edid ID of the editor textarea
- * @param array tb Associative array defining the buttons
+ * @param string tbid ID of the element where to insert the toolbar
+ * @param string edid ID of the editor textarea
+ * @param array tb Associative array defining the buttons
+ * @param bool allowblock Allow buttons creating multiline content
* @author Andreas Gohr <andi@splitbrain.org>
*/
-function initToolbar(tbid,edid,tb){
+function initToolbar(tbid,edid,tb, allowblock){
var toolbar = $(tbid);
if(!toolbar) return;
var edit = $(edid);
if(!edit) return;
if(edit.readOnly) return;
+ if (typeof allowblock === 'undefined') {
+ allowblock = true;
+ }
+
//empty the toolbar area:
toolbar.innerHTML='';
var cnt = tb.length;
for(var i=0; i<cnt; i++){
+ if (!allowblock && tb[i].block === true) {
+ continue;
+ }
var actionFunc;
// create new button
var btn = createToolButton(tb[i]['icon'],
tb[i]['title'],
- tb[i]['key']);
+ tb[i]['key'],
+ tb[i]['id'],
+ tb[i]['class']);
// type is a tb function -> assign it as onclick
@@ -225,8 +235,10 @@ function pickerToggle(pickerid,btn){
picker.style.left = (x+3)+'px';
picker.style.top = (y+btn.offsetHeight+3)+'px';
picker.style.marginLeft = '0px';
+ picker.style.marginTop = '0px';
}else{
picker.style.marginLeft = '-10000px';
+ picker.style.marginTop = '-10000px';
}
}
@@ -239,6 +251,7 @@ function pickerClose(){
var pobjs = getElementsByClass('picker');
for(var i=0; i<pobjs.length; i++){
pobjs[i].style.marginLeft = '-10000px';
+ pobjs[i].style.marginTop = '-10000px';
}
}
diff --git a/lib/scripts/tw-sack.js b/lib/scripts/tw-sack.js
index cfcbe0ea9..b5a5c8861 100644
--- a/lib/scripts/tw-sack.js
+++ b/lib/scripts/tw-sack.js
@@ -10,6 +10,7 @@ function sack(file){
this.URLString = "";
this.encodeURIString = true;
this.execute = false;
+ this.asynchronous = true;
this.onLoading = function() { };
this.onLoaded = function() { };
@@ -86,9 +87,9 @@ function sack(file){
var self = this;
if (this.method == "GET") {
var totalurlstring = this.requestFile + "?" + this.URLString;
- this.xmlhttp.open(this.method, totalurlstring, true);
+ this.xmlhttp.open(this.method, totalurlstring, this.asynchronous);
} else {
- this.xmlhttp.open(this.method, this.requestFile, true);
+ this.xmlhttp.open(this.method, this.requestFile, this.asynchronous);
}
if (this.method == "POST"){
try {