ajout de la partie slam dans le dossier web
							
								
								
									
										195
									
								
								ap23/web/doku/lib/scripts/behaviour.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,195 @@ | ||||
| /** | ||||
|  * Hides elements with a slide animation | ||||
|  * | ||||
|  * @param {function} fn optional callback to run after hiding | ||||
|  * @param {bool} noaria supress aria-expanded state setting | ||||
|  * @author Adrian Lang <mail@adrianlang.de> | ||||
|  */ | ||||
| jQuery.fn.dw_hide = function(fn, noaria) { | ||||
|     if(!noaria) this.attr('aria-expanded', 'false'); | ||||
|     return this.slideUp('fast', fn); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Unhides elements with a slide animation | ||||
|  * | ||||
|  * @param {function} fn optional callback to run after hiding | ||||
|  * @param {bool} noaria supress aria-expanded state setting | ||||
|  * @author Adrian Lang <mail@adrianlang.de> | ||||
|  */ | ||||
| jQuery.fn.dw_show = function(fn, noaria) { | ||||
|     if(!noaria) this.attr('aria-expanded', 'true'); | ||||
|     return this.slideDown('fast', fn); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Toggles visibility of an element using a slide element | ||||
|  * | ||||
|  * @param {bool} state the current state of the element (optional) | ||||
|  * @param {function} fn callback after the state has been toggled | ||||
|  * @param {bool} noaria supress aria-expanded state setting | ||||
|  */ | ||||
| jQuery.fn.dw_toggle = function(state, fn, noaria) { | ||||
|     return this.each(function() { | ||||
|         var $this = jQuery(this); | ||||
|         if (typeof state === 'undefined') { | ||||
|             state = $this.is(':hidden'); | ||||
|         } | ||||
|         $this[state ? "dw_show" : "dw_hide" ](fn, noaria); | ||||
|     }); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Automatic behaviours | ||||
|  * | ||||
|  * This class wraps various JavaScript functionalities that are triggered | ||||
|  * automatically whenever a certain object is in the DOM or a certain CSS | ||||
|  * class was found | ||||
|  */ | ||||
| var dw_behaviour = { | ||||
|  | ||||
|     init: function(){ | ||||
|         dw_behaviour.focusMarker(); | ||||
|         dw_behaviour.scrollToMarker(); | ||||
|         dw_behaviour.removeHighlightOnClick(); | ||||
|         dw_behaviour.quickSelect(); | ||||
|         dw_behaviour.checkWindowsShares(); | ||||
|         dw_behaviour.subscription(); | ||||
|  | ||||
|         dw_behaviour.revisionBoxHandler(); | ||||
|         jQuery(document).on('click','#page__revisions input[type=checkbox]', | ||||
|             dw_behaviour.revisionBoxHandler | ||||
|         ); | ||||
|  | ||||
|         jQuery('.bounce').effect('bounce', {times:10}, 2000 ); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Looks for an element with the ID scroll__here at scrolls to it | ||||
|      */ | ||||
|     scrollToMarker: function(){ | ||||
|         var $obj = jQuery('#scroll__here'); | ||||
|         if($obj.length) { | ||||
|             if($obj.offset().top != 0) { | ||||
|                 jQuery('html, body').animate({ | ||||
|                     scrollTop: $obj.offset().top - 100 | ||||
|                 }, 500); | ||||
|             } else { | ||||
|                 // hidden object have no offset but can still be scrolled into view | ||||
|                 $obj[0].scrollIntoView(); | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Looks for an element with the ID focus__this at sets focus to it | ||||
|      */ | ||||
|     focusMarker: function(){ | ||||
|         jQuery('#focus__this').trigger('focus'); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Remove all search highlighting when clicking on a highlighted term | ||||
|      */ | ||||
|     removeHighlightOnClick: function(){ | ||||
|         jQuery('span.search_hit').on('click', | ||||
|             function(e){ | ||||
|                 jQuery(e.target).removeClass('search_hit', 1000); | ||||
|             } | ||||
|         ); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Autosubmit quick select forms | ||||
|      * | ||||
|      * When a <select> tag has the class "quickselect", this script will | ||||
|      * automatically submit its parent form when the select value changes. | ||||
|      * It also hides the submit button of the form. | ||||
|      * | ||||
|      * @author Andreas Gohr <andi@splitbrain.org> | ||||
|      */ | ||||
|     quickSelect: function(){ | ||||
|         jQuery('select.quickselect') | ||||
|             .on('change', function(e){ e.target.form.submit(); }) | ||||
|             .closest('form').find(':button').not('.show').hide(); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Display error for Windows Shares on browsers other than IE | ||||
|      * | ||||
|      * @author Michael Klier <chi@chimeric.de> | ||||
|      */ | ||||
|     checkWindowsShares: function() { | ||||
|         if(!LANG.nosmblinks || navigator.userAgent.match(/(Trident|MSIE|Edge)/)) { | ||||
|             // No warning requested or none necessary | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         jQuery('a.windows').on('click', function(){ | ||||
|             alert(LANG.nosmblinks.replace(/\\n/,"\n")); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Hide list subscription style if target is a page | ||||
|      * | ||||
|      * @author Adrian Lang <lang@cosmocode.de> | ||||
|      * @author Pierre Spring <pierre.spring@caillou.ch> | ||||
|      */ | ||||
|     subscription: function(){ | ||||
|         var $form, $list, $digest; | ||||
|  | ||||
|         $form = jQuery('#subscribe__form'); | ||||
|         if (0 === $form.length) return; | ||||
|  | ||||
|         $list = $form.find("input[name='sub_style'][value='list']"); | ||||
|         $digest = $form.find("input[name='sub_style'][value='digest']"); | ||||
|  | ||||
|         $form.find("input[name='sub_target']") | ||||
|             .on('click', | ||||
|                 function () { | ||||
|                     var $this = jQuery(this), show_list; | ||||
|                     if (!$this.prop('checked')) { | ||||
|                         return; | ||||
|                     } | ||||
|  | ||||
|                     show_list = $this.val().match(/:$/); | ||||
|                     $list.parent().dw_toggle(show_list); | ||||
|                     if (!show_list && $list.prop('checked')) { | ||||
|                         $digest.prop('checked', 'checked'); | ||||
|                     } | ||||
|                 } | ||||
|             ) | ||||
|             .filter(':checked') | ||||
|             .trigger('click'); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * disable multiple revisions checkboxes if two are checked | ||||
|      * | ||||
|      * @author Andreas Gohr <andi@splitbrain.org> | ||||
|      * @author Anika Henke <anika@selfthinker.org> | ||||
|      */ | ||||
|     revisionBoxHandler: function() { | ||||
|         var $revisions = jQuery('#page__revisions'); | ||||
|         var $all       = jQuery('input[type=checkbox]', $revisions); | ||||
|         var $checked   = $all.filter(':checked'); | ||||
|         var $button    = jQuery('button', $revisions); | ||||
|  | ||||
|         if($checked.length < 2) { | ||||
|             $all.prop('disabled', false); | ||||
|             $button.prop('disabled', true); | ||||
|         } else { | ||||
|             $all.prop('disabled', true); | ||||
|             $button.prop('disabled', false); | ||||
|             $checked.each(function(i) { | ||||
|                 jQuery(this).prop('disabled', false); | ||||
|                 if(i>1) { | ||||
|                     jQuery(this).prop('checked', false); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| jQuery(dw_behaviour.init); | ||||
							
								
								
									
										42
									
								
								ap23/web/doku/lib/scripts/compatibility.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,42 @@ | ||||
| /** | ||||
|  * Mark a JavaScript function as deprecated | ||||
|  * | ||||
|  * This will print a warning to the JavaScript console (if available) in | ||||
|  * Firebug and Chrome and a stack trace (if available) to easily locate the | ||||
|  * problematic function call. | ||||
|  * | ||||
|  * @param msg optional message to print | ||||
|  */ | ||||
| function DEPRECATED(msg){ | ||||
|     if(!window.console) return; | ||||
|     if(!msg) msg = ''; | ||||
|  | ||||
|     var func; | ||||
|     if(arguments.callee) func = arguments.callee.caller.name; | ||||
|     if(func) func = ' '+func+'()'; | ||||
|     var line = 'DEPRECATED function call'+func+'. '+msg; | ||||
|  | ||||
|     if(console.warn){ | ||||
|         console.warn(line); | ||||
|     }else{ | ||||
|         console.log(line); | ||||
|     } | ||||
|  | ||||
|     if(console.trace) console.trace(); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Construct a wrapper function for deprecated function names | ||||
|  * | ||||
|  * This function returns a wrapper function which just calls DEPRECATED | ||||
|  * and the new function. | ||||
|  * | ||||
|  * @param func    The new function | ||||
|  * @param context Optional; The context (`this`) of the call | ||||
|  */ | ||||
| function DEPRECATED_WRAP(func, context) { | ||||
|     return function () { | ||||
|         DEPRECATED(); | ||||
|         return func.apply(context || this, arguments); | ||||
|     }; | ||||
| } | ||||
							
								
								
									
										71
									
								
								ap23/web/doku/lib/scripts/cookie.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,71 @@ | ||||
| /** | ||||
| * Handles the cookie used by several JavaScript functions | ||||
| * | ||||
| * Only a single cookie is written and read. You may only save | ||||
| * simple name-value pairs - no complex types! | ||||
| * | ||||
| * You should only use the getValue and setValue methods | ||||
| * | ||||
| * @author Andreas Gohr <andi@splitbrain.org> | ||||
| * @author Michal Rezler <m.rezler@centrum.cz> | ||||
| */ | ||||
| var DokuCookie = { | ||||
|     data: {}, | ||||
|     name: 'DOKU_PREFS', | ||||
|  | ||||
|     /** | ||||
|      * Save a value to the cookie | ||||
|      * | ||||
|      * @author Andreas Gohr <andi@splitbrain.org> | ||||
|      */ | ||||
|     setValue: function(key,val){ | ||||
|         var text = [], | ||||
|             _this = this; | ||||
|         this.init(); | ||||
|         if (val === false){ | ||||
|             delete this.data[key]; | ||||
|         }else{ | ||||
|             val = val + ""; | ||||
|             this.data[key] = val; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         //save the whole data array | ||||
|         jQuery.each(_this.data, function (key, val) { | ||||
|             if (_this.data.hasOwnProperty(key)) { | ||||
|                 text.push(encodeURIComponent(key)+'#'+encodeURIComponent(val)); | ||||
|             } | ||||
|         }); | ||||
|         jQuery.cookie(this.name, text.join('#'), {expires: 365, path: DOKU_COOKIE_PARAM.path, secure: DOKU_COOKIE_PARAM.secure}); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Get a Value from the Cookie | ||||
|      * | ||||
|      * @author Andreas Gohr <andi@splitbrain.org> | ||||
|      * @param def default value if key does not exist; if not set, returns undefined by default | ||||
|      */ | ||||
|     getValue: function(key, def){ | ||||
|         this.init(); | ||||
|         return this.data.hasOwnProperty(key) ? this.data[key] : def; | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Loads the current set cookie | ||||
|      * | ||||
|      * @author Andreas Gohr <andi@splitbrain.org> | ||||
|      */ | ||||
|     init: function(){ | ||||
|         var text, parts, i; | ||||
|         if(!jQuery.isEmptyObject(this.data)) { | ||||
|             return; | ||||
|         } | ||||
|         text = jQuery.cookie(this.name); | ||||
|         if(text){ | ||||
|             parts = text.split('#'); | ||||
|             for(i = 0; i < parts.length; i += 2){ | ||||
|                 this.data[decodeURIComponent(parts[i])] = decodeURIComponent(parts[i+1]); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										70
									
								
								ap23/web/doku/lib/scripts/delay.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,70 @@ | ||||
| /** | ||||
|  * 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 () { | ||||
|         DEPRECATED('don\'t use the Delay object, use window.timeout with a callback instead'); | ||||
|         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); | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										307
									
								
								ap23/web/doku/lib/scripts/edit.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,307 @@ | ||||
| /** | ||||
|  * Functions for text editing (toolbar stuff) | ||||
|  * | ||||
|  * @todo most of the stuff in here should be revamped and then moved to toolbar.js | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Creates a toolbar button through the DOM | ||||
|  * Called for each entry of toolbar definition array (built by inc/toolbar.php and extended via js) | ||||
|  * | ||||
|  * Style the buttons through the toolbutton class | ||||
|  * | ||||
|  * @param {string} icon      image filename, relative to folder lib/images/toolbar/ | ||||
|  * @param {string} label     title of button, show on mouseover | ||||
|  * @param {string} key       hint in title of button for access key | ||||
|  * @param {string} id        id of button, and '<id>_ico' of icon | ||||
|  * @param {string} classname for styling buttons | ||||
|  * | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  * @author Michal Rezler <m.rezler@centrum.cz> | ||||
|  */ | ||||
| function createToolButton(icon,label,key,id,classname){ | ||||
|     var $btn = jQuery(document.createElement('button')), | ||||
|         $ico = jQuery(document.createElement('img')); | ||||
|  | ||||
|     // prepare the basic button stuff | ||||
|     $btn.addClass('toolbutton'); | ||||
|     if(classname){ | ||||
|         $btn.addClass(classname); | ||||
|     } | ||||
|  | ||||
|     $btn.attr('title', label).attr('aria-controls', 'wiki__text'); | ||||
|     if(key){ | ||||
|         $btn.attr('title', label + ' ['+key.toUpperCase()+']') | ||||
|             .attr('accessKey', key); | ||||
|     } | ||||
|  | ||||
|     // set IDs if given | ||||
|     if(id){ | ||||
|         $btn.attr('id', id); | ||||
|         $ico.attr('id', id+'_ico'); | ||||
|     } | ||||
|  | ||||
|     // create the icon and add it to the button | ||||
|     if(icon.substr(0,1) !== '/'){ | ||||
|         icon = DOKU_BASE + 'lib/images/toolbar/' + icon; | ||||
|     } | ||||
|     $ico.attr('src', icon); | ||||
|     $ico.attr('alt', ''); | ||||
|     $ico.attr('width', 16); | ||||
|     $ico.attr('height', 16); | ||||
|     $btn.append($ico); | ||||
|  | ||||
|     // we have to return a DOM object (for compatibility reasons) | ||||
|     return $btn[0]; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Creates a picker window for inserting text | ||||
|  * | ||||
|  * The given list can be an associative array with text,icon pairs | ||||
|  * or a simple list of text. Style the picker window through the picker | ||||
|  * class or the picker buttons with the pickerbutton class. Picker | ||||
|  * windows are appended to the body and created invisible. | ||||
|  * | ||||
|  * @param  {string} id    the ID to assign to the picker | ||||
|  * @param  {Array}  props the properties for the picker | ||||
|  * @param  {string} edid  the ID of the textarea | ||||
|  * @return DOMobject    the created picker | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  */ | ||||
| function createPicker(id,props,edid){ | ||||
|     // create the wrapping div | ||||
|     var $picker = jQuery(document.createElement('div')); | ||||
|  | ||||
|     $picker.addClass('picker a11y'); | ||||
|     if(props['class']){ | ||||
|         $picker.addClass(props['class']); | ||||
|     } | ||||
|  | ||||
|     $picker.attr('id', id).css('position', 'absolute'); | ||||
|  | ||||
|     function $makebutton(title) { | ||||
|         var $btn = jQuery(document.createElement('button')) | ||||
|             .addClass('pickerbutton').attr('title', title) | ||||
|             .attr('aria-controls', edid) | ||||
|             .on('click', bind(pickerInsert, title, edid)) | ||||
|             .appendTo($picker); | ||||
|         return $btn; | ||||
|     } | ||||
|  | ||||
|     jQuery.each(props.list, function (key, item) { | ||||
|         if (!props.list.hasOwnProperty(key)) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if(isNaN(key)){ | ||||
|             // associative array -> treat as text => image pairs | ||||
|             if (item.substr(0,1) !== '/') { | ||||
|                 item = DOKU_BASE+'lib/images/'+props.icobase+'/'+item; | ||||
|             } | ||||
|             jQuery(document.createElement('img')) | ||||
|                 .attr('src', item) | ||||
|                 .attr('alt', '') | ||||
|                 .appendTo($makebutton(key)); | ||||
|         }else if (typeof item == 'string'){ | ||||
|             // a list of text -> treat as text picker | ||||
|             $makebutton(item).text(item); | ||||
|         }else{ | ||||
|             // a list of lists -> treat it as subtoolbar | ||||
|             initToolbar($picker,edid,props.list); | ||||
|             return false; // all buttons handled already | ||||
|         } | ||||
|  | ||||
|     }); | ||||
|     jQuery('body').append($picker); | ||||
|  | ||||
|     // we have to return a DOM object (for compatibility reasons) | ||||
|     return $picker[0]; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Called by picker buttons to insert Text and close the picker again | ||||
|  * | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  */ | ||||
| function pickerInsert(text,edid){ | ||||
|     insertAtCarret(edid,text); | ||||
|     pickerClose(); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Add button action for signature button | ||||
|  * | ||||
|  * @param  {jQuery} $btn   Button element to add the action to | ||||
|  * @param  {Array}  props  Associative array of button properties | ||||
|  * @param  {string} edid   ID of the editor textarea | ||||
|  * @return {string} picker id for aria-controls attribute | ||||
|  * @author Gabriel Birke <birke@d-scribe.de> | ||||
|  */ | ||||
| function addBtnActionSignature($btn, props, edid) { | ||||
|     if(typeof SIG != 'undefined' && SIG != ''){ | ||||
|         $btn.on('click', function (e) { | ||||
|             insertAtCarret(edid,SIG); | ||||
|             e.preventDefault(); | ||||
|         }); | ||||
|         return edid; | ||||
|     } | ||||
|     return ''; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Determine the current section level while editing | ||||
|  * | ||||
|  * @param {string} textboxId   ID of the text field | ||||
|  * | ||||
|  * @author Andreas Gohr <gohr@cosmocode.de> | ||||
|  */ | ||||
| function currentHeadlineLevel(textboxId){ | ||||
|     var field = jQuery('#' + textboxId)[0], | ||||
|         s = false, | ||||
|         opts = [field.value.substr(0,DWgetSelection(field).start)]; | ||||
|     if (field.form && field.form.prefix) { | ||||
|         // we need to look in prefix context | ||||
|         opts.push(field.form.prefix.value); | ||||
|     } | ||||
|  | ||||
|     jQuery.each(opts, function (_, opt) { | ||||
|         // Check whether there is a headline in the given string | ||||
|         var str = "\n" + opt, | ||||
|             lasthl = str.lastIndexOf("\n=="); | ||||
|         if (lasthl !== -1) { | ||||
|             s = str.substr(lasthl+1,6); | ||||
|             return false; | ||||
|         } | ||||
|     }); | ||||
|     if (s === false) { | ||||
|         return 0; | ||||
|     } | ||||
|     return 7 - s.match(/^={2,6}/)[0].length; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * global var used for not saved yet warning | ||||
|  */ | ||||
| window.textChanged = false; | ||||
|  | ||||
| /** | ||||
|  * global var which stores original editor content | ||||
|  */ | ||||
| window.doku_edit_text_content = ''; | ||||
| /** | ||||
|  * Delete the draft before leaving the page | ||||
|  */ | ||||
| function deleteDraft() { | ||||
|     if (is_opera || window.keepDraft) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     var $dwform = jQuery('#dw__editform'); | ||||
|  | ||||
|     if($dwform.length === 0) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     // remove a possibly saved draft using ajax | ||||
|     jQuery.post(DOKU_BASE + 'lib/exe/ajax.php', | ||||
|         { | ||||
|             call: 'draftdel', | ||||
|             id: $dwform.find('input[name=id]').val() | ||||
|         } | ||||
|     ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Activate "not saved" dialog, add draft deletion to page unload, | ||||
|  * add handlers to monitor changes | ||||
|  * Note: textChanged could be set by e.g. html_edit() as well | ||||
|  * | ||||
|  * Sets focus to the editbox as well | ||||
|  */ | ||||
| jQuery(function () { | ||||
|     var $editform = jQuery('#dw__editform'); | ||||
|     if ($editform.length == 0) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     var $edit_text = jQuery('#wiki__text'); | ||||
|     if ($edit_text.length > 0) { | ||||
|         if($edit_text.attr('readOnly')) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // set focus and place cursor at the start | ||||
|         var sel = DWgetSelection($edit_text[0]); | ||||
|         sel.start = 0; | ||||
|         sel.end   = 0; | ||||
|         DWsetSelection(sel); | ||||
|         $edit_text.trigger('focus'); | ||||
|  | ||||
|         doku_edit_text_content = $edit_text.val(); | ||||
|     } | ||||
|  | ||||
|     var changeHandler = function() { | ||||
|         doku_hasTextBeenModified(); | ||||
|  | ||||
|         doku_summaryCheck(); | ||||
|     }; | ||||
|  | ||||
|     $editform.change(changeHandler); | ||||
|     $editform.keydown(changeHandler); | ||||
|  | ||||
|     window.onbeforeunload = function(){ | ||||
|         if(window.textChanged) { | ||||
|             return LANG.notsavedyet; | ||||
|         } | ||||
|     }; | ||||
|     window.onunload = deleteDraft; | ||||
|  | ||||
|     // reset change memory var on submit | ||||
|     jQuery('#edbtn__save').on('click', | ||||
|         function() { | ||||
|             window.onbeforeunload = ''; | ||||
|             textChanged = false; | ||||
|         } | ||||
|     ); | ||||
|     jQuery('#edbtn__preview').on('click', | ||||
|         function() { | ||||
|             window.onbeforeunload = ''; | ||||
|             textChanged = false; | ||||
|             window.keepDraft = true; // needed to keep draft on page unload | ||||
|         } | ||||
|     ); | ||||
|  | ||||
|     var $summary = jQuery('#edit__summary'); | ||||
|     $summary.on('change keyup', doku_summaryCheck); | ||||
|  | ||||
|     if (textChanged) doku_summaryCheck(); | ||||
| }); | ||||
|  | ||||
| /** | ||||
|  * Updates textChanged variable if content of the editor has been modified | ||||
|  */ | ||||
| function doku_hasTextBeenModified() { | ||||
|     if (!textChanged) { | ||||
|         var $edit_text = jQuery('#wiki__text'); | ||||
|  | ||||
|         if ($edit_text.length > 0) { | ||||
|             textChanged = doku_edit_text_content != $edit_text.val(); | ||||
|         } else { | ||||
|             textChanged = true; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks if a summary was entered - if not the style is changed | ||||
|  * | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  */ | ||||
| function doku_summaryCheck(){ | ||||
|     var $sum = jQuery('#edit__summary'), | ||||
|         missing = $sum.val() === ''; | ||||
|     $sum.toggleClass('missing', missing).toggleClass('edit', !missing); | ||||
| } | ||||
							
								
								
									
										205
									
								
								ap23/web/doku/lib/scripts/editor.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,205 @@ | ||||
| /** | ||||
|  * The DokuWiki editor features | ||||
|  * | ||||
|  * These are the advanced features of the editor. It does NOT contain any | ||||
|  * code for the toolbar buttons and it functions. See toolbar.js for that. | ||||
|  */ | ||||
|  | ||||
| var dw_editor = { | ||||
|  | ||||
|     /** | ||||
|      * initialize the default editor functionality | ||||
|      * | ||||
|      * All other functions can also be called separately for non-default | ||||
|      * textareas | ||||
|      */ | ||||
|     init: function(){ | ||||
|         var $editor = jQuery('#wiki__text'); | ||||
|         if($editor.length === 0) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         dw_editor.initSizeCtl('#size__ctl',$editor); | ||||
|  | ||||
|         if($editor.attr('readOnly')) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $editor.keydown(dw_editor.keyHandler); | ||||
|  | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Add the edit window size and wrap controls | ||||
|      * | ||||
|      * Initial values are read from cookie if it exists | ||||
|      * | ||||
|      * @param selector ctlarea the div to place the controls | ||||
|      * @param selector editor  the textarea to control | ||||
|      */ | ||||
|     initSizeCtl: function(ctlarea,editor){ | ||||
|         var $ctl      = jQuery(ctlarea), | ||||
|             $textarea = jQuery(editor); | ||||
|  | ||||
|         if($ctl.length === 0 || $textarea.length === 0) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $textarea.css('height', DokuCookie.getValue('sizeCtl') || '300px'); | ||||
|  | ||||
|         var wrp = DokuCookie.getValue('wrapCtl'); | ||||
|         if(wrp){ | ||||
|             dw_editor.setWrap($textarea[0], wrp); | ||||
|         } // else use default value | ||||
|  | ||||
|         jQuery.each([ | ||||
|             ['larger', function(){dw_editor.sizeCtl(editor,100);}], | ||||
|             ['smaller', function(){dw_editor.sizeCtl(editor,-100);}], | ||||
|             ['wrap', function(){dw_editor.toggleWrap(editor);}] | ||||
|         ], function (_, img) { | ||||
|             jQuery(document.createElement('img')) | ||||
|                 .attr('src', DOKU_BASE+'lib/images/' + img[0] + '.gif') | ||||
|                 .attr('alt', '') | ||||
|                 .on('click', img[1]) | ||||
|                 .appendTo($ctl); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * This sets the vertical size of the editbox and adjusts the cookie | ||||
|      * | ||||
|      * @param selector editor  the textarea to control | ||||
|      * @param int val          the relative value to resize in pixel | ||||
|      */ | ||||
|     sizeCtl: function(editor,val){ | ||||
|         var $textarea = jQuery(editor), | ||||
|             height = parseInt($textarea.css('height')) + val; | ||||
|         $textarea.css('height', height+'px'); | ||||
|         DokuCookie.setValue('sizeCtl',$textarea.css('height')); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Toggle the wrapping mode of the editor textarea and adjusts the | ||||
|      * cookie | ||||
|      * | ||||
|      * @param selector editor  the textarea to control | ||||
|      */ | ||||
|     toggleWrap: function(editor){ | ||||
|         var $textarea = jQuery(editor), | ||||
|             wrap = $textarea.attr('wrap'); | ||||
|         dw_editor.setWrap($textarea[0], | ||||
|                           (wrap && wrap.toLowerCase() == 'off') ? 'soft' : 'off'); | ||||
|         DokuCookie.setValue('wrapCtl',$textarea.attr('wrap')); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Set the wrapping mode of a textarea | ||||
|      * | ||||
|      * @author Fluffy Convict <fluffyconvict@hotmail.com> | ||||
|      * @author <shutdown@flashmail.com> | ||||
|      * @link   http://news.hping.org/comp.lang.javascript.archive/12265.html | ||||
|      * @link   https://bugzilla.mozilla.org/show_bug.cgi?id=41464 | ||||
|      * @param  DomObject textarea | ||||
|      * @param  string wrapAttrValue | ||||
|      */ | ||||
|     setWrap: function(textarea, wrapAttrValue){ | ||||
|         textarea.setAttribute('wrap', wrapAttrValue); | ||||
|  | ||||
|         // Fix display for mozilla | ||||
|         var parNod = textarea.parentNode; | ||||
|         var nxtSib = textarea.nextSibling; | ||||
|         parNod.removeChild(textarea); | ||||
|         parNod.insertBefore(textarea, nxtSib); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Make intended formattings easier to handle | ||||
|      * | ||||
|      * Listens to all key inputs and handle indentions | ||||
|      * of lists and code blocks | ||||
|      * | ||||
|      * Currently handles space, backspace, enter and | ||||
|      * ctrl-enter presses | ||||
|      * | ||||
|      * @author Andreas Gohr <andi@splitbrain.org> | ||||
|      * @fixme handle tabs | ||||
|      * @param event e - the key press event object | ||||
|      */ | ||||
|     keyHandler: function(e){ | ||||
|         if(jQuery.inArray(e.keyCode,[8, 10, 13, 32]) === -1) { | ||||
|             return; | ||||
|         } | ||||
|         var selection = DWgetSelection(this); | ||||
|         if(selection.getLength() > 0) { | ||||
|             return; //there was text selected, keep standard behavior | ||||
|         } | ||||
|         var search    = "\n"+this.value.substr(0,selection.start); | ||||
|         var linestart = Math.max(search.lastIndexOf("\n"), | ||||
|                                  search.lastIndexOf("\r")); //IE workaround | ||||
|         search = search.substr(linestart); | ||||
|  | ||||
|         if((e.keyCode == 13 || e.keyCode == 10) && e.ctrlKey) { // Ctrl-Enter (With Chrome workaround) | ||||
|             // Submit current edit | ||||
|             jQuery('#edbtn__save').trigger('click'); | ||||
|             e.preventDefault(); // prevent enter key | ||||
|             return false; | ||||
|         }else if(e.keyCode == 13){ // Enter | ||||
|             // keep current indention for lists and code | ||||
|             var match = search.match(/(\n  +([\*-] ?)?)/); | ||||
|             if(match){ | ||||
|                 var scroll = this.scrollHeight; | ||||
|                 var match2 = search.match(/^\n  +[\*-]\s*$/); | ||||
|                 // Cancel list if the last item is empty (i. e. two times enter) | ||||
|                 if (match2 && this.value.substr(selection.start).match(/^($|\r?\n)/)) { | ||||
|                     this.value = this.value.substr(0, linestart) + "\n" + | ||||
|                                  this.value.substr(selection.start); | ||||
|                     selection.start = linestart + 1; | ||||
|                     selection.end = linestart + 1; | ||||
|                     DWsetSelection(selection); | ||||
|                 } else { | ||||
|                     insertAtCarret(this.id,match[1]); | ||||
|                 } | ||||
|                 this.scrollTop += (this.scrollHeight - scroll); | ||||
|                 e.preventDefault(); // prevent enter key | ||||
|                 return false; | ||||
|             } | ||||
|         }else if(e.keyCode == 8){ // Backspace | ||||
|             // unindent lists | ||||
|             var match = search.match(/(\n  +)([*-] ?)$/); | ||||
|             if(match){ | ||||
|                 var spaces = match[1].length-1; | ||||
|  | ||||
|                 if(spaces > 3){ // unindent one level | ||||
|                     this.value = this.value.substr(0,linestart)+ | ||||
|                                  this.value.substr(linestart+2); | ||||
|                     selection.start = selection.start - 2; | ||||
|                     selection.end   = selection.start; | ||||
|                 }else{ // delete list point | ||||
|                     this.value = this.value.substr(0,linestart)+ | ||||
|                                  this.value.substr(selection.start); | ||||
|                     selection.start = linestart; | ||||
|                     selection.end   = linestart; | ||||
|                 } | ||||
|                 DWsetSelection(selection); | ||||
|                 e.preventDefault(); // prevent backspace | ||||
|                 return false; | ||||
|             } | ||||
|         }else if(e.keyCode == 32){ // Space | ||||
|             // intend list item | ||||
|             var match = search.match(/(\n  +)([*-] )$/); | ||||
|             if(match){ | ||||
|                 this.value = this.value.substr(0,linestart)+'  '+ | ||||
|                              this.value.substr(linestart); | ||||
|                 selection.start = selection.start + 2; | ||||
|                 selection.end   = selection.start; | ||||
|                 DWsetSelection(selection); | ||||
|                 e.preventDefault(); // prevent space | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
| }; | ||||
|  | ||||
| jQuery(dw_editor.init); | ||||
							
								
								
									
										1249
									
								
								ap23/web/doku/lib/scripts/fileuploader.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										345
									
								
								ap23/web/doku/lib/scripts/fileuploaderextended.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,345 @@ | ||||
| qq.extend(qq.FileUploader.prototype, { | ||||
|     _createUploadHandler: function(){ | ||||
|         var self = this, | ||||
|             handlerClass; | ||||
|  | ||||
|         if(qq.UploadHandlerXhr.isSupported()){ | ||||
|             handlerClass = 'UploadHandlerXhr'; | ||||
|             //handlerClass = 'UploadHandlerForm'; | ||||
|         } else { | ||||
|             handlerClass = 'UploadHandlerForm'; | ||||
|         } | ||||
|  | ||||
|         var handler = new qq[handlerClass]({ | ||||
|             debug: this._options.debug, | ||||
|             action: this._options.action, | ||||
|             maxConnections: this._options.maxConnections, | ||||
|             onProgress: function(id, fileName, loaded, total){ | ||||
|                 self._onProgress(id, fileName, loaded, total); | ||||
|                 self._options.onProgress(id, fileName, loaded, total); | ||||
|             }, | ||||
|             onComplete: function(id, fileName, result){ | ||||
|                 self._onComplete(id, fileName, result); | ||||
|                 self._options.onComplete(id, fileName, result); | ||||
|             }, | ||||
|             onCancel: function(id, fileName){ | ||||
|                 self._onCancel(id, fileName); | ||||
|                 self._options.onCancel(id, fileName); | ||||
|             }, | ||||
|             onUpload: function(){ | ||||
|                 self._onUpload(); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         return handler; | ||||
|     }, | ||||
|  | ||||
|     _onUpload: function(){ | ||||
|         this._handler.uploadAll(this._options.params); | ||||
|     }, | ||||
|  | ||||
|     _uploadFile: function(fileContainer){ | ||||
|         var id = this._handler.add(fileContainer); | ||||
|         var fileName = this._handler.getName(id); | ||||
|  | ||||
|         if (this._options.onSubmit(id, fileName) !== false){ | ||||
|             this._onSubmit(id, fileName); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _addToList: function(id, fileName){ | ||||
|         var item = qq.toElement(this._options.fileTemplate); | ||||
|         item.qqFileId = id; | ||||
|  | ||||
|         var fileElement = this._find(item, 'file'); | ||||
|         qq.setText(fileElement, fileName); | ||||
|         this._find(item, 'size').style.display = 'none'; | ||||
|  | ||||
|         // name suggestion (simplified cleanID) | ||||
|         var nameElement = this._find(item, 'nameInput'); | ||||
|         fileName = fileName.toLowerCase(); | ||||
|         fileName = fileName.replace(/([ !"#$%&\'()+,\/;<=>?@[\]^`{|}~:]+)/g, '_'); | ||||
|         fileName = fileName.replace(/^_+/,''); | ||||
|         nameElement.value = fileName; | ||||
|         nameElement.id = 'mediamanager__upload_item'+id; | ||||
|  | ||||
|         this._listElement.appendChild(item); | ||||
|     } | ||||
|  | ||||
| }); | ||||
|  | ||||
| qq.FileUploaderExtended = function(o){ | ||||
|     // call parent constructor | ||||
|     qq.FileUploaderBasic.apply(this, arguments); | ||||
|  | ||||
|     qq.extend(this._options, { | ||||
|         element: null, | ||||
|         // if set, will be used instead of qq-upload-list in template | ||||
|         listElement: null, | ||||
|  | ||||
|         template: '<div class="qq-uploader">' + | ||||
|             '<div class="qq-upload-drop-area"><span>' + LANG.media_drop + '</span></div>' + | ||||
|             '<div class="qq-upload-button">' + LANG.media_select + '</div>' + | ||||
|             '<ul class="qq-upload-list"></ul>' + | ||||
|             '<div class="qq-action-container">' + | ||||
|             '  <button class="qq-upload-action" type="submit" id="mediamanager__upload_button">' + LANG.media_upload_btn + '</button>' + | ||||
|             '  <label class="qq-overwrite-check"><input type="checkbox" value="1" name="ow" class="dw__ow"> <span>' + LANG.media_overwrt + '</span></label>' + | ||||
|             '</div>' + | ||||
|             '</div>', | ||||
|  | ||||
|         // template for one item in file list | ||||
|         fileTemplate: '<li>' + | ||||
|               '<span class="qq-upload-file hidden"></span>' + | ||||
|             '  <input class="qq-upload-name-input edit" type="text" value="" />' + | ||||
|             '  <span class="qq-upload-spinner hidden"></span>' + | ||||
|             '  <span class="qq-upload-size"></span>' + | ||||
|             '  <a class="qq-upload-cancel" href="#">' + LANG.media_cancel + '</a>' + | ||||
|             '  <span class="qq-upload-failed-text error">Failed</span>' + | ||||
|             '</li>', | ||||
|  | ||||
|         classes: { | ||||
|             // used to get elements from templates | ||||
|             button: 'qq-upload-button', | ||||
|             drop: 'qq-upload-drop-area', | ||||
|             dropActive: 'qq-upload-drop-area-active', | ||||
|             list: 'qq-upload-list', | ||||
|             nameInput: 'qq-upload-name-input', | ||||
|             overwriteInput: 'qq-overwrite-check', | ||||
|             uploadButton: 'qq-upload-action', | ||||
|             file: 'qq-upload-file', | ||||
|  | ||||
|             spinner: 'qq-upload-spinner', | ||||
|             size: 'qq-upload-size', | ||||
|             cancel: 'qq-upload-cancel', | ||||
|  | ||||
|             // added to list item when upload completes | ||||
|             // used in css to hide progress spinner | ||||
|             success: 'qq-upload-success', | ||||
|             fail: 'qq-upload-fail', | ||||
|             failedText: 'qq-upload-failed-text' | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     qq.extend(this._options, o); | ||||
|  | ||||
|     this._element = this._options.element; | ||||
|     this._element.innerHTML = this._options.template; | ||||
|     this._listElement = this._options.listElement || this._find(this._element, 'list'); | ||||
|  | ||||
|     this._classes = this._options.classes; | ||||
|  | ||||
|     this._button = this._createUploadButton(this._find(this._element, 'button')); | ||||
|  | ||||
|     this._bindCancelEvent(); | ||||
|     this._bindUploadEvent(); | ||||
|     this._setupDragDrop(); | ||||
| }; | ||||
|  | ||||
| qq.extend(qq.FileUploaderExtended.prototype, qq.FileUploader.prototype); | ||||
|  | ||||
| qq.extend(qq.FileUploaderExtended.prototype, { | ||||
|     _bindUploadEvent: function(){ | ||||
|         var self = this, | ||||
|             list = this._listElement; | ||||
|  | ||||
|         qq.attach(document.getElementById('mediamanager__upload_button'), 'click', function(e){ | ||||
|             e = e || window.event; | ||||
|             var target = e.target || e.srcElement; | ||||
|             qq.preventDefault(e); | ||||
|             self._handler._options.onUpload(); | ||||
|  | ||||
|             jQuery(".qq-upload-name-input").each(function (i) { | ||||
|                 jQuery(this).prop('disabled', true); | ||||
|             }); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     _onComplete: function(id, fileName, result){ | ||||
|         this._filesInProgress--; | ||||
|  | ||||
|         // mark completed | ||||
|         var item = this._getItemByFileId(id); | ||||
|         qq.remove(this._find(item, 'cancel')); | ||||
|         qq.remove(this._find(item, 'spinner')); | ||||
|  | ||||
|         var nameInput = this._find(item, 'nameInput'); | ||||
|         var fileElement = this._find(item, 'file'); | ||||
|         qq.setText(fileElement, nameInput.value); | ||||
|         qq.removeClass(fileElement, 'hidden'); | ||||
|         qq.remove(nameInput); | ||||
|         jQuery('.qq-upload-button, #mediamanager__upload_button').remove(); | ||||
|         jQuery('.dw__ow').parent().hide(); | ||||
|         jQuery('.qq-upload-drop-area').remove(); | ||||
|  | ||||
|         if (result.success){ | ||||
|             qq.addClass(item, this._classes.success); | ||||
|             $link = '<a href="' + result.link + '" id="h_:' + result.id + '" class="select">' + nameInput.value + '</a>'; | ||||
|             jQuery(fileElement).html($link); | ||||
|  | ||||
|         } else { | ||||
|             qq.addClass(item, this._classes.fail); | ||||
|             var fail = this._find(item, 'failedText'); | ||||
|             if (result.error) qq.setText(fail, result.error); | ||||
|         } | ||||
|  | ||||
|         if (document.getElementById('media__content') && !document.getElementById('mediamanager__done_form')) { | ||||
|             var action = document.location.href; | ||||
|             var i = action.indexOf('?'); | ||||
|             if (i) action = action.substr(0, i); | ||||
|             var button = '<form method="post" action="' + action + '" id="mediamanager__done_form"><div>'; | ||||
|             button += '<input type="hidden" value="' + result.ns + '" name="ns">'; | ||||
|             button += '<input type="hidden" value="1" name="recent">'; | ||||
|             button += '<button type="submit">' + LANG.media_done_btn + '</button></div></form>'; | ||||
|             jQuery('#mediamanager__uploader').append(button); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| }); | ||||
|  | ||||
| qq.extend(qq.UploadHandlerForm.prototype, { | ||||
|     uploadAll: function(params){ | ||||
|         this._uploadAll(params); | ||||
|     }, | ||||
|  | ||||
|     getName: function(id){ | ||||
|         var file = this._inputs[id]; | ||||
|         var name = document.getElementById('mediamanager__upload_item'+id); | ||||
|         if (name != null) { | ||||
|             return name.value; | ||||
|         } else { | ||||
|             if (file != null) { | ||||
|                 // get input value and remove path to normalize | ||||
|                 return file.value.replace(/.*(\/|\\)/, ""); | ||||
|             } else { | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     _uploadAll: function(params){ | ||||
|          jQuery(".qq-upload-spinner").each(function (i) { | ||||
|             jQuery(this).removeClass('hidden'); | ||||
|         }); | ||||
|         for (key in this._inputs) { | ||||
|             this.upload(key, params); | ||||
|         } | ||||
|  | ||||
|     }, | ||||
|  | ||||
|     _upload: function(id, params){ | ||||
|         var input = this._inputs[id]; | ||||
|  | ||||
|         if (!input){ | ||||
|             throw new Error('file with passed id was not added, or already uploaded or cancelled'); | ||||
|         } | ||||
|  | ||||
|         var fileName = this.getName(id); | ||||
|  | ||||
|         var iframe = this._createIframe(id); | ||||
|         var form = this._createForm(iframe, params); | ||||
|         form.appendChild(input); | ||||
|  | ||||
|         var nameInput = qq.toElement('<input name="mediaid" value="' + fileName + '" type="text">'); | ||||
|         form.appendChild(nameInput); | ||||
|  | ||||
|         var checked = jQuery('.dw__ow').is(':checked'); | ||||
|         var owCheckbox = jQuery('.dw__ow').clone(); | ||||
|         owCheckbox.attr('checked', checked); | ||||
|         jQuery(form).append(owCheckbox); | ||||
|  | ||||
|         var self = this; | ||||
|         this._attachLoadEvent(iframe, function(){ | ||||
|             self.log('iframe loaded'); | ||||
|  | ||||
|             var response = self._getIframeContentJSON(iframe); | ||||
|  | ||||
|             self._options.onComplete(id, fileName, response); | ||||
|             self._dequeue(id); | ||||
|  | ||||
|             delete self._inputs[id]; | ||||
|             // timeout added to fix busy state in FF3.6 | ||||
|             setTimeout(function(){ | ||||
|                 qq.remove(iframe); | ||||
|             }, 1); | ||||
|         }); | ||||
|  | ||||
|         form.submit(); | ||||
|         qq.remove(form); | ||||
|  | ||||
|         return id; | ||||
|     } | ||||
| }); | ||||
|  | ||||
| qq.extend(qq.UploadHandlerXhr.prototype, { | ||||
|     uploadAll: function(params){ | ||||
|         this._uploadAll(params); | ||||
|     }, | ||||
|  | ||||
|     getName: function(id){ | ||||
|         var file = this._files[id]; | ||||
|         var name = document.getElementById('mediamanager__upload_item'+id); | ||||
|         if (name != null) { | ||||
|             return name.value; | ||||
|         } else { | ||||
|             if (file != null) { | ||||
|                 // fix missing name in Safari 4 | ||||
|                 return file.fileName != null ? file.fileName : file.name; | ||||
|             } else { | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     getSize: function(id){ | ||||
|         var file = this._files[id]; | ||||
|         if (file == null) return null; | ||||
|         return file.fileSize != null ? file.fileSize : file.size; | ||||
|     }, | ||||
|  | ||||
|     _upload: function(id, params){ | ||||
|         var file = this._files[id], | ||||
|             name = this.getName(id), | ||||
|             size = this.getSize(id); | ||||
|         if (name == null || size == null) return; | ||||
|  | ||||
|         this._loaded[id] = 0; | ||||
|  | ||||
|         var xhr = this._xhrs[id] = new XMLHttpRequest(); | ||||
|         var self = this; | ||||
|  | ||||
|         xhr.upload.onprogress = function(e){ | ||||
|             if (e.lengthComputable){ | ||||
|                 self._loaded[id] = e.loaded; | ||||
|                 self._options.onProgress(id, name, e.loaded, e.total); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         xhr.onreadystatechange = function(){ | ||||
|             if (xhr.readyState == 4){ | ||||
|                 self._onComplete(id, xhr); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         // build query string | ||||
|         params = params || {}; | ||||
|         params['qqfile'] = name; | ||||
|         params['ow'] = jQuery('.dw__ow').is(':checked'); | ||||
|         var queryString = qq.obj2url(params, this._options.action); | ||||
|  | ||||
|         xhr.open("POST", queryString, true); | ||||
|         xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); | ||||
|         xhr.setRequestHeader("X-File-Name", encodeURIComponent(name)); | ||||
|         xhr.setRequestHeader("Content-Type", "application/octet-stream"); | ||||
|         xhr.send(file); | ||||
|     }, | ||||
|  | ||||
|     _uploadAll: function(params){ | ||||
|         jQuery(".qq-upload-spinner").each(function (i) { | ||||
|             jQuery(this).removeClass('hidden'); | ||||
|         }); | ||||
|         for (key in this._files) { | ||||
|             this.upload(key, params); | ||||
|         } | ||||
|  | ||||
|     } | ||||
| }); | ||||
							
								
								
									
										69
									
								
								ap23/web/doku/lib/scripts/helpers.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,69 @@ | ||||
| /** | ||||
|  * Various helper functions | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * A PHP-style substr_replace | ||||
|  * | ||||
|  * Supports negative start and length and omitting length, but not | ||||
|  * str and replace arrays. | ||||
|  * See http://php.net/substr-replace for further documentation. | ||||
|  */ | ||||
| function substr_replace(str, replace, start, length) { | ||||
|     var a2, b1; | ||||
|     a2 = (start < 0 ? str.length : 0) + start; | ||||
|     if (typeof length === 'undefined') { | ||||
|         length = str.length - a2; | ||||
|     } else if (length < 0 && start < 0 && length <= start) { | ||||
|         length = 0; | ||||
|     } | ||||
|     b1 = (length < 0 ? str.length : a2) + length; | ||||
|     return str.substring(0, a2) + replace + str.substring(b1); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Bind variables to a function call creating a closure | ||||
|  * | ||||
|  * Use this to circumvent variable scope problems when creating closures | ||||
|  * inside a loop | ||||
|  * | ||||
|  * @author  Adrian Lang <lang@cosmocode.de> | ||||
|  * @link    http://www.cosmocode.de/en/blog/gohr/2009-10/15-javascript-fixing-the-closure-scope-in-loops | ||||
|  * @param   functionref fnc - the function to be called | ||||
|  * @param   mixed - any arguments to be passed to the function | ||||
|  * @returns functionref | ||||
|  */ | ||||
| function bind(fnc/*, ... */) { | ||||
|     var Aps = Array.prototype.slice, | ||||
|     // Store passed arguments in this scope. | ||||
|     // Since arguments is no Array nor has an own slice method, | ||||
|     // we have to apply the slice method from the Array.prototype | ||||
|         static_args = Aps.call(arguments, 1); | ||||
|  | ||||
|     // Return a function evaluating the passed function with the | ||||
|     // given args and optional arguments passed on invocation. | ||||
|     return function (/* ... */) { | ||||
|         // Same here, but we use Array.prototype.slice solely for | ||||
|         // converting arguments to an Array. | ||||
|         return fnc.apply(this, | ||||
|                          static_args.concat(Aps.call(arguments, 0))); | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Report an error from a JS file to the console | ||||
|  * | ||||
|  * @param e    The error object | ||||
|  * @param file The file in which the error occurred | ||||
|  */ | ||||
| function logError(e, file) { | ||||
|     if (window.console && console.error) { | ||||
|         console.error('The error "%s: %s" occurred in file "%s". ' + | ||||
|             'If this is in a plugin try updating or disabling the plugin, ' + | ||||
|             'if this is in a template try updating the template or switching to the "dokuwiki" template.', | ||||
|             e.name, e.message, file); | ||||
|         if(e.stack) { | ||||
|             console.error(e.stack); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										302
									
								
								ap23/web/doku/lib/scripts/hotkeys.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,302 @@ | ||||
| /** | ||||
|  * 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 button 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() { | ||||
|                     location.href = a.href; | ||||
|                 }); | ||||
|                 a.accessKey = ''; | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         /** | ||||
|          * Lookup all button [type="submit"] with accesskey and register event - | ||||
|          * perform "click" on a button. | ||||
|          */ | ||||
|         var inputs = document.getElementsByTagName("button"); | ||||
|         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 = is_macos; | ||||
|  | ||||
|     /** | ||||
|      * 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 (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(); | ||||
| } | ||||
							
								
								
									
										11
									
								
								ap23/web/doku/lib/scripts/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,11 @@ | ||||
| <!DOCTYPE html> | ||||
| <html> | ||||
| <head> | ||||
| <meta http-equiv="refresh" content="0; URL=../../" /> | ||||
| <meta name="robots" content="noindex" /> | ||||
| <title>nothing here...</title> | ||||
| </head> | ||||
| <body> | ||||
| <!-- this is just here to prevent directory browsing --> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										16
									
								
								ap23/web/doku/lib/scripts/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,16 @@ | ||||
| var dw_index = jQuery('#index__tree').dw_tree({deferInit: true, | ||||
|     load_data: function  (show_sublist, $clicky) { | ||||
|         jQuery.post( | ||||
|             DOKU_BASE + 'lib/exe/ajax.php', | ||||
|             $clicky[0].search.substr(1) + '&call=index', | ||||
|             show_sublist, 'html' | ||||
|         ); | ||||
|     } | ||||
| }); | ||||
| jQuery(function () { | ||||
|     var $tree = jQuery('#index__tree'); | ||||
|  | ||||
|     dw_index.$obj = $tree; | ||||
|  | ||||
|     dw_index.init(); | ||||
| }); | ||||
| After Width: | Height: | Size: 393 B | 
| After Width: | Height: | Size: 265 B | 
| After Width: | Height: | Size: 323 B | 
| After Width: | Height: | Size: 324 B | 
| After Width: | Height: | Size: 390 B | 
| After Width: | Height: | Size: 325 B | 
| After Width: | Height: | Size: 6.9 KiB | 
| After Width: | Height: | Size: 4.6 KiB | 
| After Width: | Height: | Size: 6.9 KiB | 
| After Width: | Height: | Size: 6.9 KiB | 
| After Width: | Height: | Size: 4.6 KiB | 
							
								
								
									
										1311
									
								
								ap23/web/doku/lib/scripts/jquery/jquery-ui-theme/smoothness.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										13
									
								
								ap23/web/doku/lib/scripts/jquery/jquery-ui.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										117
									
								
								ap23/web/doku/lib/scripts/jquery/jquery.cookie.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,117 @@ | ||||
| /*! | ||||
|  * jQuery Cookie Plugin v1.4.1 | ||||
|  * https://github.com/carhartl/jquery-cookie | ||||
|  * | ||||
|  * Copyright 2013 Klaus Hartl | ||||
|  * Released under the MIT license | ||||
|  */ | ||||
| (function (factory) { | ||||
| 	if (typeof define === 'function' && define.amd) { | ||||
| 		// AMD | ||||
| 		define(['jquery'], factory); | ||||
| 	} else if (typeof exports === 'object') { | ||||
| 		// CommonJS | ||||
| 		factory(require('jquery')); | ||||
| 	} else { | ||||
| 		// Browser globals | ||||
| 		factory(jQuery); | ||||
| 	} | ||||
| }(function ($) { | ||||
|  | ||||
| 	var pluses = /\+/g; | ||||
|  | ||||
| 	function encode(s) { | ||||
| 		return config.raw ? s : encodeURIComponent(s); | ||||
| 	} | ||||
|  | ||||
| 	function decode(s) { | ||||
| 		return config.raw ? s : decodeURIComponent(s); | ||||
| 	} | ||||
|  | ||||
| 	function stringifyCookieValue(value) { | ||||
| 		return encode(config.json ? JSON.stringify(value) : String(value)); | ||||
| 	} | ||||
|  | ||||
| 	function parseCookieValue(s) { | ||||
| 		if (s.indexOf('"') === 0) { | ||||
| 			// This is a quoted cookie as according to RFC2068, unescape... | ||||
| 			s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); | ||||
| 		} | ||||
|  | ||||
| 		try { | ||||
| 			// Replace server-side written pluses with spaces. | ||||
| 			// If we can't decode the cookie, ignore it, it's unusable. | ||||
| 			// If we can't parse the cookie, ignore it, it's unusable. | ||||
| 			s = decodeURIComponent(s.replace(pluses, ' ')); | ||||
| 			return config.json ? JSON.parse(s) : s; | ||||
| 		} catch(e) {} | ||||
| 	} | ||||
|  | ||||
| 	function read(s, converter) { | ||||
| 		var value = config.raw ? s : parseCookieValue(s); | ||||
| 		return $.isFunction(converter) ? converter(value) : value; | ||||
| 	} | ||||
|  | ||||
| 	var config = $.cookie = function (key, value, options) { | ||||
|  | ||||
| 		// Write | ||||
|  | ||||
| 		if (value !== undefined && !$.isFunction(value)) { | ||||
| 			options = $.extend({}, config.defaults, options); | ||||
|  | ||||
| 			if (typeof options.expires === 'number') { | ||||
| 				var days = options.expires, t = options.expires = new Date(); | ||||
| 				t.setTime(+t + days * 864e+5); | ||||
| 			} | ||||
|  | ||||
| 			return (document.cookie = [ | ||||
| 				encode(key), '=', stringifyCookieValue(value), | ||||
| 				options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE | ||||
| 				options.path    ? '; path=' + options.path : '', | ||||
| 				options.domain  ? '; domain=' + options.domain : '', | ||||
| 				options.secure  ? '; secure' : '' | ||||
| 			].join('')); | ||||
| 		} | ||||
|  | ||||
| 		// Read | ||||
|  | ||||
| 		var result = key ? undefined : {}; | ||||
|  | ||||
| 		// To prevent the for loop in the first place assign an empty array | ||||
| 		// in case there are no cookies at all. Also prevents odd result when | ||||
| 		// calling $.cookie(). | ||||
| 		var cookies = document.cookie ? document.cookie.split('; ') : []; | ||||
|  | ||||
| 		for (var i = 0, l = cookies.length; i < l; i++) { | ||||
| 			var parts = cookies[i].split('='); | ||||
| 			var name = decode(parts.shift()); | ||||
| 			var cookie = parts.join('='); | ||||
|  | ||||
| 			if (key && key === name) { | ||||
| 				// If second argument (value) is a function it's a converter... | ||||
| 				result = read(cookie, value); | ||||
| 				break; | ||||
| 			} | ||||
|  | ||||
| 			// Prevent storing a cookie that we couldn't decode. | ||||
| 			if (!key && (cookie = read(cookie)) !== undefined) { | ||||
| 				result[name] = cookie; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return result; | ||||
| 	}; | ||||
|  | ||||
| 	config.defaults = {}; | ||||
|  | ||||
| 	$.removeCookie = function (key, options) { | ||||
| 		if ($.cookie(key) === undefined) { | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		// Must not alter options, thus extending a fresh object... | ||||
| 		$.cookie(key, '', $.extend({}, options, { expires: -1 })); | ||||
| 		return !$.cookie(key); | ||||
| 	}; | ||||
|  | ||||
| })); | ||||
							
								
								
									
										2
									
								
								ap23/web/doku/lib/scripts/jquery/jquery.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										48
									
								
								ap23/web/doku/lib/scripts/jquery/update.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						| @@ -0,0 +1,48 @@ | ||||
| #!/usr/bin/env sh | ||||
| # | ||||
| # This script loads the latest jQuery and jQuery-UI 1.* versions from jQuery's CDN | ||||
| # | ||||
| # It also loads the 'smoothness' jQuery-UI theme and all referenced images. | ||||
| # | ||||
| # @author Andreas Gohr <andi@splitbrain.org> | ||||
| # @author Stefan Grönke <stefan@gronke.net> | ||||
| # @link   http://code.jquery.com/ | ||||
|  | ||||
| # load version infor from external file | ||||
| source ./versions | ||||
| JQUI_HOST="https://code.jquery.com/ui/$JQUI_VERSION" | ||||
| JQUI_GIT="https://raw.githubusercontent.com/jquery/jquery-ui/$JQUI_VERSION/ui" | ||||
|  | ||||
| # load jQuery | ||||
| wget -nv https://code.jquery.com/jquery-${JQ_VERSION}.min.js      -O jquery.min.js | ||||
| # load jQuery-UI | ||||
| wget -nv "$JQUI_HOST/jquery-ui.min.js" -O jquery-ui.min.js | ||||
|  | ||||
| # load the smoothness theme | ||||
| mkdir -p jquery-ui-theme/images | ||||
| wget -nv -qO- "$JQUI_HOST/themes/smoothness/jquery-ui.css" | sed "s/font-family:[^;]*;//" > jquery-ui-theme/smoothness.css | ||||
| images=`gawk 'match($0, /url\("?(images\/[^\)"]+)"?\)/, m) { print m[1] }' jquery-ui-theme/smoothness.css` | ||||
| for img in $images | ||||
| do | ||||
|     wget -nv "$JQUI_HOST/themes/smoothness/$img" -O jquery-ui-theme/$img | ||||
| done | ||||
|  | ||||
| # load the localization data for jquery ui | ||||
| for LNG in ../../../inc/lang/* | ||||
| do | ||||
|     CODE=`basename $LNG` | ||||
|     wget -nv "$JQUI_GIT/i18n/datepicker-$CODE.js" -O $LNG/jquery.ui.datepicker.js | ||||
|     if [ ! -s "$LNG/jquery.ui.datepicker.js" ]; then | ||||
|         rm -f $LNG/jquery.ui.datepicker.js | ||||
|     fi | ||||
| done | ||||
|  | ||||
| # some custom language codes | ||||
| wget -nv "$JQUI_GIT/i18n/datepicker-de.js" -O ../../../inc/lang/de-informal/jquery.ui.datepicker.js | ||||
| wget -nv "$JQUI_GIT/i18n/datepicker-pt-BR.js" -O ../../../inc/lang/pt-br/jquery.ui.datepicker.js | ||||
| wget -nv "$JQUI_GIT/i18n/datepicker-zh-CN.js" -O ../../../inc/lang/zh/jquery.ui.datepicker.js | ||||
| wget -nv "$JQUI_GIT/i18n/datepicker-zh-TW.js" -O ../../../inc/lang/zh-tw/jquery.ui.datepicker.js | ||||
| wget -nv "$JQUI_GIT/i18n/datepicker-cy-GB.js" -O ../../../inc/lang/cy/jquery.ui.datepicker.js | ||||
|  | ||||
| # strip source maps | ||||
| sed -i '/sourceMappingURL/d' *.min.js | ||||
							
								
								
									
										3
									
								
								ap23/web/doku/lib/scripts/jquery/versions
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,3 @@ | ||||
| # this is loaded from the update.sh script and our PHP code | ||||
| JQ_VERSION=3.5.1 | ||||
| JQUI_VERSION=1.12.1 | ||||
							
								
								
									
										339
									
								
								ap23/web/doku/lib/scripts/linkwiz.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,339 @@ | ||||
| /** | ||||
|  * The Link Wizard | ||||
|  * | ||||
|  * @author Andreas Gohr <gohr@cosmocode.de> | ||||
|  * @author Pierre Spring <pierre.spring@caillou.ch> | ||||
|  */ | ||||
| var dw_linkwiz = { | ||||
|     $wiz: null, | ||||
|     $entry: null, | ||||
|     result: null, | ||||
|     timer: null, | ||||
|     textArea: null, | ||||
|     selected: null, | ||||
|     selection: null, | ||||
|  | ||||
|     /** | ||||
|      * Initialize the dw_linkwizard by creating the needed HTML | ||||
|      * and attaching the eventhandlers | ||||
|      */ | ||||
|     init: function($editor){ | ||||
|         // position relative to the text area | ||||
|         var pos = $editor.position(); | ||||
|  | ||||
|         // create HTML Structure | ||||
|         if(dw_linkwiz.$wiz) | ||||
|             return; | ||||
|         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') | ||||
|                .css({ | ||||
|                     'position':    'absolute', | ||||
|                     'top':         (pos.top+20)+'px', | ||||
|                     'left':        (pos.left+80)+'px' | ||||
|                    }) | ||||
|                .hide() | ||||
|                .appendTo('.dokuwiki:first'); | ||||
|  | ||||
|         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'); | ||||
|         if(JSINFO.namespace){ | ||||
|             dw_linkwiz.$entry.val(JSINFO.namespace+':'); | ||||
|         } | ||||
|  | ||||
|         // attach event handlers | ||||
|         jQuery('#link__wiz .ui-dialog-titlebar-close').on('click', dw_linkwiz.hide); | ||||
|         dw_linkwiz.$entry.keyup(dw_linkwiz.onEntry); | ||||
|         jQuery(dw_linkwiz.result).on('click', 'a', dw_linkwiz.onResultClick); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * handle all keyup events in the entry field | ||||
|      */ | ||||
|     onEntry: function(e){ | ||||
|         if(e.keyCode == 37 || e.keyCode == 39){ //left/right | ||||
|             return true; //ignore | ||||
|         } | ||||
|         if(e.keyCode == 27){ //Escape | ||||
|             dw_linkwiz.hide(); | ||||
|             e.preventDefault(); | ||||
|             e.stopPropagation(); | ||||
|             return false; | ||||
|         } | ||||
|         if(e.keyCode == 38){ //Up | ||||
|             dw_linkwiz.select(dw_linkwiz.selected -1); | ||||
|             e.preventDefault(); | ||||
|             e.stopPropagation(); | ||||
|             return false; | ||||
|         } | ||||
|         if(e.keyCode == 40){ //Down | ||||
|             dw_linkwiz.select(dw_linkwiz.selected +1); | ||||
|             e.preventDefault(); | ||||
|             e.stopPropagation(); | ||||
|             return false; | ||||
|         } | ||||
|         if(e.keyCode == 13){ //Enter | ||||
|             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(dw_linkwiz.$entry.val()){ | ||||
|                 dw_linkwiz.insertLink(dw_linkwiz.$entry.val()); | ||||
|             } | ||||
|  | ||||
|             e.preventDefault(); | ||||
|             e.stopPropagation(); | ||||
|             return false; | ||||
|         } | ||||
|         dw_linkwiz.autocomplete(); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Get one of the results by index | ||||
|      * | ||||
|      * @param   num int result div to return | ||||
|      * @returns DOMObject or null | ||||
|      */ | ||||
|     getResult: function(num){ | ||||
|         DEPRECATED('use dw_linkwiz.$getResult()[0] instead'); | ||||
|         return dw_linkwiz.$getResult()[0] || null; | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Get one of the results by index | ||||
|      * | ||||
|      * @param   num int result div to return | ||||
|      * @returns jQuery object | ||||
|      */ | ||||
|     $getResult: function(num) { | ||||
|         return jQuery(dw_linkwiz.result).find('div').eq(num); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Select the given result | ||||
|      */ | ||||
|     select: function(num){ | ||||
|         if(num < 0){ | ||||
|             dw_linkwiz.deselect(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         var $obj = dw_linkwiz.$getResult(num); | ||||
|         if ($obj.length === 0) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         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(dw_linkwiz.selected > -1){ | ||||
|             dw_linkwiz.$getResult(dw_linkwiz.selected).removeClass('selected'); | ||||
|         } | ||||
|         dw_linkwiz.selected = -1; | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Handle clicks in the result set an dispatch them to | ||||
|      * resultClick() | ||||
|      */ | ||||
|     onResultClick: function(e){ | ||||
|         if(!jQuery(this).is('a')) { | ||||
|             return; | ||||
|         } | ||||
|         e.stopPropagation(); | ||||
|         e.preventDefault(); | ||||
|         dw_linkwiz.resultClick(this); | ||||
|         return false; | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Handles the "click" on a given result anchor | ||||
|      */ | ||||
|     resultClick: function(a){ | ||||
|         dw_linkwiz.$entry.val(a.title); | ||||
|         if(a.title == '' || a.title.substr(a.title.length-1) == ':'){ | ||||
|             dw_linkwiz.autocomplete_exec(); | ||||
|         }else{ | ||||
|             if (jQuery(a.nextSibling).is('span')) { | ||||
|                 dw_linkwiz.insertLink(a.nextSibling.innerHTML); | ||||
|             }else{ | ||||
|                 dw_linkwiz.insertLink(''); | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Insert the id currently in the entry box to the textarea, | ||||
|      * 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){ | ||||
|         var link = dw_linkwiz.$entry.val(), | ||||
|             sel, stxt; | ||||
|         if(!link) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         sel = DWgetSelection(dw_linkwiz.textArea); | ||||
|         if(sel.start == 0 && sel.end == 0) { | ||||
|             sel = dw_linkwiz.selection; | ||||
|         } | ||||
|  | ||||
|         stxt = sel.getText(); | ||||
|  | ||||
|         // don't include trailing space in selection | ||||
|         if(stxt.charAt(stxt.length - 1) == ' '){ | ||||
|             sel.end--; | ||||
|             stxt = sel.getText(); | ||||
|         } | ||||
|  | ||||
|         if(!stxt && !DOKU_UHC) { | ||||
|             stxt=title; | ||||
|         } | ||||
|  | ||||
|         // prepend colon inside namespaces for non namespace pages | ||||
|         if(dw_linkwiz.textArea.form.id.value.indexOf(':') != -1 && | ||||
|            link.indexOf(':') == -1){ | ||||
|            link = ':' + link; | ||||
|         } | ||||
|  | ||||
|         var so = link.length; | ||||
|         var eo = 0; | ||||
|         if(dw_linkwiz.val){ | ||||
|             if(dw_linkwiz.val.open) { | ||||
|                 so += dw_linkwiz.val.open.length; | ||||
|                 link = dw_linkwiz.val.open+link; | ||||
|             } | ||||
|             link += '|'; | ||||
|             so += 1; | ||||
|             if(stxt) { | ||||
|                 link += stxt; | ||||
|             } | ||||
|             if(dw_linkwiz.val.close) { | ||||
|                 link += dw_linkwiz.val.close; | ||||
|                 eo = dw_linkwiz.val.close.length; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         pasteText(sel,link,{startofs: so, endofs: eo}); | ||||
|         dw_linkwiz.hide(); | ||||
|  | ||||
|         // reset the entry to the parent namespace | ||||
|         var externallinkpattern = new RegExp('^((f|ht)tps?:)?//', 'i'), | ||||
|             entry_value; | ||||
|         if (externallinkpattern.test(dw_linkwiz.$entry.val())) { | ||||
|             if (JSINFO.namespace) { | ||||
|                 entry_value = JSINFO.namespace + ':'; | ||||
|             } else { | ||||
|                 entry_value = ''; //reset whole external links | ||||
|             } | ||||
|         } else { | ||||
|             entry_value = dw_linkwiz.$entry.val().replace(/[^:]*$/, '') | ||||
|         } | ||||
|         dw_linkwiz.$entry.val(entry_value); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Start the page/namespace lookup timer | ||||
|      * | ||||
|      * Calls autocomplete_exec when the timer runs out | ||||
|      */ | ||||
|     autocomplete: function(){ | ||||
|         if(dw_linkwiz.timer !== null){ | ||||
|             window.clearTimeout(dw_linkwiz.timer); | ||||
|             dw_linkwiz.timer = null; | ||||
|         } | ||||
|  | ||||
|         dw_linkwiz.timer = window.setTimeout(dw_linkwiz.autocomplete_exec,350); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Executes the AJAX call for the page/namespace lookup | ||||
|      */ | ||||
|     autocomplete_exec: function(){ | ||||
|         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 link wizard | ||||
|      */ | ||||
|     show: function(){ | ||||
|         dw_linkwiz.selection  = DWgetSelection(dw_linkwiz.textArea); | ||||
|         dw_linkwiz.$wiz.show(); | ||||
|         dw_linkwiz.$entry.focus(); | ||||
|         dw_linkwiz.autocomplete(); | ||||
|  | ||||
|         // Move the cursor to the end of the input | ||||
|         var temp = dw_linkwiz.$entry.val(); | ||||
|         dw_linkwiz.$entry.val(''); | ||||
|         dw_linkwiz.$entry.val(temp); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Hide the link wizard | ||||
|      */ | ||||
|     hide: function(){ | ||||
|         dw_linkwiz.$wiz.hide(); | ||||
|         dw_linkwiz.textArea.focus(); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Toggle the link wizard | ||||
|      */ | ||||
|     toggle: function(){ | ||||
|         if(dw_linkwiz.$wiz.css('display') == 'none'){ | ||||
|             dw_linkwiz.show(); | ||||
|         }else{ | ||||
|             dw_linkwiz.hide(); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										151
									
								
								ap23/web/doku/lib/scripts/locktimer.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,151 @@ | ||||
| /** | ||||
|  * Class managing the timer to display a warning on a expiring lock | ||||
|  */ | ||||
| var dw_locktimer = { | ||||
|     timeout: 0, | ||||
|     draft: false, | ||||
|     timerID: null, | ||||
|     lasttime: null, | ||||
|     msg: LANG.willexpire, | ||||
|     pageid: '', | ||||
|     fieldsToSaveAsDraft: [ | ||||
|         'input[name=prefix]', | ||||
|         'textarea[name=wikitext]', | ||||
|         'input[name=suffix]', | ||||
|         'input[name=date]', | ||||
|     ], | ||||
|     callbacks: [], | ||||
|  | ||||
|     /** | ||||
|      * Initialize the lock timer | ||||
|      * | ||||
|      * @param {int}    timeout Length of timeout in seconds | ||||
|      * @param {bool}   draft   Whether to save drafts | ||||
|      * @param {string} edid    Optional; ID of an edit object which has to be present | ||||
|      */ | ||||
|     init: function(timeout,draft,edid){ | ||||
|         var $edit; | ||||
|  | ||||
|         edid = edid || 'wiki__text'; | ||||
|  | ||||
|         $edit = jQuery('#' + edid); | ||||
|         if($edit.length === 0 || $edit.attr('readonly')) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // init values | ||||
|         dw_locktimer.timeout  = timeout*1000; | ||||
|         dw_locktimer.draft    = draft; | ||||
|         dw_locktimer.lasttime = new Date(); | ||||
|  | ||||
|         dw_locktimer.pageid   = jQuery('#dw__editform').find('input[name=id]').val(); | ||||
|         if(!dw_locktimer.pageid) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // register refresh event | ||||
|         $edit.keypress(dw_locktimer.refresh); | ||||
|         // start timer | ||||
|         dw_locktimer.reset(); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Add another field of the editform to be posted to the server when a draft is saved | ||||
|      */ | ||||
|     addField: function(selector) { | ||||
|         dw_locktimer.fieldsToSaveAsDraft.push(selector); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Add a callback that is executed when the post request to renew the lock and save the draft returns successfully | ||||
|      * | ||||
|      * If the user types into the edit-area, then dw_locktimer will regularly send a post request to the DokuWiki server | ||||
|      * to extend the page's lock and update the draft. When this request returns successfully, then the draft__status | ||||
|      * is updated. This method can be used to add further callbacks to be executed at that moment. | ||||
|      * | ||||
|      * @param {function} callback the only param is the data returned by the server | ||||
|      */ | ||||
|     addRefreshCallback: function(callback) { | ||||
|         dw_locktimer.callbacks.push(callback); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * (Re)start the warning timer | ||||
|      */ | ||||
|     reset: function(){ | ||||
|         dw_locktimer.clear(); | ||||
|         dw_locktimer.timerID = window.setTimeout(dw_locktimer.warning, dw_locktimer.timeout); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Display the warning about the expiring lock | ||||
|      */ | ||||
|     warning: function(){ | ||||
|         dw_locktimer.clear(); | ||||
|         alert(fixtxt(dw_locktimer.msg)); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Remove the current warning timer | ||||
|      */ | ||||
|     clear: function(){ | ||||
|         if(dw_locktimer.timerID !== null){ | ||||
|             window.clearTimeout(dw_locktimer.timerID); | ||||
|             dw_locktimer.timerID = null; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Refresh the lock via AJAX | ||||
|      * | ||||
|      * Called on keypresses in the edit area | ||||
|      */ | ||||
|     refresh: function(){ | ||||
|         var now = new Date(), | ||||
|             params = 'call=lock&id=' + dw_locktimer.pageid + '&'; | ||||
|  | ||||
|         // refresh every half minute only | ||||
|         if(now.getTime() - dw_locktimer.lasttime.getTime() <= 30*1000) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // POST everything necessary for draft saving | ||||
|         if(dw_locktimer.draft && jQuery('#dw__editform').find('textarea[name=wikitext]').length > 0){ | ||||
|             params += jQuery('#dw__editform').find(dw_locktimer.fieldsToSaveAsDraft.join(', ')).serialize(); | ||||
|         } | ||||
|  | ||||
|         jQuery.post( | ||||
|             DOKU_BASE + 'lib/exe/ajax.php', | ||||
|             params, | ||||
|             null, | ||||
|             'json' | ||||
|         ).done(function dwLocktimerRefreshDoneHandler(data) { | ||||
|             dw_locktimer.callbacks.forEach( | ||||
|                 function (callback) { | ||||
|                     callback(data); | ||||
|                 } | ||||
|             ); | ||||
|         }); | ||||
|         dw_locktimer.lasttime = now; | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Callback. Resets the warning timer | ||||
|      */ | ||||
|     refreshed: function(data){ | ||||
|         if (data.errors.length) { | ||||
|             data.errors.forEach(function(error) { | ||||
|                 jQuery('#draft__status').after( | ||||
|                     jQuery('<div class="error"></div>').text(error) | ||||
|                 ); | ||||
|             }) | ||||
|         } | ||||
|  | ||||
|         jQuery('#draft__status').html(data.draft); | ||||
|         if(data.lock !== '1') { | ||||
|             return; // locking failed | ||||
|         } | ||||
|         dw_locktimer.reset(); | ||||
|     } | ||||
| }; | ||||
| dw_locktimer.callbacks.push(dw_locktimer.refreshed); | ||||
							
								
								
									
										974
									
								
								ap23/web/doku/lib/scripts/media.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,974 @@ | ||||
| /** | ||||
|  * JavaScript functionality for the media management popup | ||||
|  * | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  * @author Pierre Spring <pierre.spring@caillou.ch> | ||||
|  */ | ||||
|  | ||||
| var dw_mediamanager = { | ||||
|     keepopen: false, | ||||
|     hide: false, | ||||
|     popup: false, | ||||
|     display: false, | ||||
|     ext: false, | ||||
|     $popup: null, | ||||
|  | ||||
|     // Image insertion opts | ||||
|     align: false, | ||||
|     link: false, | ||||
|     size: false, | ||||
|     forbidden_opts: {}, | ||||
|  | ||||
|     // File list options | ||||
|     view_opts: {list: false, sort: false}, | ||||
|  | ||||
|     layout_width: 0, | ||||
|  | ||||
|     // The minimum height of the full-screen mediamanager in px | ||||
|     minHeights: {thumbs: 200, rows: 100}, | ||||
|  | ||||
|     init: function () { | ||||
|         var $content, $tree; | ||||
|         $content = jQuery('#media__content'); | ||||
|         $tree = jQuery('#media__tree'); | ||||
|         if (!$tree.length) return; | ||||
|  | ||||
|         dw_mediamanager.prepare_content($content); | ||||
|  | ||||
|         dw_mediamanager.attachoptions(); | ||||
|         dw_mediamanager.initpopup(); | ||||
|  | ||||
|         // add the action to autofill the "upload as" field | ||||
|         $content | ||||
|             .on('change', '#upload__file', dw_mediamanager.suggest) | ||||
|             // Attach the image selector action to all links | ||||
|             .on('click', 'a.select', dw_mediamanager.select) | ||||
|             // Attach deletion confirmation dialog to the delete buttons | ||||
|             .on('click', '#media__content a.btn_media_delete', dw_mediamanager.confirmattach) | ||||
|             .on('submit', '#mediamanager__done_form', dw_mediamanager.list); | ||||
|  | ||||
|         $tree.dw_tree({ | ||||
|             toggle_selector: 'img', | ||||
|             load_data: function (show_sublist, $clicky) { | ||||
|                 // get the enclosed link (is always the first one) | ||||
|                 var $link = $clicky.parent().find('div.li a.idx_dir'); | ||||
|  | ||||
|                 jQuery.post( | ||||
|                     DOKU_BASE + 'lib/exe/ajax.php', | ||||
|                     $link[0].search.substr(1) + '&call=medians', | ||||
|                     show_sublist, | ||||
|                     'html' | ||||
|                 ); | ||||
|             }, | ||||
|  | ||||
|             toggle_display: function ($clicky, opening) { | ||||
|                 $clicky.attr('src', DOKU_BASE + 'lib/images/' + (opening ? 'minus' : 'plus') + '.gif'); | ||||
|             } | ||||
|         }); | ||||
|         $tree.on('click', 'a', dw_mediamanager.list); | ||||
|  | ||||
|         // Init view property | ||||
|         dw_mediamanager.set_fileview_list(); | ||||
|  | ||||
|         dw_mediamanager.init_options(); | ||||
|  | ||||
|         dw_mediamanager.image_diff(); | ||||
|         dw_mediamanager.init_ajax_uploader(); | ||||
|  | ||||
|         // changing opened tab in the file list panel | ||||
|         var $page = jQuery('#mediamanager__page'); | ||||
|         $page.find('div.filelist') | ||||
|             .on('click', 'ul.tabs a', dw_mediamanager.list) | ||||
|             // loading file details | ||||
|             .on('click', 'div.panelContent a', dw_mediamanager.details) | ||||
|             // search form | ||||
|             .on('submit', '#dw__mediasearch', dw_mediamanager.list) | ||||
|             // "upload as" field autofill | ||||
|             .on('change', '#upload__file', dw_mediamanager.suggest) | ||||
|             // uploaded images | ||||
|             .on('click', '.qq-upload-file a', dw_mediamanager.details); | ||||
|  | ||||
|         // changing opened tab in the file details panel | ||||
|         $page.find('div.file') | ||||
|             .on('click', 'ul.tabs a', dw_mediamanager.details) | ||||
|             // "update new version" button | ||||
|             .on('submit', '#mediamanager__btn_update', dw_mediamanager.list) | ||||
|             // revisions form | ||||
|             .on('submit', '#page__revisions', dw_mediamanager.details) | ||||
|             .on('click', '#page__revisions a', dw_mediamanager.details) | ||||
|             // meta edit form | ||||
|             .on('submit', '#mediamanager__save_meta', dw_mediamanager.details) | ||||
|             // delete button | ||||
|             .on('submit', '#mediamanager__btn_delete', dw_mediamanager.details) | ||||
|             // "restore this version" button | ||||
|             .on('submit', '#mediamanager__btn_restore', dw_mediamanager.details) | ||||
|             // less/more recent buttons in media revisions form | ||||
|             .on('submit', '.btn_newer, .btn_older', dw_mediamanager.details); | ||||
|  | ||||
|         dw_mediamanager.update_resizable(); | ||||
|         dw_mediamanager.layout_width = $page.width(); | ||||
|         jQuery(window).on('resize', dw_mediamanager.window_resize); | ||||
|     }, | ||||
|  | ||||
|     init_options: function () { | ||||
|         var $options = jQuery('div.filelist div.panelHeader form.options'), | ||||
|             $listType, $sortBy, $both; | ||||
|         if ($options.length === 0) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $listType = $options.find('li.listType'); | ||||
|         $sortBy = $options.find('li.sortBy'); | ||||
|         $both = $listType.add($sortBy); | ||||
|  | ||||
|         // Remove the submit button | ||||
|         $options.find('button[type=submit]').parent().hide(); | ||||
|  | ||||
|         // Prepare HTML for jQuery UI buttonset | ||||
|         $both.find('label').each(function () { | ||||
|             var $this = jQuery(this); | ||||
|             $this.children('input').appendTo($this.parent()); | ||||
|         }); | ||||
|  | ||||
|         // Init buttonset | ||||
|         $both.find("input[type='radio']").checkboxradio({icon: false}); | ||||
|         $both.controlgroup(); | ||||
|  | ||||
|         // Change handlers | ||||
|         $listType.children('input').change(function () { | ||||
|             dw_mediamanager.set_fileview_list(); | ||||
|         }); | ||||
|         $sortBy.children('input').change(function (event) { | ||||
|             dw_mediamanager.set_fileview_sort(); | ||||
|             dw_mediamanager.list.call(jQuery('#dw__mediasearch')[0] || this, event); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * build the popup window | ||||
|      * | ||||
|      * @author Dominik Eckelmann <eckelmann@cosmocode.de> | ||||
|      */ | ||||
|     initpopup: function () { | ||||
|         var opts, $insp, $insbtn; | ||||
|  | ||||
|         dw_mediamanager.$popup = jQuery(document.createElement('div')) | ||||
|             .attr('id', 'media__popup_content') | ||||
|             .dialog({ | ||||
|                 autoOpen: false, width: 280, modal: true, | ||||
|                 draggable: true, title: LANG.mediatitle, | ||||
|                 resizable: false | ||||
|             }); | ||||
|  | ||||
|         opts = [ | ||||
|             { | ||||
|                 id: 'link', label: LANG.mediatarget, | ||||
|                 btns: ['lnk', 'direct', 'nolnk', 'displaylnk'] | ||||
|             }, | ||||
|             { | ||||
|                 id: 'align', label: LANG.mediaalign, | ||||
|                 btns: ['noalign', 'left', 'center', 'right'] | ||||
|             }, | ||||
|             { | ||||
|                 id: 'size', label: LANG.mediasize, | ||||
|                 btns: ['small', 'medium', 'large', 'original'] | ||||
|             } | ||||
|         ]; | ||||
|  | ||||
|         jQuery.each(opts, function (_, opt) { | ||||
|             var $p, $l; | ||||
|             $p = jQuery(document.createElement('p')) | ||||
|                 .attr('id', 'media__' + opt.id); | ||||
|  | ||||
|             if (dw_mediamanager.display === "2") { | ||||
|                 $p.hide(); | ||||
|             } | ||||
|  | ||||
|             $l = jQuery(document.createElement('label')) | ||||
|                 .text(opt.label); | ||||
|             $p.append($l); | ||||
|  | ||||
|             jQuery.each(opt.btns, function (i, text) { | ||||
|                 var $btn, $img; | ||||
|                 $btn = jQuery(document.createElement('button')) | ||||
|                     .addClass('button') | ||||
|                     .attr('id', "media__" + opt.id + "btn" + (i + 1)) | ||||
|                     .attr('title', LANG['media' + text]) | ||||
|                     .on('click', bind(dw_mediamanager.setOpt, opt.id)); | ||||
|  | ||||
|                 $img = jQuery(document.createElement('img')) | ||||
|                     .attr('src', DOKU_BASE + 'lib/images/media_' + opt.id + '_' + text + '.png'); | ||||
|  | ||||
|                 $btn.append($img); | ||||
|                 $p.append($btn); | ||||
|             }); | ||||
|  | ||||
|             dw_mediamanager.$popup.append($p); | ||||
|         }); | ||||
|  | ||||
|         // insert button | ||||
|         $insp = jQuery(document.createElement('p')); | ||||
|         dw_mediamanager.$popup.append($insp); | ||||
|  | ||||
|         $insbtn = jQuery(document.createElement('input')) | ||||
|             .attr('id', 'media__sendbtn') | ||||
|             .attr('type', 'button') | ||||
|             .addClass('button') | ||||
|             .val(LANG.mediainsert); | ||||
|         $insp.append($insbtn); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Insert the clicked image into the opener's textarea | ||||
|      * | ||||
|      * @author Andreas Gohr <andi@splitbrain.org> | ||||
|      * @author Dominik Eckelmann <eckelmann@cosmocode.de> | ||||
|      * @author Pierre Spring <pierre.spring@caillou.ch> | ||||
|      */ | ||||
|     insert: function (id) { | ||||
|         var opts, cb, edid, s; | ||||
|  | ||||
|         // set syntax options | ||||
|         dw_mediamanager.$popup.dialog('close'); | ||||
|  | ||||
|         opts = ''; | ||||
|  | ||||
|         if ({img: 1, swf: 1}[dw_mediamanager.ext] === 1) { | ||||
|  | ||||
|             if (dw_mediamanager.link === '4') { | ||||
|                 opts = '?linkonly'; | ||||
|             } else { | ||||
|  | ||||
|                 if (dw_mediamanager.link === "3" && dw_mediamanager.ext === 'img') { | ||||
|                     opts = '?nolink'; | ||||
|                 } else if (dw_mediamanager.link === "2" && dw_mediamanager.ext === 'img') { | ||||
|                     opts = '?direct'; | ||||
|                 } | ||||
|  | ||||
|                 s = parseInt(dw_mediamanager.size, 10); | ||||
|                 var size = s * 200; | ||||
|  | ||||
|                 if (s && s >= 1 && s < 4) { | ||||
|                     opts += (opts.length) ? '&' : '?'; | ||||
|                     opts += size; | ||||
|                     if (dw_mediamanager.ext === 'swf') { | ||||
|                         switch (s) { | ||||
|                             case 1: | ||||
|                                 opts += 'x62'; | ||||
|                                 break; | ||||
|                             case 2: | ||||
|                                 opts += 'x123'; | ||||
|                                 break; | ||||
|                             case 3: | ||||
|                                 opts += 'x185'; | ||||
|                                 break; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         edid = String.prototype.match.call(document.location, /&edid=([^&]+)/); | ||||
|         edid = edid ? edid[1] : 'wiki__text'; | ||||
|         cb = String.prototype.match.call(document.location, /&onselect=([^&]+)/); | ||||
|         cb = cb ? cb[1].replace(/[^\w]+/, '') : 'dw_mediamanager_item_select'; | ||||
|  | ||||
|         // arguments here only match the dw_mediamanager_item_select function, these will need to change if you override cb with onselect GET param | ||||
|         opener[cb](edid, id, opts, dw_mediamanager.align, dw_mediamanager.keepopen); | ||||
|         if (!dw_mediamanager.keepopen) { | ||||
|             window.close(); | ||||
|         } | ||||
|         opener.focus(); | ||||
|         return false; | ||||
|     }, | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Prefills the wikiname. | ||||
|      * | ||||
|      * @author Andreas Gohr <andi@splitbrain.org> | ||||
|      */ | ||||
|     suggest: function () { | ||||
|         var $file, $name, text; | ||||
|  | ||||
|         $file = jQuery(this); | ||||
|         $name = jQuery('#upload__name'); | ||||
|  | ||||
|         if ($name.val() != '') return; | ||||
|  | ||||
|         if (!$file.length || !$name.length) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         text = $file.val(); | ||||
|         text = text.substr(text.lastIndexOf('/') + 1); | ||||
|         text = text.substr(text.lastIndexOf('\\') + 1); | ||||
|         $name.val(text); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * list the content of a namespace using AJAX | ||||
|      * | ||||
|      * @author Andreas Gohr <andi@splitbrain.org> | ||||
|      * @author Pierre Spring <pierre.spring@caillou.ch> | ||||
|      */ | ||||
|     list: function (event) { | ||||
|         var $link, $content, params; | ||||
|  | ||||
|         if (event) { | ||||
|             event.preventDefault(); | ||||
|         } | ||||
|  | ||||
|         jQuery('div.success, div.info, div.error, div.notify').remove(); | ||||
|  | ||||
|         $link = jQuery(this); | ||||
|  | ||||
|         //popup | ||||
|         $content = jQuery('#media__content'); | ||||
|  | ||||
|         if ($content.length === 0) { | ||||
|             //fullscreen media manager | ||||
|             $content = jQuery('div.filelist'); | ||||
|  | ||||
|             if ($link.hasClass('idx_dir')) { | ||||
|                 //changing namespace | ||||
|                 jQuery('div.file').empty(); | ||||
|                 jQuery('div.namespaces .selected').removeClass('selected'); | ||||
|                 $link.addClass('selected'); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         params = 'call=medialist&'; | ||||
|  | ||||
|         if ($link[0].search) { | ||||
|             params += $link[0].search.substr(1); | ||||
|         } else if ($link.is('form')) { | ||||
|             params += dw_mediamanager.form_params($link); | ||||
|         } else if ($link.closest('form').length > 0) { | ||||
|             params += dw_mediamanager.form_params($link.closest('form')); | ||||
|         } | ||||
|  | ||||
|         // fetch the subtree | ||||
|         dw_mediamanager.update_content($content, params); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Returns form parameters | ||||
|      * | ||||
|      * @author Kate Arzamastseva <pshns@ukr.net> | ||||
|      */ | ||||
|     form_params: function ($form) { | ||||
|         if (!$form.length) return; | ||||
|  | ||||
|         var action = ''; | ||||
|         var i = $form[0].action.indexOf('?'); | ||||
|         if (i >= 0) { | ||||
|             action = $form[0].action.substr(i + 1); | ||||
|         } | ||||
|         return action + '&' + $form.serialize(); | ||||
|     }, | ||||
|  | ||||
|     set_fileview_list: function (new_type) { | ||||
|         dw_mediamanager.set_fileview_opt(['list', 'listType', function (new_type) { | ||||
|             jQuery('div.filelist div.panelContent ul') | ||||
|                 .toggleClass('rows', new_type === 'rows') | ||||
|                 .toggleClass('thumbs', new_type === 'thumbs'); | ||||
|         }], new_type); | ||||
|  | ||||
|         // FIXME: Move to onchange handler (opt[2])? | ||||
|         dw_mediamanager.resize(); | ||||
|     }, | ||||
|  | ||||
|     set_fileview_sort: function (new_sort) { | ||||
|         dw_mediamanager.set_fileview_opt(['sort', 'sortBy', function (new_sort) { | ||||
|             // FIXME | ||||
|         }], new_sort); | ||||
|     }, | ||||
|  | ||||
|     set_fileview_opt: function (opt, new_val) { | ||||
|         if (typeof new_val === 'undefined') { | ||||
|             new_val = jQuery('form.options li.' + opt[1] + ' input') | ||||
|                 .filter(':checked').val(); | ||||
|             // if new_val is still undefined (because form.options is not in active tab), set to most spacious option | ||||
|             if (typeof new_val === 'undefined') { | ||||
|                 new_val = 'thumbs'; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (new_val !== dw_mediamanager.view_opts[opt[0]]) { | ||||
|             opt[2](new_val); | ||||
|  | ||||
|             DokuCookie.setValue(opt[0], new_val); | ||||
|  | ||||
|             dw_mediamanager.view_opts[opt[0]] = new_val; | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Lists the content of the right column (image details) using AJAX | ||||
|      * | ||||
|      * @author Kate Arzamastseva <pshns@ukr.net> | ||||
|      */ | ||||
|     details: function (event) { | ||||
|         var $link, $content, params, update_list; | ||||
|         $link = jQuery(this); | ||||
|         event.preventDefault(); | ||||
|  | ||||
|         jQuery('div.success, div.info, div.error, div.notify').remove(); | ||||
|  | ||||
|         if ($link[0].id == 'mediamanager__btn_delete' && !confirm(LANG.del_confirm)) { | ||||
|             return false; | ||||
|         } | ||||
|         if ($link[0].id == 'mediamanager__btn_restore' && !confirm(LANG.restore_confirm)) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         $content = jQuery('div.file'); | ||||
|         params = 'call=mediadetails&'; | ||||
|  | ||||
|         if ($link[0].search) { | ||||
|             params += $link[0].search.substr(1); | ||||
|         } else if ($link.is('form')) { | ||||
|             params += dw_mediamanager.form_params($link); | ||||
|         } else if ($link.closest('form').length > 0) { | ||||
|             params += dw_mediamanager.form_params($link.closest('form')); | ||||
|         } | ||||
|  | ||||
|         update_list = ($link[0].id == 'mediamanager__btn_delete' || | ||||
|         $link[0].id == 'mediamanager__btn_restore'); | ||||
|  | ||||
|         dw_mediamanager.update_content($content, params, update_list); | ||||
|     }, | ||||
|  | ||||
|     update_content: function ($content, params, update_list) { | ||||
|         var $container; | ||||
|  | ||||
|         jQuery.post( | ||||
|             DOKU_BASE + 'lib/exe/ajax.php', | ||||
|             params, | ||||
|             function (data) { | ||||
|                 dw_mediamanager.$resizables().resizable('destroy'); | ||||
|  | ||||
|                 if (update_list) { | ||||
|                     dw_mediamanager.list.call(jQuery('#mediamanager__page').find('form.options button[type="submit"]')[0]); | ||||
|                 } | ||||
|  | ||||
|                 $content.html(data); | ||||
|  | ||||
|                 dw_mediamanager.prepare_content($content); | ||||
|                 dw_mediamanager.updatehide(); | ||||
|  | ||||
|                 dw_mediamanager.update_resizable(); | ||||
|                 dw_behaviour.revisionBoxHandler(); | ||||
|  | ||||
|                 // Make sure that the list view style stays the same | ||||
|                 dw_mediamanager.set_fileview_list(dw_mediamanager.view_opts.list); | ||||
|  | ||||
|                 dw_mediamanager.image_diff(); | ||||
|                 dw_mediamanager.init_ajax_uploader(); | ||||
|                 dw_mediamanager.init_options(); | ||||
|  | ||||
|             }, | ||||
|             'html' | ||||
|         ); | ||||
|         $container = $content.find('div.panelContent'); | ||||
|         if ($container.length === 0) { | ||||
|             $container = $content; | ||||
|         } | ||||
|         $container.html('<img src="' + DOKU_BASE + 'lib/images/throbber.gif" alt="..." class="load" />'); | ||||
|     }, | ||||
|  | ||||
|     window_resize: function () { | ||||
|         dw_mediamanager.resize(); | ||||
|  | ||||
|         dw_mediamanager.opacity_slider(); | ||||
|         dw_mediamanager.portions_slider(); | ||||
|     }, | ||||
|  | ||||
|     $resizables: function () { | ||||
|         return jQuery('#mediamanager__page').find('div.namespaces, div.filelist'); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Updates mediamanager layout | ||||
|      * | ||||
|      * @author Kate Arzamastseva <pshns@ukr.net> | ||||
|      */ | ||||
|     update_resizable: function () { | ||||
|         var $resizables = dw_mediamanager.$resizables(); | ||||
|  | ||||
|         $resizables.resizable({ | ||||
|             handles: (jQuery('html[dir=rtl]').length ? 'w' : 'e'), | ||||
|             resize: function (event, ui) { | ||||
|                 var $page = jQuery('#mediamanager__page'); | ||||
|                 var widthFull = $page.width(); | ||||
|                 var widthResizables = 0; | ||||
|                 $resizables.each(function () { | ||||
|                     widthResizables += jQuery(this).width(); | ||||
|                 }); | ||||
|                 var $filePanel = $page.find('div.panel.file'); | ||||
|  | ||||
|                 // set max width of resizable column | ||||
|                 var widthOtherResizable = widthResizables - jQuery(this).width(); | ||||
|                 var minWidthNonResizable = parseFloat($filePanel.css("min-width")); | ||||
|                 var maxWidth = widthFull - (widthOtherResizable + minWidthNonResizable) - 1; | ||||
|                 $resizables.resizable("option", "maxWidth", maxWidth); | ||||
|  | ||||
|                 // width of file panel in % = 100% - width of resizables in % | ||||
|                 // this calculates with 99.9 and not 100 to overcome rounding errors | ||||
|                 var relWidthNonResizable = 99.9 - (100 * widthResizables / widthFull); | ||||
|                 // set width of file panel | ||||
|                 $filePanel.width(relWidthNonResizable + '%'); | ||||
|  | ||||
|                 dw_mediamanager.resize(); | ||||
|  | ||||
|                 dw_mediamanager.opacity_slider(); | ||||
|                 dw_mediamanager.portions_slider(); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         dw_mediamanager.resize(); | ||||
|     }, | ||||
|  | ||||
|     resize: function () { | ||||
|         var $contents = jQuery('#mediamanager__page').find('div.panelContent'), | ||||
|             height = jQuery(window).height() - jQuery(document.body).height() + | ||||
|                 Math.max.apply(null, jQuery.map($contents, function (v) { | ||||
|                     return jQuery(v).height(); | ||||
|                 })); | ||||
|  | ||||
|         // If the screen is too small, don’t try to resize | ||||
|         if (height < dw_mediamanager.minHeights[dw_mediamanager.view_opts.list]) { | ||||
|             $contents.add(dw_mediamanager.$resizables()).height('auto'); | ||||
|         } else { | ||||
|             $contents.height(height); | ||||
|             dw_mediamanager.$resizables().each(function () { | ||||
|                 var $this = jQuery(this); | ||||
|                 $this.height(height + $this.find('div.panelContent').offset().top - $this.offset().top); | ||||
|             }); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Prints 'select' for image difference representation type | ||||
|      * | ||||
|      * @author Kate Arzamastseva <pshns@ukr.net> | ||||
|      */ | ||||
|     image_diff: function () { | ||||
|         if (jQuery('#mediamanager__difftype').length) return; | ||||
|  | ||||
|         var $form = jQuery('#mediamanager__form_diffview'); | ||||
|         if (!$form.length) return; | ||||
|  | ||||
|         var $label = jQuery(document.createElement('label')); | ||||
|         $label.append('<span>' + LANG.media_diff + '</span> '); | ||||
|         var $select = jQuery(document.createElement('select')) | ||||
|             .attr('id', 'mediamanager__difftype') | ||||
|             .attr('name', 'difftype') | ||||
|             .change(dw_mediamanager.change_diff_type); | ||||
|         $select.append(new Option(LANG.media_diff_both, "both")); | ||||
|         $select.append(new Option(LANG.media_diff_opacity, "opacity")); | ||||
|         $select.append(new Option(LANG.media_diff_portions, "portions")); | ||||
|         $label.append($select); | ||||
|         $form.append($label); | ||||
|  | ||||
|         // for IE | ||||
|         var select = document.getElementById('mediamanager__difftype'); | ||||
|         select.options[0].text = LANG.media_diff_both; | ||||
|         select.options[1].text = LANG.media_diff_opacity; | ||||
|         select.options[2].text = LANG.media_diff_portions; | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Handles selection of image difference representation type | ||||
|      * | ||||
|      * @author Kate Arzamastseva <pshns@ukr.net> | ||||
|      */ | ||||
|     change_diff_type: function () { | ||||
|         var $select = jQuery('#mediamanager__difftype'); | ||||
|         var $content = jQuery('#mediamanager__diff'); | ||||
|  | ||||
|         var params = dw_mediamanager.form_params($select.closest('form')) + '&call=mediadiff'; | ||||
|         jQuery.post( | ||||
|             DOKU_BASE + 'lib/exe/ajax.php', | ||||
|             params, | ||||
|             function (data) { | ||||
|                 $content.html(data); | ||||
|                 dw_mediamanager.portions_slider(); | ||||
|                 dw_mediamanager.opacity_slider(); | ||||
|             }, | ||||
|             'html' | ||||
|         ); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Sets options for opacity diff slider | ||||
|      * | ||||
|      * @author Kate Arzamastseva <pshns@ukr.net> | ||||
|      */ | ||||
|     opacity_slider: function () { | ||||
|         var $diff = jQuery("#mediamanager__diff"); | ||||
|         var $slider = $diff.find("div.slider"); | ||||
|         if (!$slider.length) return; | ||||
|  | ||||
|         var $image = $diff.find('div.imageDiff.opacity div.image1 img'); | ||||
|         if (!$image.length) return; | ||||
|         $slider.width($image.width() - 20); | ||||
|  | ||||
|         $slider.slider(); | ||||
|         $slider.slider("option", "min", 0); | ||||
|         $slider.slider("option", "max", 0.999); | ||||
|         $slider.slider("option", "step", 0.001); | ||||
|         $slider.slider("option", "value", 0.5); | ||||
|         $slider.on("slide", function (event, ui) { | ||||
|             jQuery('#mediamanager__diff').find('div.imageDiff.opacity div.image2 img').css({opacity: $slider.slider("option", "value")}); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Sets options for red line diff slider | ||||
|      * | ||||
|      * @author Kate Arzamastseva <pshns@ukr.net> | ||||
|      */ | ||||
|     portions_slider: function () { | ||||
|         var $diff = jQuery("#mediamanager__diff"); | ||||
|         if (!$diff.length) return; | ||||
|  | ||||
|         var $image1 = $diff.find('div.imageDiff.portions div.image1 img'); | ||||
|         var $image2 = $diff.find('div.imageDiff.portions div.image2 img'); | ||||
|         if (!$image1.length || !$image2.length) return; | ||||
|  | ||||
|         $diff.width('100%'); | ||||
|         $image2.parent().width('97%'); | ||||
|         $image1.width('100%'); | ||||
|         $image2.width('100%'); | ||||
|  | ||||
|         if ($image1.width() < $diff.width()) { | ||||
|             $diff.width($image1.width()); | ||||
|         } | ||||
|  | ||||
|         $image2.parent().width('50%'); | ||||
|         $image2.width($image1.width()); | ||||
|         $image1.width($image1.width()); | ||||
|  | ||||
|         var $slider = $diff.find("div.slider"); | ||||
|         if (!$slider.length) return; | ||||
|         $slider.width($image1.width() - 20); | ||||
|  | ||||
|         $slider.slider(); | ||||
|         $slider.slider("option", "min", 0); | ||||
|         $slider.slider("option", "max", 97); | ||||
|         $slider.slider("option", "step", 1); | ||||
|         $slider.slider("option", "value", 50); | ||||
|         $slider.on("slide", function (event, ui) { | ||||
|             jQuery('#mediamanager__diff').find('div.imageDiff.portions div.image2').css({width: $slider.slider("option", "value") + '%'}); | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Parse a URI query string to an associative array | ||||
|      * | ||||
|      * @author Kate Arzamastseva <pshns@ukr.net> | ||||
|      */ | ||||
|     params_toarray: function (str) { | ||||
|         var vars = [], hash; | ||||
|         var hashes = str.split('&'); | ||||
|         for (var i = 0; i < hashes.length; i++) { | ||||
|             hash = hashes[i].split('='); | ||||
|             vars[decodeURIComponent(hash[0])] = decodeURIComponent(hash[1]); | ||||
|         } | ||||
|         return vars; | ||||
|     }, | ||||
|  | ||||
|     init_ajax_uploader: function () { | ||||
|         if (!jQuery('#mediamanager__uploader').length) return; | ||||
|         if (jQuery('.qq-upload-list').length) return; | ||||
|  | ||||
|         var params = dw_mediamanager.form_params(jQuery('#dw__upload')) + '&call=mediaupload'; | ||||
|         params = dw_mediamanager.params_toarray(params); | ||||
|  | ||||
|         var uploader = new qq.FileUploaderExtended({ | ||||
|             element: document.getElementById('mediamanager__uploader'), | ||||
|             action: DOKU_BASE + 'lib/exe/ajax.php', | ||||
|             params: params | ||||
|         }); | ||||
|     }, | ||||
|  | ||||
|     prepare_content: function ($content) { | ||||
|         // hide syntax example | ||||
|         $content.find('div.example:visible').hide(); | ||||
|         // toggle list of allowed mime types | ||||
|         $content.find('a.allowedmime').on('click', function (event) { | ||||
|             event.preventDefault(); | ||||
|             $toggle = jQuery(this); | ||||
|             $list = $toggle.next('span'); | ||||
|             $list.toggle(); | ||||
|         }).next('span').hide(); | ||||
|  | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * shows the popup for a image link | ||||
|      */ | ||||
|     select: function (event) { | ||||
|         var $link, id, dot, ext; | ||||
|  | ||||
|         event.preventDefault(); | ||||
|  | ||||
|         $link = jQuery(this); | ||||
|         id = $link.attr('id').substr(2); | ||||
|  | ||||
|         if (!opener) { | ||||
|             // if we don't run in popup display example | ||||
|             // the id's are a bit wierd and jQuery('#ex_wiki_dokuwiki-128.png') | ||||
|             // will not be found by Sizzle (the CSS Selector Engine | ||||
|             // used by jQuery), hence the document.getElementById() call | ||||
|             jQuery(document.getElementById('ex_' + id.replace(/:/g, '_').replace(/^_/, ''))).dw_toggle(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         dw_mediamanager.ext = false; | ||||
|         dot = id.lastIndexOf("."); | ||||
|  | ||||
|         if (-1 === dot) { | ||||
|             dw_mediamanager.insert(id); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         ext = id.substr(dot); | ||||
|  | ||||
|         if ({'.jpg': 1, '.jpeg': 1, '.png': 1, '.gif': 1, '.swf': 1}[ext] !== 1) { | ||||
|             dw_mediamanager.insert(id); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // remove old callback from the insert button and set the new one. | ||||
|         var $sendbtn = jQuery('#media__sendbtn'); | ||||
|         $sendbtn.off().on('click', bind(dw_mediamanager.insert, id)); | ||||
|  | ||||
|         dw_mediamanager.unforbid('ext'); | ||||
|         if (ext === '.swf') { | ||||
|             dw_mediamanager.ext = 'swf'; | ||||
|             dw_mediamanager.forbid('ext', { | ||||
|                 link: ['1', '2'], | ||||
|                 size: ['4'] | ||||
|             }); | ||||
|         } else { | ||||
|             dw_mediamanager.ext = 'img'; | ||||
|         } | ||||
|  | ||||
|         // Set to defaults | ||||
|         dw_mediamanager.setOpt('link'); | ||||
|         dw_mediamanager.setOpt('align'); | ||||
|         dw_mediamanager.setOpt('size'); | ||||
|  | ||||
|         // toggle buttons for detail and linked image, original size | ||||
|         jQuery('#media__linkbtn1, #media__linkbtn2, #media__sizebtn4') | ||||
|             .toggle(dw_mediamanager.ext === 'img'); | ||||
|  | ||||
|         dw_mediamanager.$popup.dialog('open'); | ||||
|  | ||||
|         $sendbtn.focus(); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Deletion confirmation dialog to the delete buttons. | ||||
|      * | ||||
|      * @author Michael Klier <chi@chimeric.de> | ||||
|      * @author Pierre Spring <pierre.spring@caillou.ch> | ||||
|      */ | ||||
|     confirmattach: function (e) { | ||||
|         if (!confirm(LANG.del_confirm + "\n" + jQuery(this).attr('title'))) { | ||||
|             e.preventDefault(); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Creates checkboxes for additional options | ||||
|      * | ||||
|      * @author Andreas Gohr <andi@splitbrain.org> | ||||
|      * @author Pierre Spring <pierre.spring@caillou.ch> | ||||
|      */ | ||||
|     attachoptions: function () { | ||||
|         var $obj, opts; | ||||
|  | ||||
|         $obj = jQuery('#media__opts'); | ||||
|         if ($obj.length === 0) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         opts = []; | ||||
|         // keep open | ||||
|         if (opener) { | ||||
|             opts.push(['keepopen', 'keepopen']); | ||||
|         } | ||||
|         opts.push(['hide', 'hidedetails']); | ||||
|  | ||||
|         jQuery.each(opts, | ||||
|             function (_, opt) { | ||||
|                 var $box, $lbl; | ||||
|                 $box = jQuery(document.createElement('input')) | ||||
|                     .attr('type', 'checkbox') | ||||
|                     .attr('id', 'media__' + opt[0]) | ||||
|                     .on('click', bind(dw_mediamanager.toggleOption, opt[0])); | ||||
|  | ||||
|                 if (DokuCookie.getValue(opt[0])) { | ||||
|                     $box.prop('checked', true); | ||||
|                     dw_mediamanager[opt[0]] = true; | ||||
|                 } | ||||
|  | ||||
|                 $lbl = jQuery(document.createElement('label')) | ||||
|                     .attr('for', 'media__' + opt[0]) | ||||
|                     .text(LANG[opt[1]]); | ||||
|  | ||||
|                 $obj.append($box, $lbl, document.createElement('br')); | ||||
|             }); | ||||
|  | ||||
|         dw_mediamanager.updatehide(); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Generalized toggler | ||||
|      * | ||||
|      * @author Pierre Spring <pierre.spring@caillou.ch> | ||||
|      */ | ||||
|     toggleOption: function (variable) { | ||||
|         if (jQuery(this).prop('checked')) { | ||||
|             DokuCookie.setValue(variable, 1); | ||||
|             dw_mediamanager[variable] = true; | ||||
|         } else { | ||||
|             DokuCookie.setValue(variable, ''); | ||||
|             dw_mediamanager[variable] = false; | ||||
|         } | ||||
|         if (variable === 'hide') { | ||||
|             dw_mediamanager.updatehide(); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Sets the visibility of the image details accordingly to the | ||||
|      * chosen hide state | ||||
|      * | ||||
|      * @author Andreas Gohr <andi@splitbrain.org> | ||||
|      */ | ||||
|     updatehide: function () { | ||||
|         jQuery('#media__content').find('div.detail').dw_toggle(!dw_mediamanager.hide); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * set media insertion option | ||||
|      * | ||||
|      * @author Dominik Eckelmann <eckelmann@cosmocode.de> | ||||
|      */ | ||||
|     setOpt: function (opt, e) { | ||||
|         var val, i; | ||||
|         if (typeof e !== 'undefined') { | ||||
|             val = this.id.substring(this.id.length - 1); | ||||
|         } else { | ||||
|             val = dw_mediamanager.getOpt(opt); | ||||
|         } | ||||
|  | ||||
|         if (val === false) { | ||||
|             DokuCookie.setValue(opt, ''); | ||||
|             dw_mediamanager[opt] = false; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (opt === 'link') { | ||||
|             if (val !== '4' && dw_mediamanager.link === '4') { | ||||
|                 dw_mediamanager.unforbid('linkonly'); | ||||
|                 dw_mediamanager.setOpt('align'); | ||||
|                 dw_mediamanager.setOpt('size'); | ||||
|             } else if (val === '4') { | ||||
|                 dw_mediamanager.forbid('linkonly', {align: false, size: false}); | ||||
|             } | ||||
|  | ||||
|             jQuery("#media__size, #media__align").dw_toggle(val !== '4'); | ||||
|         } | ||||
|  | ||||
|         DokuCookie.setValue(opt, val); | ||||
|         dw_mediamanager[opt] = val; | ||||
|  | ||||
|         for (i = 1; i <= 4; i++) { | ||||
|             jQuery("#media__" + opt + "btn" + i).removeClass('selected'); | ||||
|         } | ||||
|         jQuery('#media__' + opt + 'btn' + val).addClass('selected'); | ||||
|     }, | ||||
|  | ||||
|     unforbid: function (group) { | ||||
|         delete dw_mediamanager.forbidden_opts[group]; | ||||
|     }, | ||||
|  | ||||
|     forbid: function (group, forbids) { | ||||
|         dw_mediamanager.forbidden_opts[group] = forbids; | ||||
|     }, | ||||
|  | ||||
|     allowedOpt: function (opt, val) { | ||||
|         var ret = true; | ||||
|         jQuery.each(dw_mediamanager.forbidden_opts, | ||||
|             function (_, forbids) { | ||||
|                 ret = forbids[opt] !== false && | ||||
|                     jQuery.inArray(val, forbids[opt]) === -1; | ||||
|                 return ret; | ||||
|             }); | ||||
|         return ret; | ||||
|     }, | ||||
|  | ||||
|     getOpt: function (opt) { | ||||
|         var allowed = bind(dw_mediamanager.allowedOpt, opt); | ||||
|  | ||||
|         // Current value | ||||
|         if (dw_mediamanager[opt] !== false && allowed(dw_mediamanager[opt])) { | ||||
|             return dw_mediamanager[opt]; | ||||
|         } | ||||
|  | ||||
|         // From cookie | ||||
|         if (DokuCookie.getValue(opt) && allowed(DokuCookie.getValue(opt))) { | ||||
|             return DokuCookie.getValue(opt); | ||||
|         } | ||||
|  | ||||
|         // size default | ||||
|         if (opt === 'size' && allowed('2')) { | ||||
|             return '2'; | ||||
|         } | ||||
|  | ||||
|         // Whatever is allowed, and be it false | ||||
|         return jQuery.grep(['1', '2', '3', '4'], allowed)[0] || false; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Default implementation for the media manager's select action | ||||
|  * | ||||
|  * Can be overriden with the onselect URL parameter. Is called on the opener context | ||||
|  * | ||||
|  * @param {string} edid | ||||
|  * @param {string} mediaid | ||||
|  * @param {string} opts | ||||
|  * @param {string} align [none, left, center, right] | ||||
|  */ | ||||
| function dw_mediamanager_item_select(edid, mediaid, opts, align, keepopen) { | ||||
|     var alignleft = ''; | ||||
|     var alignright = ''; | ||||
|  | ||||
|     // Get the 2 characters after the cursor to check if we're currently inside an image tag | ||||
|     var cursorInImageTag = false; | ||||
|     var textArea = jQuery('#' + edid)[0]; | ||||
|     var selection = DWgetSelection(textArea); | ||||
|     selection.end = selection.end + 2; | ||||
|     var charsAfterCursor = selection.getText(); | ||||
|     if (charsAfterCursor === '}}') { | ||||
|         cursorInImageTag = true; | ||||
|     } | ||||
|  | ||||
|     if (align !== '1') { | ||||
|         alignleft = align === '2' ? '' : ' '; | ||||
|         alignright = align === '4' ? '' : ' '; | ||||
|     } | ||||
|     if (keepopen && cursorInImageTag) { | ||||
|         selection.start = selection.start + 2; | ||||
|         DWsetSelection(selection); | ||||
|     } | ||||
|     insertTags(edid, '{{' + alignleft + mediaid + opts + alignright + '|', '}}', ''); | ||||
| } | ||||
|  | ||||
| jQuery(dw_mediamanager.init); | ||||
							
								
								
									
										201
									
								
								ap23/web/doku/lib/scripts/page.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,201 @@ | ||||
| /** | ||||
|  * Page behaviours | ||||
|  * | ||||
|  * This class adds various behaviours to the rendered page | ||||
|  */ | ||||
| dw_page = { | ||||
|     /** | ||||
|      * initialize page behaviours | ||||
|      */ | ||||
|     init: function(){ | ||||
|         dw_page.sectionHighlight(); | ||||
|         dw_page.currentIDHighlight(); | ||||
|         jQuery('a.fn_top').on('mouseover', dw_page.footnoteDisplay); | ||||
|         dw_page.makeToggle('#dw__toc h3','#dw__toc > div'); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Highlight the section when hovering over the appropriate section edit button | ||||
|      * | ||||
|      * @author Andreas Gohr <andi@splitbrain.org> | ||||
|      */ | ||||
|     sectionHighlight: function() { | ||||
|         jQuery('form.btn_secedit') | ||||
|             .on('mouseover', function(){ | ||||
|                 var $tgt = jQuery(this).parent(), | ||||
|                     nr = $tgt.attr('class').match(/(\s+|^)editbutton_(\d+)(\s+|$)/)[2], | ||||
|                     $highlight = jQuery(),                                             // holder for elements in the section to be highlighted | ||||
|                     $highlightWrap = jQuery('<div class="section_highlight"></div>');  // section highlight wrapper | ||||
|  | ||||
|                 // Walk the dom tree in reverse to find the sibling which is or contains the section edit marker | ||||
|                 while($tgt.length > 0 && !($tgt.hasClass('sectionedit' + nr) || $tgt.find('.sectionedit' + nr).length)) { | ||||
|                     $tgt = $tgt.prev(); | ||||
|                     $highlight = $highlight.add($tgt); | ||||
|                 } | ||||
|               // insert the section highlight wrapper before the last element added to $highlight | ||||
|               $highlight.filter(':last').before($highlightWrap); | ||||
|               // and move the elements to be highlighted inside the section highlight wrapper | ||||
|               $highlight.detach().appendTo($highlightWrap); | ||||
|             }) | ||||
|             .on('mouseout', function(){ | ||||
|                 // find the section highlight wrapper... | ||||
|                 var $highlightWrap = jQuery('.section_highlight'); | ||||
|                 // ...move its children in front of it (as siblings)... | ||||
|                 $highlightWrap.before($highlightWrap.children().detach()); | ||||
|                 // ...and remove the section highlight wrapper | ||||
|                 $highlightWrap.detach(); | ||||
|             }); | ||||
|     }, | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Highlight internal link pointing to current page | ||||
|      * | ||||
|      * @author Henry Pan <dokuwiki@phy25.com> | ||||
|      */ | ||||
|     currentIDHighlight: function(){ | ||||
|         jQuery('a.wikilink1, a.wikilink2').filter('[data-wiki-id="'+JSINFO.id+'"]').wrap('<span class="curid"></div>'); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Create/get a insitu popup used by the footnotes | ||||
|      * | ||||
|      * @param target - the DOM element at which the popup should be aligned at | ||||
|      * @param popup_id - the ID of the (new) DOM popup | ||||
|      * @return the Popup jQuery object | ||||
|      */ | ||||
|     insituPopup: function(target, popup_id) { | ||||
|         // get or create the popup div | ||||
|         var $fndiv = jQuery('#' + popup_id); | ||||
|  | ||||
|         // popup doesn't exist, yet -> create it | ||||
|         if($fndiv.length === 0){ | ||||
|             $fndiv = jQuery(document.createElement('div')) | ||||
|                 .attr('id', popup_id) | ||||
|                 .addClass('insitu-footnote JSpopup') | ||||
|                 .attr('aria-hidden', 'true') | ||||
|                 .on('mouseleave', function () {jQuery(this).hide().attr('aria-hidden', 'true');}) | ||||
|                 .attr('role', 'tooltip'); | ||||
|             jQuery('.dokuwiki:first').append($fndiv); | ||||
|         } | ||||
|  | ||||
|         // position() does not support hidden elements | ||||
|         $fndiv.show().position({ | ||||
|             my: 'left top', | ||||
|             at: 'left center', | ||||
|             of: target | ||||
|         }).hide(); | ||||
|  | ||||
|         return $fndiv; | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Display an insitu footnote popup | ||||
|      * | ||||
|      * @author Andreas Gohr <andi@splitbrain.org> | ||||
|      * @author Chris Smith <chris@jalakai.co.uk> | ||||
|      * @author Anika Henke <anika@selfthinker.org> | ||||
|      */ | ||||
|     footnoteDisplay: function () { | ||||
|         var $content = jQuery(jQuery(this).attr('href')) // Footnote text anchor | ||||
|                       .parent().siblings('.content').clone(); | ||||
|  | ||||
|         if (!$content.length) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // prefix ids on any elements with "insitu__" to ensure they remain unique | ||||
|         jQuery('[id]', $content).each(function(){ | ||||
|             var id = jQuery(this).attr('id'); | ||||
|             jQuery(this).attr('id', 'insitu__' + id); | ||||
|         }); | ||||
|  | ||||
|         var content = $content.html().trim(); | ||||
|         // now put the content into the wrapper | ||||
|         dw_page.insituPopup(this, 'insitu__fn').html(content) | ||||
|         .show().attr('aria-hidden', 'false'); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Makes an element foldable by clicking its handle | ||||
|      * | ||||
|      * This is used for the TOC toggling, but can be used for other elements | ||||
|      * as well. A state indicator is inserted into the handle and can be styled | ||||
|      * by CSS. | ||||
|      * | ||||
|      * To properly reserve space for the expanded element, the sliding animation is | ||||
|      * done on the children of the content. To make that look good and to make sure aria | ||||
|      * attributes are assigned correctly, it's recommended to make sure that the content | ||||
|      * element contains a single child element only. | ||||
|      * | ||||
|      * @param {selector} handle What should be clicked to toggle | ||||
|      * @param {selector} content This element will be toggled | ||||
|      * @param {int} state initial state (-1 = open, 1 = closed) | ||||
|      */ | ||||
|     makeToggle: function(handle, content, state){ | ||||
|         var $handle, $content, $clicky, $child, setClicky; | ||||
|         $handle = jQuery(handle); | ||||
|         if(!$handle.length) return; | ||||
|         $content = jQuery(content); | ||||
|         if(!$content.length) return; | ||||
|  | ||||
|         // we animate the children | ||||
|         $child = $content.children(); | ||||
|  | ||||
|         // class/display toggling | ||||
|         setClicky = function(hiding){ | ||||
|             if(hiding){ | ||||
|                 $clicky.html('<span>+</span>'); | ||||
|                 $handle.addClass('closed'); | ||||
|                 $handle.removeClass('open'); | ||||
|             }else{ | ||||
|                 $clicky.html('<span>−</span>'); | ||||
|                 $handle.addClass('open'); | ||||
|                 $handle.removeClass('closed'); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         $handle[0].setState = function(state){ | ||||
|             var hidden; | ||||
|             if(!state) state = 1; | ||||
|  | ||||
|             // Assert that content instantly takes the whole space | ||||
|             $content.css('min-height', $content.height()).show(); | ||||
|  | ||||
|             // stop any running animation | ||||
|             $child.stop(true, true); | ||||
|  | ||||
|             // was a state given or do we toggle? | ||||
|             if(state === -1) { | ||||
|                 hidden = false; | ||||
|             } else if(state === 1) { | ||||
|                 hidden = true; | ||||
|             } else { | ||||
|                 hidden = $child.is(':hidden'); | ||||
|             } | ||||
|  | ||||
|             // update the state | ||||
|             setClicky(!hidden); | ||||
|  | ||||
|             // Start animation and assure that $toc is hidden/visible | ||||
|             $child.dw_toggle(hidden, function () { | ||||
|                 $content.toggle(hidden); | ||||
|                 $content.attr('aria-expanded', hidden); | ||||
|                 $content.css('min-height',''); // remove min-height again | ||||
|             }, true); | ||||
|         }; | ||||
|  | ||||
|         // the state indicator | ||||
|         $clicky = jQuery(document.createElement('strong')); | ||||
|  | ||||
|         // click function | ||||
|         $handle.css('cursor','pointer') | ||||
|                .on('click', $handle[0].setState) | ||||
|                .prepend($clicky); | ||||
|  | ||||
|         // initial state | ||||
|         $handle[0].setState(state); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| jQuery(dw_page.init); | ||||
							
								
								
									
										191
									
								
								ap23/web/doku/lib/scripts/qsearch.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,191 @@ | ||||
| /** | ||||
|  * AJAX functions for the pagename quicksearch | ||||
|  * | ||||
|  * @license  GPL2 (http://www.gnu.org/licenses/gpl.html) | ||||
|  * @author   Andreas Gohr <andi@splitbrain.org> | ||||
|  * @author   Adrian Lang <lang@cosmocode.de> | ||||
|  * @author   Michal Rezler <m.rezler@centrum.cz> | ||||
|  */ | ||||
| jQuery.fn.dw_qsearch = function (overrides) { | ||||
|  | ||||
|     var dw_qsearch = { | ||||
|  | ||||
|         output: '#qsearch__out', | ||||
|  | ||||
|         $inObj: this, | ||||
|         $outObj: null, | ||||
|         timer: null, | ||||
|         curRequest: null, | ||||
|  | ||||
|         /** | ||||
|          * initialize the quick search | ||||
|          * | ||||
|          * Attaches the event handlers | ||||
|          * | ||||
|          */ | ||||
|         init: function () { | ||||
|             var do_qsearch; | ||||
|  | ||||
|             dw_qsearch.$outObj = jQuery(dw_qsearch.output); | ||||
|  | ||||
|             // objects found? | ||||
|             if (dw_qsearch.$inObj.length === 0 || | ||||
|                 dw_qsearch.$outObj.length === 0) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             // attach eventhandler to search field | ||||
|             do_qsearch = function () { | ||||
|                 // abort any previous request | ||||
|                 if (dw_qsearch.curRequest != null) { | ||||
|                     dw_qsearch.curRequest.abort(); | ||||
|                 } | ||||
|                 var value = dw_qsearch.getSearchterm(); | ||||
|                 if (value === '') { | ||||
|                     dw_qsearch.clear_results(); | ||||
|                     return; | ||||
|                 } | ||||
|                 dw_qsearch.$inObj.parents('form').addClass('searching'); | ||||
|                 dw_qsearch.curRequest = jQuery.post( | ||||
|                     DOKU_BASE + 'lib/exe/ajax.php', | ||||
|                     { | ||||
|                         call: 'qsearch', | ||||
|                         q: encodeURI(value) | ||||
|                     }, | ||||
|                     dw_qsearch.onCompletion, | ||||
|                     'html' | ||||
|                 ); | ||||
|             }; | ||||
|  | ||||
|             dw_qsearch.$inObj.on('keyup', | ||||
|                 function () { | ||||
|                     if (dw_qsearch.timer) { | ||||
|                         window.clearTimeout(dw_qsearch.timer); | ||||
|                         dw_qsearch.timer = null; | ||||
|                     } | ||||
|                     dw_qsearch.timer = window.setTimeout(do_qsearch, 500); | ||||
|                 } | ||||
|             ); | ||||
|  | ||||
|             // attach eventhandler to output field | ||||
|             dw_qsearch.$outObj.on('click', dw_qsearch.clear_results); | ||||
|         }, | ||||
|  | ||||
|         /** | ||||
|          * Read search term from input | ||||
|          */ | ||||
|         getSearchterm: function() { | ||||
|             return dw_qsearch.$inObj.val(); | ||||
|         }, | ||||
|  | ||||
|         /** | ||||
|          * Empty and hide the output div | ||||
|          */ | ||||
|         clear_results: function () { | ||||
|             dw_qsearch.$inObj.parents('form').removeClass('searching'); | ||||
|             dw_qsearch.$outObj.hide(); | ||||
|             dw_qsearch.$outObj.text(''); | ||||
|         }, | ||||
|  | ||||
|         /** | ||||
|          * Callback. Reformat and display the results. | ||||
|          * | ||||
|          * Namespaces are shortened here to keep the results from overflowing | ||||
|          * or wrapping | ||||
|          * | ||||
|          * @param data The result HTML | ||||
|          */ | ||||
|         onCompletion: function (data) { | ||||
|             var max, $links, too_big; | ||||
|             dw_qsearch.$inObj.parents('form').removeClass('searching'); | ||||
|  | ||||
|             dw_qsearch.curRequest = null; | ||||
|  | ||||
|             if (data === '') { | ||||
|                 dw_qsearch.clear_results(); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             dw_qsearch.$outObj | ||||
|                 .html(data) | ||||
|                 .show() | ||||
|                 .css('white-space', 'nowrap'); | ||||
|  | ||||
|             // disable overflow during shortening | ||||
|             dw_qsearch.$outObj.find('li').css('overflow', 'visible'); | ||||
|  | ||||
|             $links = dw_qsearch.$outObj.find('a'); | ||||
|             max = dw_qsearch.$outObj[0].clientWidth; // maximum width allowed (but take away paddings below) | ||||
|             if (document.documentElement.dir === 'rtl') { | ||||
|                 max -= parseInt(dw_qsearch.$outObj.css('padding-left')); | ||||
|                 too_big = function (l) { | ||||
|                     return l.offsetLeft < 0; | ||||
|                 }; | ||||
|             } else { | ||||
|                 max -= parseInt(dw_qsearch.$outObj.css('padding-right')); | ||||
|                 too_big = function (l) { | ||||
|                     return l.offsetWidth + l.offsetLeft > max; | ||||
|                 }; | ||||
|             } | ||||
|  | ||||
|             $links.each(function () { | ||||
|                 var start, length, replace, nsL, nsR, eli, runaway; | ||||
|  | ||||
|                 if (!too_big(this)) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 nsL = this.textContent.indexOf('('); | ||||
|                 nsR = this.textContent.indexOf(')'); | ||||
|                 eli = 0; | ||||
|                 runaway = 0; | ||||
|  | ||||
|                 while ((nsR - nsL > 3) && too_big(this) && runaway++ < 500) { | ||||
|                     if (eli !== 0) { | ||||
|                         // elipsis already inserted | ||||
|                         if ((eli - nsL) > (nsR - eli)) { | ||||
|                             // cut left | ||||
|                             start = eli - 2; | ||||
|                             length = 2; | ||||
|                         } else { | ||||
|                             // cut right | ||||
|                             start = eli + 1; | ||||
|                             length = 1; | ||||
|                         } | ||||
|                         replace = ''; | ||||
|                     } else { | ||||
|                         // replace middle with ellipsis | ||||
|                         start = Math.floor(nsL + ((nsR - nsL) / 2)); | ||||
|                         length = 1; | ||||
|                         replace = '…'; | ||||
|                     } | ||||
|                     this.textContent = substr_replace(this.textContent, | ||||
|                         replace, start, length); | ||||
|  | ||||
|                     eli = this.textContent.indexOf('…'); | ||||
|                     nsL = this.textContent.indexOf('('); | ||||
|                     nsR = this.textContent.indexOf(')'); | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             // reenable overflow | ||||
|             dw_qsearch.$outObj.find('li').css('overflow', 'hidden').css('text-overflow', 'ellipsis'); | ||||
|         } | ||||
|  | ||||
|  | ||||
|     }; | ||||
|  | ||||
|     jQuery.extend(dw_qsearch, overrides); | ||||
|  | ||||
|     if (!overrides.deferInit) { | ||||
|         dw_qsearch.init(); | ||||
|     } | ||||
|  | ||||
|     return dw_qsearch; | ||||
| }; | ||||
|  | ||||
| jQuery(function () { | ||||
|     jQuery('#qsearch__in').dw_qsearch({ | ||||
|         output: '#qsearch__out' | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										30
									
								
								ap23/web/doku/lib/scripts/script.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,30 @@ | ||||
| // if jQuery was loaded, let's make it noConflict here. | ||||
| if ('function' === typeof jQuery && 'function' === typeof jQuery.noConflict) { | ||||
|     jQuery.noConflict(); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Some browser detection | ||||
|  */ | ||||
| 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_khtml  = (navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled )); | ||||
| if (clientPC.indexOf('opera')!=-1) { | ||||
|     var is_opera = true; | ||||
|     var is_opera_preseven = (window.opera && !document.childNodes); | ||||
|     var is_opera_seven = (window.opera && document.childNodes); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Handler to close all open Popups | ||||
|  */ | ||||
| function closePopups(){ | ||||
|     jQuery('div.JSpopup').hide(); | ||||
| } | ||||
|  | ||||
| jQuery(function () { | ||||
|     jQuery(document).on('click', closePopups); | ||||
| }); | ||||
							
								
								
									
										48
									
								
								ap23/web/doku/lib/scripts/search.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,48 @@ | ||||
| jQuery(function () { | ||||
|     'use strict'; | ||||
|  | ||||
|     var $searchForm = jQuery('.search-results-form'); | ||||
|     if (!$searchForm.length) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     var $toggleAssistanceButton = jQuery('<button>') | ||||
|         .addClass('toggleAssistant') | ||||
|         .attr('type', 'button') | ||||
|         .attr('aria-expanded', 'false') | ||||
|         .text(LANG.search_toggle_tools) | ||||
|         .prependTo($searchForm.find('fieldset')) | ||||
|     ; | ||||
|  | ||||
|     $toggleAssistanceButton.on('click', function () { | ||||
|         jQuery('.advancedOptions').toggle(0, function () { | ||||
|             var $me = jQuery(this); | ||||
|             if ($me.attr('aria-hidden')) { | ||||
|                 $me.removeAttr('aria-hidden'); | ||||
|                 $toggleAssistanceButton.attr('aria-expanded', 'true'); | ||||
|                 DokuCookie.setValue('sa', 'on'); | ||||
|             } else { | ||||
|                 $me.attr('aria-hidden', 'true'); | ||||
|                 $toggleAssistanceButton.attr('aria-expanded', 'false'); | ||||
|                 DokuCookie.setValue('sa', 'off'); | ||||
|             } | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     if (DokuCookie.getValue('sa') === 'on') { | ||||
|         $toggleAssistanceButton.trigger('click'); | ||||
|     } | ||||
|  | ||||
|     $searchForm.find('.advancedOptions .toggle div.current').on('click', function () { | ||||
|         var $me = jQuery(this); | ||||
|         $me.parent().siblings().removeClass('open'); | ||||
|         $me.parent().siblings().find('ul:first').attr('aria-expanded', 'false'); | ||||
|         $me.parent().toggleClass('open'); | ||||
|         if ($me.parent().hasClass('open')) { | ||||
|             $me.parent().find('ul:first').attr('aria-expanded', 'true'); | ||||
|         } else { | ||||
|             $me.parent().find('ul:first').attr('aria-expanded', 'false'); | ||||
|         } | ||||
|     }); | ||||
|  | ||||
| }); | ||||
							
								
								
									
										152
									
								
								ap23/web/doku/lib/scripts/textselection.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,152 @@ | ||||
| /** | ||||
|  * Text selection related functions. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * selection prototype | ||||
|  * | ||||
|  * Object that capsulates the selection in a textarea. Returned by DWgetSelection. | ||||
|  * | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  */ | ||||
| function selection_class(){ | ||||
|     this.start     = 0; | ||||
|     this.end       = 0; | ||||
|     this.obj       = null; | ||||
|     this.scroll    = 0; | ||||
|     this.fix       = 0; | ||||
|  | ||||
|     this.getLength = function(){ | ||||
|         return this.end - this.start; | ||||
|     }; | ||||
|  | ||||
|     this.getText = function(){ | ||||
|         return (!this.obj) ? '' : this.obj.value.substring(this.start,this.end); | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Get current selection/cursor position in a given textArea | ||||
|  * | ||||
|  * @link   http://groups.drupal.org/node/1210 | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  * @link   http://linebyline.blogspot.com/2006/11/textarea-cursor-position-in-internet.html | ||||
|  * @returns object - a selection object | ||||
|  */ | ||||
| function DWgetSelection(textArea) { | ||||
|     var sel = new selection_class(); | ||||
|  | ||||
|     textArea.focus(); | ||||
|     sel.obj   = textArea; | ||||
|     sel.start  = textArea.selectionStart; | ||||
|     sel.end    = textArea.selectionEnd; | ||||
|     sel.scroll = textArea.scrollTop; | ||||
|     return sel; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Set the selection | ||||
|  * | ||||
|  * You need to get a selection object via DWgetSelection() first, then modify the | ||||
|  * start and end properties and pass it back to this function. | ||||
|  * | ||||
|  * @link http://groups.drupal.org/node/1210 | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  * @param {selection_class} selection  a selection object as returned by DWgetSelection() | ||||
|  */ | ||||
| function DWsetSelection(selection){ | ||||
|     selection.obj.setSelectionRange(selection.start, selection.end); | ||||
|     if(selection.scroll) selection.obj.scrollTop = selection.scroll; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * 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 {selection_class}  selection     selection object returned by DWgetSelection | ||||
|  * @param {int}     opts.startofs  number of charcters at the start to skip from new selection | ||||
|  * @param {int}     opts.endofs    number of characters at the end to skip from new selection | ||||
|  * @param {boolean} opts.nosel     set true 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 | ||||
|     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; | ||||
|     if(opts.endofs)   selection.end   -= opts.endofs; | ||||
|  | ||||
|     // no selection wanted? set cursor to end position | ||||
|     if(opts.nosel) selection.start = selection.end; | ||||
|  | ||||
|     DWsetSelection(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 = jQuery('#' + textAreaID)[0]; | ||||
|  | ||||
|     var selection = DWgetSelection(txtarea); | ||||
|     var text = selection.getText(); | ||||
|     var opts; | ||||
|  | ||||
|     // don't include trailing space in selection | ||||
|     if(text.charAt(text.length - 1) == ' '){ | ||||
|         selection.end--; | ||||
|         text = selection.getText(); | ||||
|     } | ||||
|  | ||||
|     if(!text){ | ||||
|         // nothing selected, use the sample text and select it | ||||
|         text = sampleText; | ||||
|         opts = { | ||||
|             startofs: tagOpen.length, | ||||
|             endofs: tagClose.length | ||||
|         }; | ||||
|     }else{ | ||||
|         // place cursor at the end | ||||
|         opts = { | ||||
|             nosel: true | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     // surround with tags | ||||
|     text = tagOpen + text + tagClose; | ||||
|  | ||||
|     // do it | ||||
|     pasteText(selection,text,opts); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Wraps around pasteText() for backward compatibility | ||||
|  * | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  */ | ||||
| function insertAtCarret(textAreaID, text){ | ||||
|     var txtarea = jQuery('#' + textAreaID)[0]; | ||||
|     var selection = DWgetSelection(txtarea); | ||||
|     pasteText(selection,text,{nosel: true}); | ||||
| } | ||||
							
								
								
									
										282
									
								
								ap23/web/doku/lib/scripts/toolbar.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,282 @@ | ||||
| // used to identify pickers | ||||
| 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  bool   allowblock Allow buttons creating multiline content | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  */ | ||||
| function initToolbar(tbid,edid,tb, allowblock){ | ||||
|     var $toolbar, $edit; | ||||
|     if (typeof tbid == 'string') { | ||||
|         $toolbar = jQuery('#' + tbid); | ||||
|     } else { | ||||
|         $toolbar = jQuery(tbid); | ||||
|     } | ||||
|  | ||||
|     $edit = jQuery('#' + edid); | ||||
|  | ||||
|     if ($toolbar.length == 0 || $edit.length == 0 || $edit.attr('readOnly')) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if (typeof allowblock === 'undefined') { | ||||
|         allowblock = true; | ||||
|     } | ||||
|  | ||||
|     //empty the toolbar area: | ||||
|     $toolbar.html(''); | ||||
|  | ||||
|     jQuery.each(tb, function (k, val) { | ||||
|         if (!tb.hasOwnProperty(k) || (!allowblock && val.block === true)) { | ||||
|             return; | ||||
|         } | ||||
|         var actionFunc, $btn; | ||||
|  | ||||
|         // create new button (jQuery object) | ||||
|         $btn = jQuery(createToolButton(val.icon, val.title, val.key, val.id, | ||||
|                                        val['class'])); | ||||
|  | ||||
|         // type is a tb function -> assign it as onclick | ||||
|         actionFunc = 'tb_'+val.type; | ||||
|         if( jQuery.isFunction(window[actionFunc]) ){ | ||||
|             $btn.on('click', bind(window[actionFunc],$btn,val,edid) ); | ||||
|             $toolbar.append($btn); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // type is a init function -> execute it | ||||
|         actionFunc = 'addBtnAction'+val.type.charAt(0).toUpperCase()+val.type.substring(1); | ||||
|         if( jQuery.isFunction(window[actionFunc]) ){ | ||||
|             var pickerid = window[actionFunc]($btn, val, edid); | ||||
|             if(pickerid !== ''){ | ||||
|                 $toolbar.append($btn); | ||||
|                 $btn.attr('aria-controls', pickerid); | ||||
|                 if (actionFunc === 'addBtnActionPicker') { | ||||
|                     $btn.attr('aria-haspopup', 'true'); | ||||
|                 } | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         alert('unknown toolbar type: '+val.type+'  '+actionFunc); | ||||
|     }); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Button action for format buttons | ||||
|  * | ||||
|  * @param  DOMElement btn   Button element to add the action to | ||||
|  * @param  array      props Associative array of button properties | ||||
|  * @param  string     edid  ID of the editor textarea | ||||
|  * @author Gabriel Birke <birke@d-scribe.de> | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  */ | ||||
| function tb_format(btn, props, edid) { | ||||
|     var sample = props.sample || props.title; | ||||
|     insertTags(edid, | ||||
|                fixtxt(props.open), | ||||
|                fixtxt(props.close), | ||||
|                fixtxt(sample)); | ||||
|     pickerClose(); | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Button action for format buttons | ||||
|  * | ||||
|  * This works exactly as tb_format() except that, if multiple lines | ||||
|  * are selected, each line will be formatted seperately | ||||
|  * | ||||
|  * @param  DOMElement btn   Button element to add the action to | ||||
|  * @param  array      props Associative array of button properties | ||||
|  * @param  string     edid  ID of the editor textarea | ||||
|  * @author Gabriel Birke <birke@d-scribe.de> | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  */ | ||||
| function tb_formatln(btn, props, edid) { | ||||
|     var sample = props.sample || props.title, | ||||
|         opts, | ||||
|         selection = DWgetSelection(jQuery('#'+edid)[0]); | ||||
|  | ||||
|     sample = fixtxt(sample); | ||||
|     props.open  = fixtxt(props.open); | ||||
|     props.close = fixtxt(props.close); | ||||
|  | ||||
|     // is something selected? | ||||
|     if(selection.getLength()){ | ||||
|         sample = selection.getText(); | ||||
|         opts = {nosel: true}; | ||||
|     }else{ | ||||
|         opts = { | ||||
|             startofs: props.open.length, | ||||
|             endofs: props.close.length | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     sample = sample.split("\n").join(props.close+"\n"+props.open); | ||||
|     sample = props.open+sample+props.close; | ||||
|  | ||||
|     pasteText(selection,sample,opts); | ||||
|  | ||||
|     pickerClose(); | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Button action for insert buttons | ||||
|  * | ||||
|  * @param  DOMElement btn   Button element to add the action to | ||||
|  * @param  array      props Associative array of button properties | ||||
|  * @param  string     edid  ID of the editor textarea | ||||
|  * @author Gabriel Birke <birke@d-scribe.de> | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  */ | ||||
| function tb_insert(btn, props, edid) { | ||||
|     insertAtCarret(edid,fixtxt(props.insert)); | ||||
|     pickerClose(); | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Button action for the media popup | ||||
|  * | ||||
|  * @param  DOMElement btn   Button element to add the action to | ||||
|  * @param  array      props Associative array of button properties | ||||
|  * @param  string     edid  ID of the editor textarea | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  */ | ||||
| function tb_mediapopup(btn, props, edid) { | ||||
|     window.open( | ||||
|         DOKU_BASE+props.url+encodeURIComponent(NS)+'&edid='+encodeURIComponent(edid), | ||||
|         props.name, | ||||
|         props.options); | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Button action for automatic headlines | ||||
|  * | ||||
|  * Insert a new headline based on the current section level | ||||
|  * | ||||
|  * @param  DOMElement btn   Button element to add the action to | ||||
|  * @param  array      props Associative array of button properties | ||||
|  * @param  string     edid  ID of the editor textarea | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  */ | ||||
| function tb_autohead(btn, props, edid){ | ||||
|     var lvl = currentHeadlineLevel(edid), | ||||
|         tags; | ||||
|  | ||||
|     // determine new level | ||||
|     lvl += props.mod; | ||||
|     if(lvl < 1) lvl = 1; | ||||
|     if(lvl > 5) lvl = 5; | ||||
|  | ||||
|     tags = (new Array(8 - lvl)).join('='); | ||||
|     insertTags(edid, tags+' ', ' '+tags+"\n", props.text); | ||||
|     pickerClose(); | ||||
|     return false; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Add button action for picker buttons and create picker element | ||||
|  * | ||||
|  * @param  jQuery      btn   Button element to add the action to | ||||
|  * @param  array      props Associative array of button properties | ||||
|  * @param  string     edid  ID of the editor textarea | ||||
|  * @return boolean    If button should be appended | ||||
|  * @author Gabriel Birke <birke@d-scribe.de> | ||||
|  */ | ||||
| function addBtnActionPicker($btn, props, edid) { | ||||
|     var pickerid = 'picker'+(pickercounter++); | ||||
|     var picker = createPicker(pickerid, props, edid); | ||||
|     jQuery(picker).attr('aria-hidden', 'true'); | ||||
|  | ||||
|     $btn.click( | ||||
|         function(e) { | ||||
|             pickerToggle(pickerid,$btn); | ||||
|             e.preventDefault(); | ||||
|             return ''; | ||||
|         } | ||||
|     ); | ||||
|  | ||||
|     return pickerid; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Add button action for the link wizard button | ||||
|  * | ||||
|  * @param  DOMElement btn   Button element to add the action to | ||||
|  * @param  array      props Associative array of button properties | ||||
|  * @param  string     edid  ID of the editor textarea | ||||
|  * @return boolean    If button should be appended | ||||
|  * @author Andreas Gohr <gohr@cosmocode.de> | ||||
|  */ | ||||
| function addBtnActionLinkwiz($btn, props, edid) { | ||||
|     dw_linkwiz.init(jQuery('#'+edid)); | ||||
|     jQuery($btn).click(function(e){ | ||||
|         dw_linkwiz.val = props; | ||||
|         dw_linkwiz.toggle(); | ||||
|         e.preventDefault(); | ||||
|         return ''; | ||||
|     }); | ||||
|     return 'link__wiz'; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Show/Hide a previously created picker window | ||||
|  * | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  */ | ||||
| function pickerToggle(pickerid,$btn){ | ||||
|     var $picker = jQuery('#' + pickerid), | ||||
|         pos = $btn.offset(); | ||||
|     if ($picker.hasClass('a11y')) { | ||||
|         $picker.removeClass('a11y').attr('aria-hidden', 'false'); | ||||
|     } else { | ||||
|         $picker.addClass('a11y').attr('aria-hidden', 'true'); | ||||
|     } | ||||
|     var picker_left = pos.left + 3, | ||||
|         picker_width = $picker.width(), | ||||
|         window_width = jQuery(window).width(); | ||||
|     if (picker_width > 300) { | ||||
|         $picker.css("max-width", "300"); | ||||
|         picker_width = 300; | ||||
|     } | ||||
|     if ((picker_left + picker_width + 40) > window_width) { | ||||
|         picker_left = window_width - picker_width - 40; | ||||
|     } | ||||
|     if (picker_left < 0) { | ||||
|         picker_left = 0; | ||||
|     } | ||||
|     $picker.offset({left: picker_left, top: pos.top+$btn[0].offsetHeight+3}); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Close all open pickers | ||||
|  * | ||||
|  * @author Andreas Gohr <andi@splitbrain.org> | ||||
|  */ | ||||
| function pickerClose(){ | ||||
|     jQuery('.picker').addClass('a11y'); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Replaces \n with linebreaks | ||||
|  */ | ||||
| function fixtxt(str){ | ||||
|     return str.replace(/\\n/g,"\n"); | ||||
| } | ||||
|  | ||||
| jQuery(function () { | ||||
|     initToolbar('tool__bar','wiki__text',toolbar); | ||||
|     jQuery('#tool__bar').attr('role', 'toolbar'); | ||||
| }); | ||||
							
								
								
									
										107
									
								
								ap23/web/doku/lib/scripts/tree.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,107 @@ | ||||
| jQuery.fn.dw_tree = function(overrides) { | ||||
|     var dw_tree = { | ||||
|  | ||||
|         /** | ||||
|          * Delay in ms before showing the throbber. | ||||
|          * Used to skip the throbber for fast AJAX calls. | ||||
|          */ | ||||
|         throbber_delay: 500, | ||||
|  | ||||
|         $obj: this, | ||||
|  | ||||
|         toggle_selector: 'a.idx_dir', | ||||
|  | ||||
|         init: function () { | ||||
|             this.$obj.on('click', this.toggle_selector, this, | ||||
|                                this.toggle); | ||||
|             jQuery('ul:first', this.$obj).attr('role', 'tree'); | ||||
|             jQuery('ul', this.$obj).not(':first').attr('role', 'group'); | ||||
|             jQuery('li', this.$obj).attr('role', 'treeitem'); | ||||
|             jQuery('li.open > ul', this.$obj).attr('aria-expanded', 'true'); | ||||
|             jQuery('li.closed > ul', this.$obj).attr('aria-expanded', 'false'); | ||||
|             jQuery('li.closed', this.$obj).attr('aria-live', 'assertive'); | ||||
|         }, | ||||
|  | ||||
|         /** | ||||
|          * Open or close a subtree using AJAX | ||||
|          * The contents of subtrees are "cached" until the page is reloaded. | ||||
|          * A "loading" indicator is shown only when the AJAX call is slow. | ||||
|          * | ||||
|          * @author Andreas Gohr <andi@splitbrain.org> | ||||
|          * @author Ben Coburn <btcoburn@silicodon.net> | ||||
|          * @author Pierre Spring <pierre.spring@caillou.ch> | ||||
|          */ | ||||
|         toggle: function (e) { | ||||
|             var $listitem, $sublist, timeout, $clicky, show_sublist, dw_tree, opening; | ||||
|  | ||||
|             e.preventDefault(); | ||||
|  | ||||
|             dw_tree = e.data; | ||||
|             $clicky = jQuery(this); | ||||
|             $listitem = $clicky.closest('li'); | ||||
|             $sublist = $listitem.find('ul').first(); | ||||
|             opening = $listitem.hasClass('closed'); | ||||
|             dw_tree.toggle_display($clicky, opening); | ||||
|             if ($sublist.is(':visible')) { | ||||
|                 $listitem.removeClass('open').addClass('closed'); | ||||
|                 $sublist.attr('aria-expanded', 'false'); | ||||
|             } else { | ||||
|                 $listitem.removeClass('closed').addClass('open'); | ||||
|                 $sublist.attr('aria-expanded', 'true'); | ||||
|             } | ||||
|  | ||||
|             // if already open, close by hiding the sublist | ||||
|             if (!opening) { | ||||
|                 $sublist.dw_hide(); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             show_sublist = function (data) { | ||||
|                 $sublist.hide(); | ||||
|                 if (typeof data !== 'undefined') { | ||||
|                     $sublist.html(data); | ||||
|                     $sublist.parent().attr('aria-busy', 'false').removeAttr('aria-live'); | ||||
|                     jQuery('li.closed', $sublist).attr('aria-live', 'assertive'); | ||||
|                 } | ||||
|                 if ($listitem.hasClass('open')) { | ||||
|                     // Only show if user didn’t close the list since starting | ||||
|                     // to load the content | ||||
|                     $sublist.dw_show(); | ||||
|                 } | ||||
|             }; | ||||
|  | ||||
|             // just show if already loaded | ||||
|             if ($sublist.length > 0) { | ||||
|                 show_sublist(); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             //prepare the new ul | ||||
|             $sublist = jQuery('<ul class="idx" role="group"/>'); | ||||
|             $listitem.append($sublist); | ||||
|  | ||||
|             timeout = window.setTimeout( | ||||
|                 bind(show_sublist, '<li aria-busy="true"><img src="' + DOKU_BASE + 'lib/images/throbber.gif" alt="loading..." title="loading..." /></li>'), dw_tree.throbber_delay); | ||||
|  | ||||
|             dw_tree.load_data(function (data) { | ||||
|                                   window.clearTimeout(timeout); | ||||
|                                   show_sublist(data); | ||||
|                               }, $clicky); | ||||
|         }, | ||||
|  | ||||
|         toggle_display: function ($clicky, opening) { | ||||
|         }, | ||||
|  | ||||
|         load_data: function (show_data, $clicky) { | ||||
|             show_data(); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     jQuery.extend(dw_tree, overrides); | ||||
|  | ||||
|     if (!overrides.deferInit) { | ||||
|         dw_tree.init(); | ||||
|     } | ||||
|  | ||||
|     return dw_tree; | ||||
| }; | ||||