var DOKU_BASE = '/';var DOKU_TPL = '/lib/tpl/bootstrap3/';var DOKU_COOKIE_PARAM = {"path":"\/","secure":true};Object.defineProperty(window, 'DOKU_UHN', { get: function() {console.warn('Using DOKU_UHN is deprecated. Please use JSINFO.useHeadingNavigation instead');return JSINFO.useHeadingNavigation; } });Object.defineProperty(window, 'DOKU_UHC', { get: function() {console.warn('Using DOKU_UHC is deprecated. Please use JSINFO.useHeadingContent instead');return JSINFO.useHeadingContent; } });LANG = {"search_toggle_tools":"Toggle Search Tools","willexpire":"Your lock for editing this page is about to expire in a minute.\\nTo avoid conflicts use the preview button to reset the locktimer.","notsavedyet":"Unsaved changes will be lost.","searchmedia":"Search for files","keepopen":"Keep window open on selection","hidedetails":"Hide Details","mediatitle":"Link settings","mediadisplay":"Link type","mediaalign":"Alignment","mediasize":"Image size","mediatarget":"Link target","mediaclose":"Close","mediainsert":"Insert","mediadisplayimg":"Show the image.","mediadisplaylnk":"Show only the link.","mediasmall":"Small version","mediamedium":"Medium version","medialarge":"Large version","mediaoriginal":"Original version","medialnk":"Link to detail page","mediadirect":"Direct link to original","medianolnk":"No link","medianolink":"Do not link the image","medialeft":"Align the image on the left.","mediaright":"Align the image on the right.","mediacenter":"Align the image in the middle.","medianoalign":"Use no align.","nosmblinks":"Linking to Windows shares only works in Microsoft Internet Explorer.\\nYou still can copy and paste the link.","linkwiz":"Link Wizard","linkto":"Link to:","del_confirm":"Really delete selected item(s)?","restore_confirm":"Really restore this version?","media_diff":"View differences:","media_diff_both":"Side by Side","media_diff_opacity":"Shine-through","media_diff_portions":"Swipe","media_select":"Select files\u2026","media_upload_btn":"Upload","media_done_btn":"Done","media_drop":"Drop files here to upload","media_cancel":"remove","media_overwrt":"Overwrite existing files","data_insecure":"WARNING: It seems your data directory is not properly secured. Please read about Web Access Security in DokuWiki<\/a>.","plugins":{"edittable":{"toggle_header":"Toggle header state","align_left":"Left-align cell","align_center":"Center cell","align_right":"Right-align cell","confirmdeleterow":"Really delete row?","confirmdeletecol":"Really delete column?","row_above":"Add row above","remove_row":"Remove row","row_below":"Add row below","col_left":"Add column on the left","remove_col":"Remove column","col_right":"Add column on the right","merge_cells":"Merge cells","unmerge_cells":"Split cells"},"extension":{"reallydel":"Really uninstall this extension?","display_viewoptions":"View Options:","display_enabled":"enabled","display_disabled":"disabled","display_updatable":"updatable"},"gallery":{"addgal":"Add namespace as gallery"},"logviewer":{"filter":"Filter Loglines:"},"move":{"rename":"Rename","cancel":"Cancel","newname":"New name:","inprogress":"renaming page and adjusting links...","complete":"Move operation finished.","renameitem":"Rename this item","add":"Create a new namespace","duplicate":"Sorry, \"%s\" already exists in this namespace."},"styling":{"loader":"Preview is loading...
if this does not goes away, your values may be faulty","popup":"Open as a popup"},"tablelayout":{"loading":"Loading","print":"Print","search":"Search"},"vshare":{"button":"Insert video from video sharing sites","prompt":"Please paste the full URL to the video page here:","notfound":"Sorry, this URL wasn't recognized.\nPlease refer to the documentation on how to insert the correct syntax manually.","click":"Click to load this video. Your IP address and possibly other data will be transferred to %s."}}}; var toolbar = [{"type":"format","title":"Bold Text","icon":"bold.png","key":"b","open":"**","close":"**","block":false},{"type":"format","title":"Italic Text","icon":"italic.png","key":"i","open":"\/\/","close":"\/\/","block":false},{"type":"format","title":"Underlined Text","icon":"underline.png","key":"u","open":"__","close":"__","block":false},{"type":"format","title":"Monospaced Text","icon":"mono.png","key":"m","open":"''","close":"''","block":false},{"type":"format","title":"Strike-through Text","icon":"strike.png","key":"d","open":"","close":"<\/del>","block":false},{"type":"autohead","title":"Same Level Headline","icon":"hequal.png","key":"8","text":"Headline","mod":0,"block":true},{"type":"autohead","title":"Lower Headline","icon":"hminus.png","key":"9","text":"Headline","mod":1,"block":true},{"type":"autohead","title":"Higher Headline","icon":"hplus.png","key":"0","text":"Headline","mod":-1,"block":true},{"type":"picker","title":"Select Headline","icon":"h.png","class":"pk_hl","list":[{"type":"format","title":"Level 1 Headline","icon":"h1.png","key":"1","open":"====== ","close":" ======\\n"},{"type":"format","title":"Level 2 Headline","icon":"h2.png","key":"2","open":"===== ","close":" =====\\n"},{"type":"format","title":"Level 3 Headline","icon":"h3.png","key":"3","open":"==== ","close":" ====\\n"},{"type":"format","title":"Level 4 Headline","icon":"h4.png","key":"4","open":"=== ","close":" ===\\n"},{"type":"format","title":"Level 5 Headline","icon":"h5.png","key":"5","open":"== ","close":" ==\\n"}],"block":true},{"type":"linkwiz","title":"Internal Link","icon":"link.png","key":"l","open":"[[","close":"]]","block":false},{"type":"format","title":"External Link","icon":"linkextern.png","open":"[[","close":"]]","sample":"http:\/\/example.com|External Link","block":false},{"type":"formatln","title":"Ordered List Item","icon":"ol.png","open":" - ","close":"","key":"-","block":true},{"type":"formatln","title":"Unordered List Item","icon":"ul.png","open":" * ","close":"","key":".","block":true},{"type":"insert","title":"Horizontal Rule","icon":"hr.png","insert":"\\n----\\n","block":true},{"type":"mediapopup","title":"Add Images and other files (opens in a new window)","icon":"image.png","url":"lib\/exe\/mediamanager.php?ns=","name":"mediaselect","options":"width=750,height=500,left=20,top=20,scrollbars=yes,resizable=yes","block":false},{"type":"picker","title":"Smileys","icon":"smiley.png","list":{"8-)":"cool.svg","8-O":"eek.svg","8-o":"eek.svg",":-(":"sad.svg",":-)":"smile.svg","=)":"smile2.svg",":-\/":"doubt.svg",":-\\":"doubt2.svg",":-?":"confused.svg",":-D":"biggrin.svg",":-P":"razz.svg",":-o":"surprised.svg",":-O":"surprised.svg",":-x":"silenced.svg",":-X":"silenced.svg",":-|":"neutral.svg",";-)":"wink.svg","m(":"facepalm.svg","^_^":"fun.svg",":?:":"question.svg",":!:":"exclaim.svg","LOL":"lol.svg","FIXME":"fixme.svg","DELETEME":"deleteme.svg"},"icobase":"smileys","block":false},{"type":"picker","title":"Special Chars","icon":"chars.png","list":["\u00c0","\u00e0","\u00c1","\u00e1","\u00c2","\u00e2","\u00c3","\u00e3","\u00c4","\u00e4","\u01cd","\u01ce","\u0102","\u0103","\u00c5","\u00e5","\u0100","\u0101","\u0104","\u0105","\u00c6","\u00e6","\u0106","\u0107","\u00c7","\u00e7","\u010c","\u010d","\u0108","\u0109","\u010a","\u010b","\u00d0","\u0111","\u00f0","\u010e","\u010f","\u00c8","\u00e8","\u00c9","\u00e9","\u00ca","\u00ea","\u00cb","\u00eb","\u011a","\u011b","\u0112","\u0113","\u0116","\u0117","\u0118","\u0119","\u0122","\u0123","\u011c","\u011d","\u011e","\u011f","\u0120","\u0121","\u0124","\u0125","\u00cc","\u00ec","\u00cd","\u00ed","\u00ce","\u00ee","\u00cf","\u00ef","\u01cf","\u01d0","\u012a","\u012b","\u0130","\u0131","\u012e","\u012f","\u0134","\u0135","\u0136","\u0137","\u0139","\u013a","\u013b","\u013c","\u013d","\u013e","\u0141","\u0142","\u013f","\u0140","\u0143","\u0144","\u00d1","\u00f1","\u0145","\u0146","\u0147","\u0148","\u00d2","\u00f2","\u00d3","\u00f3","\u00d4","\u00f4","\u00d5","\u00f5","\u00d6","\u00f6","\u01d1","\u01d2","\u014c","\u014d","\u0150","\u0151","\u0152","\u0153","\u00d8","\u00f8","\u0154","\u0155","\u0156","\u0157","\u0158","\u0159","\u015a","\u015b","\u015e","\u015f","\u0160","\u0161","\u015c","\u015d","\u0162","\u0163","\u0164","\u0165","\u00d9","\u00f9","\u00da","\u00fa","\u00db","\u00fb","\u00dc","\u00fc","\u01d3","\u01d4","\u016c","\u016d","\u016a","\u016b","\u016e","\u016f","\u01d6","\u01d8","\u01da","\u01dc","\u0172","\u0173","\u0170","\u0171","\u0174","\u0175","\u00dd","\u00fd","\u0178","\u00ff","\u0176","\u0177","\u0179","\u017a","\u017d","\u017e","\u017b","\u017c","\u00de","\u00fe","\u00df","\u0126","\u0127","\u00bf","\u00a1","\u00a2","\u00a3","\u00a4","\u00a5","\u20ac","\u00a6","\u00a7","\u00aa","\u00ac","\u00af","\u00b0","\u00b1","\u00f7","\u2030","\u00bc","\u00bd","\u00be","\u00b9","\u00b2","\u00b3","\u00b5","\u00b6","\u2020","\u2021","\u00b7","\u2022","\u00ba","\u2200","\u2202","\u2203","\u018f","\u0259","\u2205","\u2207","\u2208","\u2209","\u220b","\u220f","\u2211","\u203e","\u2212","\u2217","\u00d7","\u2044","\u221a","\u221d","\u221e","\u2220","\u2227","\u2228","\u2229","\u222a","\u222b","\u2234","\u223c","\u2245","\u2248","\u2260","\u2261","\u2264","\u2265","\u2282","\u2283","\u2284","\u2286","\u2287","\u2295","\u2297","\u22a5","\u22c5","\u25ca","\u2118","\u2111","\u211c","\u2135","\u2660","\u2663","\u2665","\u2666","\u03b1","\u03b2","\u0393","\u03b3","\u0394","\u03b4","\u03b5","\u03b6","\u03b7","\u0398","\u03b8","\u03b9","\u03ba","\u039b","\u03bb","\u03bc","\u039e","\u03be","\u03a0","\u03c0","\u03c1","\u03a3","\u03c3","\u03a4","\u03c4","\u03c5","\u03a6","\u03c6","\u03c7","\u03a8","\u03c8","\u03a9","\u03c9","\u2605","\u2606","\u260e","\u261a","\u261b","\u261c","\u261d","\u261e","\u261f","\u2639","\u263a","\u2714","\u2718","\u201e","\u201c","\u201d","\u201a","\u2018","\u2019","\u00ab","\u00bb","\u2039","\u203a","\u2014","\u2013","\u2026","\u2190","\u2191","\u2192","\u2193","\u2194","\u21d0","\u21d1","\u21d2","\u21d3","\u21d4","\u00a9","\u2122","\u00ae","\u2032","\u2033","[","]","{","}","~","(",")","%","\u00a7","$","#","|","@"],"block":false},{"type":"signature","title":"Insert Signature","icon":"sig.png","key":"y","block":false},{"type":"mediapopup","title":"Bootstrap Wrapper","icon":"..\/..\/plugins\/bootswrapper\/images\/bootstrap.png","url":"lib\/plugins\/bootswrapper\/exe\/popup.php?ns=","name":"bootstrap-wrapper","options":"width=800,height=600,left=20,top=20,toolbar=no,menubar=no,scrollbars=yes,resizable=yes","block":false},{"title":"Insert a new table","type":"NewTable","icon":"..\/..\/plugins\/edittable\/images\/add_table.png","block":true},{"type":"mediapopup","title":"Icons","icon":"..\/..\/tpl\/dokuwiki\/images\/logo.png","url":"lib\/plugins\/icons\/exe\/popup.php?ns=","name":"icons","options":"width=800,height=600,left=20,top=20,toolbar=no,menubar=no,scrollbars=yes,resizable=yes","block":false},{"type":"picker","title":"Wrap Plugin","icon":"..\/..\/plugins\/wrap\/images\/toolbar\/picker.png","list":[{"type":"format","title":"columns","icon":"..\/..\/plugins\/wrap\/images\/toolbar\/column.png","open":"\\n\\n","close":"\\n<\/WRAP>\\n\\n\\n\\n<\/WRAP>\\n<\/WRAP>\\n"},{"type":"format","title":"simple centered box","icon":"..\/..\/plugins\/wrap\/images\/toolbar\/box.png","open":"\\n","close":"\\n<\/WRAP>\\n"},{"type":"format","title":"info box","icon":"..\/..\/plugins\/wrap\/images\/note\/16\/info.png","open":"\\n","close":"\\n<\/WRAP>\\n"},{"type":"format","title":"tip box","icon":"..\/..\/plugins\/wrap\/images\/note\/16\/tip.png","open":"\\n","close":"\\n<\/WRAP>\\n"},{"type":"format","title":"important box","icon":"..\/..\/plugins\/wrap\/images\/note\/16\/important.png","open":"\\n","close":"\\n<\/WRAP>\\n"},{"type":"format","title":"alert box","icon":"..\/..\/plugins\/wrap\/images\/note\/16\/alert.png","open":"\\n","close":"\\n<\/WRAP>\\n"},{"type":"format","title":"help box","icon":"..\/..\/plugins\/wrap\/images\/note\/16\/help.png","open":"\\n","close":"\\n<\/WRAP>\\n"},{"type":"format","title":"download box","icon":"..\/..\/plugins\/wrap\/images\/note\/16\/download.png","open":"\\n","close":"\\n<\/WRAP>\\n"},{"type":"format","title":"todo box","icon":"..\/..\/plugins\/wrap\/images\/note\/16\/todo.png","open":"\\n","close":"\\n<\/WRAP>\\n"},{"type":"insert","title":"clear floats","icon":"..\/..\/plugins\/wrap\/images\/toolbar\/clear.png","insert":"\\n"},{"type":"format","title":"especially emphasised","icon":"..\/..\/plugins\/wrap\/images\/toolbar\/em.png","open":"","close":"<\/wrap>"},{"type":"format","title":"highlighted","icon":"..\/..\/plugins\/wrap\/images\/toolbar\/hi.png","open":"","close":"<\/wrap>"},{"type":"format","title":"less significant","icon":"..\/..\/plugins\/wrap\/images\/toolbar\/lo.png","open":"","close":"<\/wrap>"}]}]; /* XXXXXXXXXX begin of lib/scripts/jquery/jquery.cookie.js XXXXXXXXXX */ /*! * 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); }; })); /* XXXXXXXXXX end of lib/scripts/jquery/jquery.cookie.js XXXXXXXXXX */ /* XXXXXXXXXX begin of lib/scripts/fileuploader.js XXXXXXXXXX */ /** * http://github.com/valums/file-uploader * * Multiple file upload component with progress-bar, drag-and-drop. * © 2010 Andrew Valums ( andrew(at)valums.com ) * * Licensed under GNU GPL 2 or later and GNU LGPL 2 or later, see license.txt. */ // // Helper functions // var qq = qq || {}; /** * Adds all missing properties from second obj to first obj */ qq.extend = function(first, second){ for (var prop in second){ first[prop] = second[prop]; } }; /** * Searches for a given element in the array, returns -1 if it is not present. * @param {Number} [from] The index at which to begin the search */ qq.indexOf = function(arr, elt, from){ if (arr.indexOf) return arr.indexOf(elt, from); from = from || 0; var len = arr.length; if (from < 0) from += len; for (; from < len; from++){ if (from in arr && arr[from] === elt){ return from; } } return -1; }; qq.getUniqueId = (function(){ var id = 0; return function(){ return id++; }; })(); // // Events qq.attach = function(element, type, fn){ if (element.addEventListener){ element.addEventListener(type, fn, false); } else if (element.attachEvent){ element.attachEvent('on' + type, fn); } }; qq.detach = function(element, type, fn){ if (element.removeEventListener){ element.removeEventListener(type, fn, false); } else if (element.attachEvent){ element.detachEvent('on' + type, fn); } }; qq.preventDefault = function(e){ if (e.preventDefault){ e.preventDefault(); } else{ e.returnValue = false; } }; // // Node manipulations /** * Insert node a before node b. */ qq.insertBefore = function(a, b){ b.parentNode.insertBefore(a, b); }; qq.remove = function(element){ element.parentNode.removeChild(element); }; qq.contains = function(parent, descendant){ // compareposition returns false in this case if (parent == descendant) return true; if (parent.contains){ return parent.contains(descendant); } else { return !!(descendant.compareDocumentPosition(parent) & 8); } }; /** * Creates and returns element from html string * Uses innerHTML to create an element */ qq.toElement = (function(){ var div = document.createElement('div'); return function(html){ div.innerHTML = html; var element = div.firstChild; div.removeChild(element); return element; }; })(); // // Node properties and attributes /** * Sets styles for an element. * Fixes opacity in IE6-8. */ qq.css = function(element, styles){ if (styles.opacity != null){ if (typeof element.style.opacity != 'string' && typeof(element.filters) != 'undefined'){ styles.filter = 'alpha(opacity=' + Math.round(100 * styles.opacity) + ')'; } } qq.extend(element.style, styles); }; qq.hasClass = function(element, name){ var re = new RegExp('(^| )' + name + '( |$)'); return re.test(element.className); }; qq.addClass = function(element, name){ if (!qq.hasClass(element, name)){ element.className += ' ' + name; } }; qq.removeClass = function(element, name){ var re = new RegExp('(^| )' + name + '( |$)'); element.className = element.className.replace(re, ' ').replace(/^\s+|\s+$/g, ""); }; qq.setText = function(element, text){ element.innerText = text; element.textContent = text; }; // // Selecting elements qq.children = function(element){ var children = [], child = element.firstChild; while (child){ if (child.nodeType == 1){ children.push(child); } child = child.nextSibling; } return children; }; qq.getByClass = function(element, className){ if (element.querySelectorAll){ return element.querySelectorAll('.' + className); } var result = []; var candidates = element.getElementsByTagName("*"); var len = candidates.length; for (var i = 0; i < len; i++){ if (qq.hasClass(candidates[i], className)){ result.push(candidates[i]); } } return result; }; /** * obj2url() takes a json-object as argument and generates * a querystring. pretty much like jQuery.param() * * how to use: * * `qq.obj2url({a:'b',c:'d'},'http://any.url/upload?otherParam=value');` * * will result in: * * `http://any.url/upload?otherParam=value&a=b&c=d` * * @param Object JSON-Object * @param String current querystring-part * @return String encoded querystring */ qq.obj2url = function(obj, temp, prefixDone){ var uristrings = [], prefix = '&', add = function(nextObj, i){ var nextTemp = temp ? (/\[\]$/.test(temp)) // prevent double-encoding ? temp : temp+'['+i+']' : i; if ((nextTemp != 'undefined') && (i != 'undefined')) { uristrings.push( (typeof nextObj === 'object') ? qq.obj2url(nextObj, nextTemp, true) : (Object.prototype.toString.call(nextObj) === '[object Function]') ? encodeURIComponent(nextTemp) + '=' + encodeURIComponent(nextObj()) : encodeURIComponent(nextTemp) + '=' + encodeURIComponent(nextObj) ); } }; if (!prefixDone && temp) { prefix = (/\?/.test(temp)) ? (/\?$/.test(temp)) ? '' : '&' : '?'; uristrings.push(temp); uristrings.push(qq.obj2url(obj)); } else if ((Object.prototype.toString.call(obj) === '[object Array]') && (typeof obj != 'undefined') ) { // we wont use a for-in-loop on an array (performance) for (var i = 0, len = obj.length; i < len; ++i){ add(obj[i], i); } } else if ((typeof obj != 'undefined') && (obj !== null) && (typeof obj === "object")){ // for anything else but a scalar, we will use for-in-loop for (var i in obj){ if(obj.hasOwnProperty(i) && typeof obj[i] != 'function') { add(obj[i], i); } } } else { uristrings.push(encodeURIComponent(temp) + '=' + encodeURIComponent(obj)); } return uristrings.join(prefix) .replace(/^&/, '') .replace(/%20/g, '+'); }; // // // Uploader Classes // // var qq = qq || {}; /** * Creates upload button, validates upload, but doesn't create file list or dd. */ qq.FileUploaderBasic = function(o){ this._options = { // set to true to see the server response debug: false, action: '/server/upload', params: {}, button: null, multiple: true, maxConnections: 3, // validation allowedExtensions: [], sizeLimit: 0, minSizeLimit: 0, // events // return false to cancel submit onSubmit: function(id, fileName){}, onProgress: function(id, fileName, loaded, total){}, onComplete: function(id, fileName, responseJSON){}, onCancel: function(id, fileName){}, // messages messages: { typeError: "{file} has invalid extension. Only {extensions} are allowed.", sizeError: "{file} is too large, maximum file size is {sizeLimit}.", minSizeError: "{file} is too small, minimum file size is {minSizeLimit}.", emptyError: "{file} is empty, please select files again without it.", onLeave: "The files are being uploaded, if you leave now the upload will be cancelled." }, showMessage: function(message){ alert(message); } }; qq.extend(this._options, o); // number of files being uploaded this._filesInProgress = 0; this._handler = this._createUploadHandler(); if (this._options.button){ this._button = this._createUploadButton(this._options.button); } this._preventLeaveInProgress(); }; qq.FileUploaderBasic.prototype = { setParams: function(params){ this._options.params = params; }, getInProgress: function(){ return this._filesInProgress; }, _createUploadButton: function(element){ var self = this; return new qq.UploadButton({ element: element, multiple: this._options.multiple && qq.UploadHandlerXhr.isSupported(), onChange: function(input){ self._onInputChange(input); } }); }, _createUploadHandler: function(){ var self = this, handlerClass; if(qq.UploadHandlerXhr.isSupported()){ handlerClass = 'UploadHandlerXhr'; } 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); } }); return handler; }, _preventLeaveInProgress: function(){ var self = this; qq.attach(window, 'beforeunload', function(e){ if (!self._filesInProgress){return;} var e = e || window.event; // for ie, ff e.returnValue = self._options.messages.onLeave; // for webkit return self._options.messages.onLeave; }); }, _onSubmit: function(id, fileName){ this._filesInProgress++; }, _onProgress: function(id, fileName, loaded, total){ }, _onComplete: function(id, fileName, result){ this._filesInProgress--; if (result.error){ this._options.showMessage(result.error); } }, _onCancel: function(id, fileName){ this._filesInProgress--; }, _onInputChange: function(input){ if (this._handler instanceof qq.UploadHandlerXhr){ this._uploadFileList(input.files); } else { if (this._validateFile(input)){ this._uploadFile(input); } } this._button.reset(); }, _uploadFileList: function(files){ for (var i=0; i this._options.sizeLimit){ this._error('sizeError', name); return false; } else if (size && size < this._options.minSizeLimit){ this._error('minSizeError', name); return false; } return true; }, _error: function(code, fileName){ var message = this._options.messages[code]; function r(name, replacement){ message = message.replace(name, replacement); } r('{file}', this._formatFileName(fileName)); r('{extensions}', this._options.allowedExtensions.join(', ')); r('{sizeLimit}', this._formatSize(this._options.sizeLimit)); r('{minSizeLimit}', this._formatSize(this._options.minSizeLimit)); this._options.showMessage(message); }, _formatFileName: function(name){ if (name.length > 33){ name = name.slice(0, 19) + '...' + name.slice(-13); } return name; }, _isAllowedExtension: function(fileName){ var ext = (-1 !== fileName.indexOf('.')) ? fileName.replace(/.*[.]/, '').toLowerCase() : ''; var allowed = this._options.allowedExtensions; if (!allowed.length){return true;} for (var i=0; i 99); return Math.max(bytes, 0.1).toFixed(1) + ['kB', 'MB', 'GB', 'TB', 'PB', 'EB'][i]; } }; /** * Class that creates upload widget with drag-and-drop and file list * @inherits qq.FileUploaderBasic */ qq.FileUploader = function(o){ // call parent constructor qq.FileUploaderBasic.apply(this, arguments); // additional options qq.extend(this._options, { element: null, // if set, will be used instead of qq-upload-list in template listElement: null, template: '
' + '
Drop files here to upload
' + '
Upload a file
' + '
    ' + '
    ', // template for one item in file list fileTemplate: '
  • ' + '' + '' + '' + 'Cancel' + 'Failed' + '
  • ', 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', 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' } }); // overwrite options with user supplied 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._setupDragDrop(); }; // inherit from Basic Uploader qq.extend(qq.FileUploader.prototype, qq.FileUploaderBasic.prototype); qq.extend(qq.FileUploader.prototype, { /** * Gets one of the elements listed in this._options.classes **/ _find: function(parent, type){ var element = qq.getByClass(parent, this._options.classes[type])[0]; if (!element){ throw new Error('element not found ' + type); } return element; }, _setupDragDrop: function(){ var self = this, dropArea = this._find(this._element, 'drop'); var dz = new qq.UploadDropZone({ element: dropArea, onEnter: function(e){ qq.addClass(dropArea, self._classes.dropActive); e.stopPropagation(); }, onLeave: function(e){ e.stopPropagation(); }, onLeaveNotDescendants: function(e){ qq.removeClass(dropArea, self._classes.dropActive); }, onDrop: function(e){ dropArea.style.display = 'none'; qq.removeClass(dropArea, self._classes.dropActive); self._uploadFileList(e.dataTransfer.files); } }); dropArea.style.display = 'none'; qq.attach(document, 'dragenter', function(e){ if (!dz._isValidFileDrag(e)) return; dropArea.style.display = 'block'; }); qq.attach(document, 'dragleave', function(e){ if (!dz._isValidFileDrag(e)) return; var relatedTarget = document.elementFromPoint(e.clientX, e.clientY); // only fire when leaving document out if ( ! relatedTarget || relatedTarget.nodeName == "HTML"){ dropArea.style.display = 'none'; } }); }, _onSubmit: function(id, fileName){ qq.FileUploaderBasic.prototype._onSubmit.apply(this, arguments); this._addToList(id, fileName); }, _onProgress: function(id, fileName, loaded, total){ qq.FileUploaderBasic.prototype._onProgress.apply(this, arguments); var item = this._getItemByFileId(id); var size = this._find(item, 'size'); size.style.display = 'inline'; var text; if (loaded != total){ text = Math.round(loaded / total * 100) + '% from ' + this._formatSize(total); } else { text = this._formatSize(total); } qq.setText(size, text); }, _onComplete: function(id, fileName, result){ qq.FileUploaderBasic.prototype._onComplete.apply(this, arguments); // mark completed var item = this._getItemByFileId(id); qq.remove(this._find(item, 'cancel')); qq.remove(this._find(item, 'spinner')); if (result.success){ qq.addClass(item, this._classes.success); } else { qq.addClass(item, this._classes.fail); } }, _addToList: function(id, fileName){ var item = qq.toElement(this._options.fileTemplate); item.qqFileId = id; var fileElement = this._find(item, 'file'); qq.setText(fileElement, this._formatFileName(fileName)); this._find(item, 'size').style.display = 'none'; this._listElement.appendChild(item); }, _getItemByFileId: function(id){ var item = this._listElement.firstChild; // there can't be txt nodes in dynamically created list // and we can use nextSibling while (item){ if (item.qqFileId == id) return item; item = item.nextSibling; } }, /** * delegate click event for cancel link **/ _bindCancelEvent: function(){ var self = this, list = this._listElement; qq.attach(list, 'click', function(e){ e = e || window.event; var target = e.target || e.srcElement; if (qq.hasClass(target, self._classes.cancel)){ qq.preventDefault(e); var item = target.parentNode; self._handler.cancel(item.qqFileId); qq.remove(item); } }); } }); qq.UploadDropZone = function(o){ this._options = { element: null, onEnter: function(e){}, onLeave: function(e){}, // is not fired when leaving element by hovering descendants onLeaveNotDescendants: function(e){}, onDrop: function(e){} }; qq.extend(this._options, o); this._element = this._options.element; this._disableDropOutside(); this._attachEvents(); }; qq.UploadDropZone.prototype = { _disableDropOutside: function(e){ // run only once for all instances if (!qq.UploadDropZone.dropOutsideDisabled ){ qq.attach(document, 'dragover', function(e){ if (e.dataTransfer){ e.dataTransfer.dropEffect = 'none'; e.preventDefault(); } }); qq.UploadDropZone.dropOutsideDisabled = true; } }, _attachEvents: function(){ var self = this; qq.attach(self._element, 'dragover', function(e){ if (!self._isValidFileDrag(e)) return; var effect = e.dataTransfer.effectAllowed; if (effect == 'move' || effect == 'linkMove'){ e.dataTransfer.dropEffect = 'move'; // for FF (only move allowed) } else { e.dataTransfer.dropEffect = 'copy'; // for Chrome } e.stopPropagation(); e.preventDefault(); }); qq.attach(self._element, 'dragenter', function(e){ if (!self._isValidFileDrag(e)) return; self._options.onEnter(e); }); qq.attach(self._element, 'dragleave', function(e){ if (!self._isValidFileDrag(e)) return; self._options.onLeave(e); var relatedTarget = document.elementFromPoint(e.clientX, e.clientY); // do not fire when moving a mouse over a descendant if (qq.contains(this, relatedTarget)) return; self._options.onLeaveNotDescendants(e); }); qq.attach(self._element, 'drop', function(e){ if (!self._isValidFileDrag(e)) return; e.preventDefault(); self._options.onDrop(e); }); }, _isValidFileDrag: function(e){ var dt = e.dataTransfer, // do not check dt.types.contains in webkit, because it crashes safari 4 isWebkit = navigator.userAgent.indexOf("AppleWebKit") > -1; // dt.effectAllowed is none in Safari 5 // dt.types.contains check is for firefox return dt && dt.effectAllowed != 'none' && (dt.files || (!isWebkit && dt.types.contains && dt.types.contains('Files'))); } }; qq.UploadButton = function(o){ this._options = { element: null, // if set to true adds multiple attribute to file input multiple: false, // name attribute of file input name: 'file', onChange: function(input){}, hoverClass: 'qq-upload-button-hover', focusClass: 'qq-upload-button-focus' }; qq.extend(this._options, o); this._element = this._options.element; // make button suitable container for input qq.css(this._element, { position: 'relative', overflow: 'hidden', // Make sure browse button is in the right side // in Internet Explorer direction: 'ltr' }); this._input = this._createInput(); }; qq.UploadButton.prototype = { /* returns file input element */ getInput: function(){ return this._input; }, /* cleans/recreates the file input */ reset: function(){ if (this._input.parentNode){ qq.remove(this._input); } qq.removeClass(this._element, this._options.focusClass); this._input = this._createInput(); }, _createInput: function(){ var input = document.createElement("input"); if (this._options.multiple){ input.setAttribute("multiple", "multiple"); } input.setAttribute("type", "file"); input.setAttribute("name", this._options.name); qq.css(input, { position: 'absolute', // in Opera only 'browse' button // is clickable and it is located at // the right side of the input right: 0, top: 0, fontFamily: 'Arial', // 4 persons reported this, the max values that worked for them were 243, 236, 236, 118 fontSize: '118px', margin: 0, padding: 0, cursor: 'pointer', opacity: 0 }); this._element.appendChild(input); var self = this; qq.attach(input, 'change', function(){ self._options.onChange(input); }); qq.attach(input, 'mouseover', function(){ qq.addClass(self._element, self._options.hoverClass); }); qq.attach(input, 'mouseout', function(){ qq.removeClass(self._element, self._options.hoverClass); }); qq.attach(input, 'focus', function(){ qq.addClass(self._element, self._options.focusClass); }); qq.attach(input, 'blur', function(){ qq.removeClass(self._element, self._options.focusClass); }); // IE and Opera, unfortunately have 2 tab stops on file input // which is unacceptable in our case, disable keyboard access if (window.attachEvent){ // it is IE or Opera input.setAttribute('tabIndex', "-1"); } return input; } }; /** * Class for uploading files, uploading itself is handled by child classes */ qq.UploadHandlerAbstract = function(o){ this._options = { debug: false, action: '/upload.php', // maximum number of concurrent uploads maxConnections: 999, onProgress: function(id, fileName, loaded, total){}, onComplete: function(id, fileName, response){}, onCancel: function(id, fileName){} }; qq.extend(this._options, o); this._queue = []; // params for files in queue this._params = []; }; qq.UploadHandlerAbstract.prototype = { log: function(str){ if (this._options.debug && window.console) console.log('[uploader] ' + str); }, /** * Adds file or file input to the queue * @returns id **/ add: function(file){}, /** * Sends the file identified by id and additional query params to the server */ upload: function(id, params){ var len = this._queue.push(id); var copy = {}; qq.extend(copy, params); this._params[id] = copy; // if too many active uploads, wait... if (len <= this._options.maxConnections){ this._upload(id, this._params[id]); } }, /** * Cancels file upload by id */ cancel: function(id){ this._cancel(id); this._dequeue(id); }, /** * Cancells all uploads */ cancelAll: function(){ for (var i=0; i= max && i < max){ var nextId = this._queue[max-1]; this._upload(nextId, this._params[nextId]); } } }; /** * Class for uploading files using form and iframe * @inherits qq.UploadHandlerAbstract */ qq.UploadHandlerForm = function(o){ qq.UploadHandlerAbstract.apply(this, arguments); this._inputs = {}; }; // @inherits qq.UploadHandlerAbstract qq.extend(qq.UploadHandlerForm.prototype, qq.UploadHandlerAbstract.prototype); qq.extend(qq.UploadHandlerForm.prototype, { add: function(fileInput){ fileInput.setAttribute('name', 'qqfile'); var id = 'qq-upload-handler-iframe' + qq.getUniqueId(); this._inputs[id] = fileInput; // remove file input from DOM if (fileInput.parentNode){ qq.remove(fileInput); } return id; }, getName: function(id){ // get input value and remove path to normalize return this._inputs[id].value.replace(/.*(\/|\\)/, ""); }, _cancel: function(id){ this._options.onCancel(id, this.getName(id)); delete this._inputs[id]; var iframe = document.getElementById(id); if (iframe){ // to cancel request set src to something else // we use src="javascript:false;" because it doesn't // trigger ie6 prompt on https iframe.setAttribute('src', 'javascript:false;'); qq.remove(iframe); } }, _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 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; }, _attachLoadEvent: function(iframe, callback){ qq.attach(iframe, 'load', function(){ // when we remove iframe from dom // the request stops, but in IE load // event fires if (!iframe.parentNode){ return; } // fixing Opera 10.53 if (iframe.contentDocument && iframe.contentDocument.body && iframe.contentDocument.body.innerHTML == "false"){ // In Opera event is fired second time // when body.innerHTML changed from false // to server response approx. after 1 sec // when we upload file with iframe return; } callback(); }); }, /** * Returns json object received by iframe from server. */ _getIframeContentJSON: function(iframe){ // iframe.contentWindow.document - for IE<7 var doc = iframe.contentDocument ? iframe.contentDocument: iframe.contentWindow.document, response; this.log("converting iframe's innerHTML to JSON"); this.log("innerHTML = " + doc.body.innerHTML); try { response = eval("(" + doc.body.innerHTML + ")"); } catch(err){ response = {}; } return response; }, /** * Creates iframe with unique name */ _createIframe: function(id){ // We can't use following code as the name attribute // won't be properly registered in IE6, and new window // on form submit will open // var iframe = document.createElement('iframe'); // iframe.setAttribute('name', id); var iframe = qq.toElement(''; } else if ( vimeoUrl ) { qs = ui.parseUri( url, { 'autoplay' : ( plugin.settings.autoplayVideos ? '1' : '0' ), 'byline' : '0', 'portrait' : '0', 'color': plugin.settings.vimeoColor }); iframe = ''; } else { iframe = ''; } return '
    ' + iframe + '
    '; }, /** * Load image */ loadMedia : function ( src, callback ) { // Inline content if ( src.trim().indexOf('#') === 0 ) { callback.call( $('
    ', { 'class' : 'swipebox-inline-container' }) .append( $(src) .clone() .toggleClass( plugin.settings.toggleClassOnLoad ) ) ); } // Everything else else { if ( ! this.isVideo( src ) ) { var img = $( '' ).on( 'load', function() { callback.call( img ); } ); img.attr( 'src', src ); } } }, /** * Get next slide */ getNext : function () { var $this = this, src, index = $( '#swipebox-slider .slide' ).index( $( '#swipebox-slider .slide.current' ) ); if ( index + 1 < elements.length ) { src = $( '#swipebox-slider .slide' ).eq( index ).contents().find( 'iframe' ).attr( 'src' ); $( '#swipebox-slider .slide' ).eq( index ).contents().find( 'iframe' ).attr( 'src', src ); index++; $this.setSlide( index ); $this.preloadMedia( index+1 ); if ( plugin.settings.nextSlide ) { plugin.settings.nextSlide(index); } } else { if ( plugin.settings.loopAtEnd === true ) { src = $( '#swipebox-slider .slide' ).eq( index ).contents().find( 'iframe' ).attr( 'src' ); $( '#swipebox-slider .slide' ).eq( index ).contents().find( 'iframe' ).attr( 'src', src ); index = 0; $this.preloadMedia( index ); $this.setSlide( index ); $this.preloadMedia( index + 1 ); if ( plugin.settings.nextSlide ) { plugin.settings.nextSlide(index); } } else { $( '#swipebox-overlay' ).addClass( 'rightSpring' ); setTimeout( function() { $( '#swipebox-overlay' ).removeClass( 'rightSpring' ); }, 500 ); } } }, /** * Get previous slide */ getPrev : function () { var index = $( '#swipebox-slider .slide' ).index( $( '#swipebox-slider .slide.current' ) ), src; if ( index > 0 ) { src = $( '#swipebox-slider .slide' ).eq( index ).contents().find( 'iframe').attr( 'src' ); $( '#swipebox-slider .slide' ).eq( index ).contents().find( 'iframe' ).attr( 'src', src ); index--; this.setSlide( index ); this.preloadMedia( index-1 ); if ( plugin.settings.prevSlide ) { plugin.settings.prevSlide(index); } } else { $( '#swipebox-overlay' ).addClass( 'leftSpring' ); setTimeout( function() { $( '#swipebox-overlay' ).removeClass( 'leftSpring' ); }, 500 ); } }, /* jshint unused:false */ nextSlide : function ( index ) { // Callback for next slide }, prevSlide : function ( index ) { // Callback for prev slide }, /** * Close */ closeSlide : function () { $( 'html' ).removeClass( 'swipebox-html' ); $( 'html' ).removeClass( 'swipebox-touch' ); $( window ).trigger( 'resize' ); this.destroy(); }, /** * Destroy the whole thing */ destroy : function () { $( window ).unbind( 'keyup' ); $( 'body' ).unbind( 'touchstart' ); $( 'body' ).unbind( 'touchmove' ); $( 'body' ).unbind( 'touchend' ); $( '#swipebox-slider' ).unbind(); $( '#swipebox-overlay' ).remove(); if ( ! $.isArray( elem ) ) { elem.removeData( '_swipebox' ); } if ( this.target ) { this.target.trigger( 'swipebox-destroy' ); } $.swipebox.isOpen = false; if ( plugin.settings.afterClose ) { plugin.settings.afterClose(); } } }; plugin.init(); }; $.fn.swipebox = function( options ) { if ( ! $.data( this, '_swipebox' ) ) { var swipebox = new $.swipebox( this, options ); this.data( '_swipebox', swipebox ); } return this.data( '_swipebox' ); }; }( window, document, jQuery ) ); jQuery(function () { /** * Add a quicklink to the media popup */ function gallery_plugin() { var $opts = jQuery('#media__opts'); if (!$opts.length) return; if (!window.opener) return; var glbl = document.createElement('label'); var glnk = document.createElement('a'); var gbrk = document.createElement('br'); glnk.name = 'gallery_plugin'; glnk.innerHTML = LANG.plugins.gallery.addgal; //FIXME localize glnk.style.cursor = 'pointer'; glnk.onclick = function () { var $h1 = jQuery('#media__ns'); if (!$h1.length) return; var ns = $h1[0].innerHTML; opener.insertAtCarret('wiki__text', '{{gallery>' + ns + '}}'); if (!dw_mediamanager.keepopen) window.close(); }; $opts[0].appendChild(glbl); glbl.appendChild(glnk); $opts[0].appendChild(gbrk); } /** * Display a selected page and hide all others */ function gallery_pageselect(e) { var galid = e.target.hash.substr(10, 4); var $pages = jQuery('div.gallery__' + galid); $pages.hide(); jQuery('#' + e.target.hash.substr(1)).show(); return false; } // === main === // initialize the lightbox mechanism jQuery("a.lightbox, a[rel^='lightbox']").swipebox({ loopAtEnd: true }); gallery_plugin(); // hide all pages except the first one var $pages = jQuery('div.gallery_page'); $pages.hide(); $pages.eq(0).show(); // attach page selector jQuery('a.gallery_pgsel').click(gallery_pageselect); }); /* XXXXXXXXXX end of lib/plugins/gallery/script.js XXXXXXXXXX */ /* XXXXXXXXXX begin of lib/plugins/imagereference/script.js XXXXXXXXXX */ /** * Extends toolbar * Image captions: * - copy url from image to magnify button * - try copy image title to caption * - try copy alignment of image to caption * - resize box to width of image */ if (window.toolbar !== undefined) { toolbar[toolbar.length] = { "type": "format", "title": "Adds an ImageCaption tag", "icon": "../../plugins/imagereference/button.png", "key": "", "open": "", "close": "" }; toolbar[toolbar.length] = { "type": "format", "title": "Adds an ImageReference tag", "icon": "../../plugins/imagereference/refbutton.png", "key": "", "open": "" }; } jQuery(function () { // captions of images jQuery('span.imgcaption').each(function () { let $imgcaption = jQuery(this); let $amedia = $imgcaption.find('a.media'); let $img = $imgcaption.find('img'); //copy img url to magnify button if ($amedia[0]) { let link = $amedia.attr('href'); $imgcaption.find('span.undercaption a').last() .attr('href', link)//set link .children().show(); //display button } //copy possibly img title when no caption is set let captionparts = $imgcaption.find('span.undercaption').text().split(':', 2); if (!jQuery.trim(captionparts[1])) { let title = $img.attr('title'); if (title) { $imgcaption.find('span.undercaption a').first().before(': ' + title); } } //apply alignment of image to imgcaption if (!($imgcaption.hasClass('left') || $imgcaption.hasClass('right') || $imgcaption.hasClass('center'))) { if ($img.hasClass('medialeft')) { $imgcaption.addClass('left'); } else if ($img.hasClass('mediaright')) { $imgcaption.addClass('right'); } else if ($img.hasClass('mediacenter')) { $imgcaption.addClass('center'); } } //add wrapper to center imgcaption if ($imgcaption.hasClass('center')) { $imgcaption.wrap(''); } // width is still zero if called from jQuery.ready() because image is not yet loaded. // Sets correct size of caption after loading image $img.on("load", function(){ let width = jQuery(this).width(); $imgcaption.width((width + 8) + "px"); }); }); // // captions of tables // jQuery('div.tabcaption').each(function() { // let $imgcaption = jQuery(this); // // //add wrapper to center imgcaption // if ($imgcaption.hasClass('center')) { // $imgcaption.wrap(''); // } // }); }); /* XXXXXXXXXX end of lib/plugins/imagereference/script.js XXXXXXXXXX */ /* XXXXXXXXXX begin of lib/plugins/include/script.js XXXXXXXXXX */ /** * Javascript functionality for the include plugin */ /** * Highlight the included section when hovering over the appropriate include edit button * * @author Andreas Gohr * @author Michael Klier * @author Michael Hamann */ jQuery(function() { jQuery('.btn_incledit') .mouseover(function () { jQuery(this).closest('.plugin_include_content').addClass('section_highlight'); }) .mouseout(function () { jQuery('.section_highlight').removeClass('section_highlight'); }); }); // vim:ts=4:sw=4:et: /* XXXXXXXXXX end of lib/plugins/include/script.js XXXXXXXXXX */ /* XXXXXXXXXX begin of lib/plugins/logviewer/script.js XXXXXXXXXX */ /** * Scroll to the end of the log on load */ jQuery(function () { var $dl = jQuery('#plugin__logviewer').find('dl'); if (!$dl.length) return; $dl.animate({scrollTop: $dl.prop("scrollHeight")}, 500); var $filter = jQuery(''); $filter.on('keyup', function (e) { var re = new RegExp($filter.val(), 'i'); $dl.find('dt').each(function (idx, elem) { if (elem.innerText.match(re)) { jQuery(elem).removeClass('hidden'); } else { jQuery(elem).addClass('hidden'); } }); }); $dl.before($filter); $filter.wrap(''); $filter.before(LANG.plugins.logviewer.filter + ' '); }); /* XXXXXXXXXX end of lib/plugins/logviewer/script.js XXXXXXXXXX */ /* XXXXXXXXXX begin of lib/plugins/move/script.js XXXXXXXXXX */ /** * includes all needed JavaScript for the move plugin * * be sure to touch this file when one of the scripts has been updated to refresh caching */ /* json2.js 2013-05-26 Public Domain. NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. See http://www.JSON.org/js.html This code should be minified before deployment. See http://javascript.crockford.com/jsmin.html USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO NOT CONTROL. This file creates a global JSON object containing two methods: stringify and parse. JSON.stringify(value, replacer, space) value any JavaScript value, usually an object or array. replacer an optional parameter that determines how object values are stringified for objects. It can be a function or an array of strings. space an optional parameter that specifies the indentation of nested structures. If it is omitted, the text will be packed without extra whitespace. If it is a number, it will specify the number of spaces to indent at each level. If it is a string (such as '\t' or ' '), it contains the characters used to indent at each level. This method produces a JSON text from a JavaScript value. When an object value is found, if the object contains a toJSON method, its toJSON method will be called and the result will be stringified. A toJSON method does not serialize: it returns the value represented by the name/value pair that should be serialized, or undefined if nothing should be serialized. The toJSON method will be passed the key associated with the value, and this will be bound to the value For example, this would serialize Dates as ISO strings. Date.prototype.toJSON = function (key) { function f(n) { // Format integers to have at least two digits. return n < 10 ? '0' + n : n; } return this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z'; }; You can provide an optional replacer method. It will be passed the key and value of each member, with this bound to the containing object. The value that is returned from your method will be serialized. If your method returns undefined, then the member will be excluded from the serialization. If the replacer parameter is an array of strings, then it will be used to select the members to be serialized. It filters the results such that only members with keys listed in the replacer array are stringified. Values that do not have JSON representations, such as undefined or functions, will not be serialized. Such values in objects will be dropped; in arrays they will be replaced with null. You can use a replacer function to replace those with JSON values. JSON.stringify(undefined) returns undefined. The optional space parameter produces a stringification of the value that is filled with line breaks and indentation to make it easier to read. If the space parameter is a non-empty string, then that string will be used for indentation. If the space parameter is a number, then the indentation will be that many spaces. Example: text = JSON.stringify(['e', {pluribus: 'unum'}]); // text is '["e",{"pluribus":"unum"}]' text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' text = JSON.stringify([new Date()], function (key, value) { return this[key] instanceof Date ? 'Date(' + this[key] + ')' : value; }); // text is '["Date(---current time---)"]' JSON.parse(text, reviver) This method parses a JSON text to produce an object or array. It can throw a SyntaxError exception. The optional reviver parameter is a function that can filter and transform the results. It receives each of the keys and values, and its return value is used instead of the original value. If it returns what it received, then the structure is not modified. If it returns undefined then the member is deleted. Example: // Parse the text. Values that look like ISO date strings will // be converted to Date objects. myData = JSON.parse(text, function (key, value) { var a; if (typeof value === 'string') { a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); if (a) { return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6])); } } return value; }); myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { var d; if (typeof value === 'string' && value.slice(0, 5) === 'Date(' && value.slice(-1) === ')') { d = new Date(value.slice(5, -1)); if (d) { return d; } } return value; }); This is a reference implementation. You are free to copy, modify, or redistribute. */ /*jslint evil: true, regexp: true */ /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, lastIndex, length, parse, prototype, push, replace, slice, stringify, test, toJSON, toString, valueOf */ // Create a JSON object only if one does not already exist. We create the // methods in a closure to avoid creating global variables. if (typeof JSON !== 'object') { JSON = {}; } (function () { 'use strict'; function f(n) { // Format integers to have at least two digits. return n < 10 ? '0' + n : n; } if (typeof Date.prototype.toJSON !== 'function') { Date.prototype.toJSON = function () { return isFinite(this.valueOf()) ? this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z' : null; }; String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function () { return this.valueOf(); }; } var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, gap, indent, meta = { // table of character substitutions '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\' }, rep; function quote(string) { // If the string contains no control characters, no quote characters, and no // backslash characters, then we can safely slap some quotes around it. // Otherwise we must also replace the offending characters with safe escape // sequences. escapable.lastIndex = 0; return escapable.test(string) ? '"' + string.replace(escapable, function (a) { var c = meta[a]; return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }) + '"' : '"' + string + '"'; } function str(key, holder) { // Produce a string from holder[key]. var i, // The loop counter. k, // The member key. v, // The member value. length, mind = gap, partial, value = holder[key]; // If the value has a toJSON method, call it to obtain a replacement value. if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); } // If we were called with a replacer function, then call the replacer to // obtain a replacement value. if (typeof rep === 'function') { value = rep.call(holder, key, value); } // What happens next depends on the value's type. switch (typeof value) { case 'string': return quote(value); case 'number': // JSON numbers must be finite. Encode non-finite numbers as null. return isFinite(value) ? String(value) : 'null'; case 'boolean': case 'null': // If the value is a boolean or null, convert it to a string. Note: // typeof null does not produce 'null'. The case is included here in // the remote chance that this gets fixed someday. return String(value); // If the type is 'object', we might be dealing with an object or an array or // null. case 'object': // Due to a specification blunder in ECMAScript, typeof null is 'object', // so watch out for that case. if (!value) { return 'null'; } // Make an array to hold the partial results of stringifying this object value. gap += indent; partial = []; // Is the value an array? if (Object.prototype.toString.apply(value) === '[object Array]') { // The value is an array. Stringify every element. Use null as a placeholder // for non-JSON values. length = value.length; for (i = 0; i < length; i += 1) { partial[i] = str(i, value) || 'null'; } // Join all of the elements together, separated with commas, and wrap them in // brackets. v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']'; gap = mind; return v; } // If the replacer is an array, use it to select the members to be stringified. if (rep && typeof rep === 'object') { length = rep.length; for (i = 0; i < length; i += 1) { if (typeof rep[i] === 'string') { k = rep[i]; v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } else { // Otherwise, iterate through all of the keys in the object. for (k in value) { if (Object.prototype.hasOwnProperty.call(value, k)) { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } // Join all of the member texts together, separated with commas, // and wrap them in braces. v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}'; gap = mind; return v; } } // If the JSON object does not yet have a stringify method, give it one. if (typeof JSON.stringify !== 'function') { JSON.stringify = function (value, replacer, space) { // The stringify method takes a value and an optional replacer, and an optional // space parameter, and returns a JSON text. The replacer can be a function // that can replace values, or an array of strings that will select the keys. // A default replacer method can be provided. Use of the space parameter can // produce text that is more easily readable. var i; gap = ''; indent = ''; // If the space parameter is a number, make an indent string containing that // many spaces. if (typeof space === 'number') { for (i = 0; i < space; i += 1) { indent += ' '; } // If the space parameter is a string, it will be used as the indent string. } else if (typeof space === 'string') { indent = space; } // If there is a replacer, it must be a function or an array. // Otherwise, throw an error. rep = replacer; if (replacer && typeof replacer !== 'function' && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) { throw new Error('JSON.stringify'); } // Make a fake root object containing our value under the key of ''. // Return the result of stringifying the value. return str('', {'': value}); }; } // If the JSON object does not yet have a parse method, give it one. if (typeof JSON.parse !== 'function') { JSON.parse = function (text, reviver) { // The parse method takes a text and an optional reviver function, and returns // a JavaScript value if the text is a valid JSON text. var j; function walk(holder, key) { // The walk method is used to recursively walk the resulting structure so // that modifications can be made. var k, v, value = holder[key]; if (value && typeof value === 'object') { for (k in value) { if (Object.prototype.hasOwnProperty.call(value, k)) { v = walk(value, k); if (v !== undefined) { value[k] = v; } else { delete value[k]; } } } } return reviver.call(holder, key, value); } // Parsing happens in four stages. In the first stage, we replace certain // Unicode characters with escape sequences. JavaScript handles many characters // incorrectly, either silently deleting them, or treating them as line endings. text = String(text); cx.lastIndex = 0; if (cx.test(text)) { text = text.replace(cx, function (a) { return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }); } // In the second stage, we run the text against regular expressions that look // for non-JSON patterns. We are especially concerned with '()' and 'new' // because they can cause invocation, and '=' because it can cause mutation. // But just to be safe, we want to reject all unexpected forms. // We split the second stage into 4 regexp operations in order to work around // crippling inefficiencies in IE's and Safari's regexp engines. First we // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we // replace all simple value tokens with ']' characters. Third, we delete all // open brackets that follow a colon or comma or that begin the text. Finally, // we look to see that the remaining characters are only whitespace or ']' or // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. if (/^[\],:{}\s]*$/ .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { // In the third stage we use the eval function to compile the text into a // JavaScript structure. The '{' operator is subject to a syntactic ambiguity // in JavaScript: it can begin a block or an object literal. We wrap the text // in parens to eliminate the ambiguity. j = eval('(' + text + ')'); // In the optional fourth stage, we recursively walk the new structure, passing // each name/value pair to a reviver function for possible transformation. return typeof reviver === 'function' ? walk({'': j}, '') : j; } // If the text is not JSON parseable, then a SyntaxError is thrown. throw new SyntaxError('JSON.parse'); }; } }()); jQuery(function() { jQuery('form.plugin_move_form').each(function(){ var $form = jQuery(this); $form.find('.click-page').click(function() { $form.find('input[name=dst]').val($form.find('.click-page code').text()); $form.find('.select').hide(); }).click(); $form.find('.click-ns').click(function() { $form.find('input[name=dst]').val($form.find('.click-ns code').text()); $form.find('.select').show(); }); }); jQuery('#plugin_move__progress').each(function () { var $this = jQuery(this); // initialize the progress bar var $progressbar = $this.find('.progress'); $progressbar.html(''); $progressbar.progressbar({ value: $progressbar.data('progress') }); /** * Set visibility of buttons according to current error state * * @param isError */ var setButtons = function(isError) { $this.find('.ctlfrm-start').addClass('hide'); if(isError) { $this.find('.ctlfrm-skip').removeClass('hide'); $this.find('.ctlfrm-retry').removeClass('hide'); $this.find('.ctlfrm-continue').addClass('hide'); }else { $this.find('.ctlfrm-skip').addClass('hide'); $this.find('.ctlfrm-retry').addClass('hide'); $this.find('.ctlfrm-continue').addClass('hide'); } }; /** * Execute the next steps * * @param {bool} skip should an error be skipped? */ var nextStep = function(skip) { // clear error output $this.find('.output').html(''); $this.find('.controls img').removeClass('hide'); setButtons(false); // execute AJAX jQuery.post( DOKU_BASE + 'lib/exe/ajax.php', { call: 'plugin_move_progress', skip: skip }, function (data) { $progressbar.progressbar('option', 'value', data.progress); $this.find('.controls img').addClass('hide'); if (data.error) { $this.find('.output').html('

    ' + data.error + '

    '); setButtons(true); } else if (data.complete) { $progressbar.progressbar('option', 'value', 100); // redirect to start page alert(LANG.plugins.move.complete); window.location.href = DOKU_BASE; } else { // do it again nextStep(skip); } } ); }; // attach AJAX actions to buttons $this.find('.ctl-continue').click(function (e) { e.preventDefault(); // move in progress, no more preview jQuery('#plugin_move__preview').remove(); // should the next error be skipped? var skip = e.target.form.skip.value; // step on it nextStep(skip); }); }); // hide preview list on namespace move jQuery('#plugin_move__preview').each(function () { var $this = jQuery(this); $this.find('ul').hide(); $this.find('span') .click(function () { $this.find('ul').dw_toggle(); $this.find('span').toggleClass('closed'); }) .addClass('closed'); }); /** * Script for the tree management interface */ var $GUI = jQuery('#plugin_move__tree'); $GUI.show(); jQuery('#plugin_move__treelink').show(); /** * Checks if the given list item was moved in the tree * * Moved elements are highlighted and a title shows where they came from * * @param {jQuery} $li */ var checkForMovement = function ($li) { // we need to check this LI and all previously moved sub LIs var $all = $li.add($li.find('li.moved')); $all.each(function () { var $this = jQuery(this); var oldid = $this.data('id'); var newid = determineNewID($this); if (newid != oldid && !$this.hasClass('created')) { $this.addClass('moved'); $this.children('div').attr('title', oldid + ' -> ' + newid); } else { $this.removeClass('moved'); $this.children('div').attr('title', ''); } }); }; /** * Check if the given name is allowed in the given parent * * @param {jQuery} $li the edited or moved LI * @param {jQuery} $parent the (new) parent of the edited or moved LI * @param {string} name the (new) name to check * @returns {boolean} */ var checkNameAllowed = function ($li, $parent, name) { var ok = true; $parent.children('li').each(function () { if (this === $li[0]) return; var cname = 'type-f'; if ($li.hasClass('type-d')) cname = 'type-d'; var $this = jQuery(this); if ($this.data('name') == name && $this.hasClass(cname)) ok = false; }); return ok; }; /** * Returns the new ID of a given list item * * @param {jQuery} $li * @returns {string} */ var determineNewID = function ($li) { var myname = $li.data('name'); var $parent = $li.parent().closest('li'); if ($parent.length) { return (determineNewID($parent) + ':' + myname).replace(/^:/, ''); } else { return myname; } }; /** * Very simplistic cleanID() in JavaScript * * Strips out namespaces * * @param {string} id */ var cleanID = function (id) { if (!id) return ''; id = id.replace(/[!"#$%§&\'()+,/;<=>?@\[\]^`\{|\}~\\;:\/\*]+/g, '_'); id = id.replace(/^_+/, ''); id = id.replace(/_+$/, ''); id = id.toLowerCase(); return id; }; /** * Initialize the drag & drop-tree at the given li (must be this). */ var initTree = function () { var $li = jQuery(this); var my_root = $li.closest('.tree_root')[0]; $li.draggable({ revert: true, revertDuration: 0, opacity: 0.5, stop : function(event, ui) { ui.helper.css({height: "auto", width: "auto"}); } }).droppable({ tolerance: 'pointer', greedy: true, accept : function(draggable) { return my_root == draggable.closest('.tree_root')[0]; }, drop : function (event, ui) { var $dropped = ui.draggable; var $me = jQuery(this); if ($dropped.children('div.li').children('input').prop('checked')) { $dropped = $dropped.add( jQuery(my_root) .find('input') .filter(function() { return jQuery(this).prop('checked'); }).parent().parent() ); } if ($me.parents().addBack().is($dropped)) { return; } var insert_child = !($me.hasClass("type-f") || $me.hasClass("closed")); var $new_parent = insert_child ? $me.children('ul') : $me.parent(); var allowed = true; $dropped.each(function () { var $this = jQuery(this); allowed &= checkNameAllowed($this, $new_parent, $this.data('name')); }); if (allowed) { if (insert_child) { $dropped.prependTo($new_parent); } else { $dropped.insertAfter($me); } } checkForMovement($dropped); } }) // add title to rename icon .find('img.rename').attr('title', LANG.plugins.move.renameitem) .end() .find('img.add').attr('title', LANG.plugins.move.add); }; var add_template = '
    • '; /** * Attach event listeners to the tree */ $GUI.find('div.tree_root > ul.tree_list') .click(function (e) { var $clicky = jQuery(e.target); var $li = $clicky.parent().parent(); if ($clicky[0].tagName == 'A' && $li.hasClass('type-d')) { // Click on folder - open and close via AJAX e.stopPropagation(); if ($li.hasClass('open')) { $li .removeClass('open') .addClass('closed'); } else { $li .removeClass('closed') .addClass('open'); // if had not been loaded before, load via AJAX if (!$li.find('ul').length) { var is_media = $li.closest('div.tree_root').hasClass('tree_media') ? 1 : 0; jQuery.post( DOKU_BASE + 'lib/exe/ajax.php', { call: 'plugin_move_tree', ns: $clicky.attr('href'), is_media: is_media }, function (data) { $li.append(data); $li.find('li').each(initTree); } ); } } e.preventDefault(); } else if ($clicky[0].tagName == 'IMG') { // Click on IMG - do rename e.stopPropagation(); var $a = $clicky.parent().find('a'); if ($clicky.hasClass('rename')) { var newname = window.prompt(LANG.plugins.move.renameitem, $li.data('name')); newname = cleanID(newname); if (newname) { if (checkNameAllowed($li, $li.parent(), newname)) { $li.data('name', newname); $a.text(newname); checkForMovement($li); } else { alert(LANG.plugins.move.duplicate.replace('%s', newname)); } } } else { var newname = window.prompt(LANG.plugins.move.add); newname = cleanID(newname); if (newname) { if (checkNameAllowed($li, $li.children('ul'), newname)) { var $new_li = jQuery(add_template.replace(/%s/g, newname)); $li.children('ul').prepend($new_li); $new_li.each(initTree); } else { alert(LANG.plugins.move.duplicate.replace('%s', newname)); } } } e.preventDefault(); } }).find('li').each(initTree); /** * Gather all moves from the trees and put them as JSON into the form before submit * * @fixme has some duplicate code */ jQuery('#plugin_move__tree_execute').submit(function (e) { var data = []; $GUI.find('.tree_pages .moved').each(function (idx, el) { var $el = jQuery(el); var newid = determineNewID($el); data[data.length] = { 'class': $el.hasClass('type-d') ? 'ns' : 'doc', type: 'page', src: $el.data('id'), dst: newid }; }); $GUI.find('.tree_media .moved').each(function (idx, el) { var $el = jQuery(el); var newid = determineNewID($el); data[data.length] = { 'class': $el.hasClass('type-d') ? 'ns' : 'doc', type: 'media', src: $el.data('id'), dst: newid }; }); jQuery(this).find('input[name=json]').val(JSON.stringify(data)); }); /** * Rename dialog for end users * * @author Andreas Gohr */ (function () { if (!JSINFO || !JSINFO.move_renameokay) return; // basic dialog template const $dialog = jQuery( '
      ' + '
      ' + '' + '
      ' + '
      ' ); /** * Executes the renaming based on the form contents * @return {boolean} */ const renameFN = function () { const newid = $dialog.find('input[name=id]').val(); if (!newid) return false; // remove buttons and show throbber $dialog.html( ' ' + LANG.plugins.move.inprogress ); $dialog.dialog('option', 'buttons', []); // post the data jQuery.post( DOKU_BASE + 'lib/exe/ajax.php', { call: 'plugin_move_rename', id: JSINFO.id, newid: newid }, // redirect or display error function (result) { if (result.error) { $dialog.html(result.error.msg); } else { window.location.href = result.redirect_url; } } ); return false; }; /** * Create the actual dialog modal and show it */ const showDialog = function () { $dialog.dialog({ title: LANG.plugins.move.rename + ' ' + JSINFO.id, width: 800, height: 200, dialogClass: 'plugin_move_dialog', modal: true, buttons: [ { text: LANG.plugins.move.cancel, click: function () { $dialog.dialog("close"); } }, { text: LANG.plugins.move.rename, click: renameFN } ], // remove HTML from DOM again close: function () { jQuery(this).remove(); } }); $dialog.find('input[name=id]').val(JSINFO.id); $dialog.find('form').submit(renameFN); }; /** * Bind an event handler as the first handler * * @param {jQuery} $owner * @param {string} event * @param {function} handler * @link https://stackoverflow.com/a/4700103 */ const bindFirst = function ($owner, event, handler) { $owner.unbind(event, handler); $owner.bind(event, handler); const events = jQuery._data($owner[0])['events'][event]; events.unshift(events.pop()); jQuery._data($owner[0])['events'][event] = events; }; // attach handler to menu item jQuery('.plugin_move_page') .show() .click(function (e) { e.preventDefault(); showDialog(); }); // attach handler to mobile menu entry const $mobileMenuOption = jQuery('form select[name=do] option[value=plugin_move]'); if ($mobileMenuOption.length === 1) { bindFirst($mobileMenuOption.form().find('select[name=do]'), 'change', function (e) { const $select = jQuery(this); if ($select.val() !== 'plugin_move') return; e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); $select.val(''); showDialog(); }); } })(); }); /* XXXXXXXXXX end of lib/plugins/move/script.js XXXXXXXXXX */ /* XXXXXXXXXX begin of lib/plugins/styling/script.js XXXXXXXXXX */ jQuery(function () { /** * Function to reload the preview styles in the main window * * @param {Window} target the main window */ function applyPreview(target) { // remove style var $style = target.jQuery('link[rel=stylesheet][href*="lib/exe/css.php"]'); $style.attr('href', ''); // append the loader screen var $loader = target.jQuery('#plugin__styling_loader'); if (!$loader.length) { $loader = target.jQuery('
      ' + LANG.plugins.styling.loader + '
      '); $loader.css({ 'position': 'absolute', 'width': '100%', 'height': '100%', 'top': 0, 'left': 0, 'z-index': 5000, 'background-color': '#fff', 'opacity': '0.7', 'color': '#000', 'font-size': '2.5em', 'text-align': 'center', 'line-height': 1.5, 'padding-top': '2em' }); target.jQuery('body').append($loader); } // load preview in main window (timeout works around chrome updating CSS weirdness) setTimeout(function () { var now = new Date().getTime(); $style.attr('href', DOKU_BASE + 'lib/exe/css.php?preview=1&tseed=' + now); }, 500); } var doreload = 1; var $styling_plugin = jQuery('#plugin__styling'); // if we are not on the plugin page (either main or popup) if (!$styling_plugin.length) { // handle the preview cookie if(DokuCookie.getValue('styling_plugin') == 1) { applyPreview(window); } return; // nothing more to do here } /* ---- from here on we're in the popup or admin page ---- */ // add button on main page if (!$styling_plugin.hasClass('ispopup')) { var $form = $styling_plugin.find('form.styling').first(); var $btn = jQuery(''); $form.prepend($btn); $btn.on('click', function (e) { var windowFeatures = "menubar=no,location=no,resizable=yes,scrollbars=yes,status=false,width=500,height=500"; window.open(DOKU_BASE + 'lib/plugins/styling/popup.php', 'styling_popup', windowFeatures); e.preventDefault(); e.stopPropagation(); }).wrap('

      '); return; // we exit here if this is not the popup } /* ---- from here on we're in the popup only ---- */ // reload the main page on close window.onunload = function(e) { if(doreload) { DokuCookie.setValue('styling_plugin', 0); if(window.opener) window.opener.document.location.reload(); } return null; }; // don't reload on our own buttons jQuery(':button').click(function(e){ doreload = false; }); // on first load apply preview if(window.opener) applyPreview(window.opener); // enable the preview cookie DokuCookie.setValue('styling_plugin', 1); }); /* XXXXXXXXXX end of lib/plugins/styling/script.js XXXXXXXXXX */ /* XXXXXXXXXX begin of lib/plugins/svgembed/script.js XXXXXXXXXX */ function closeSVGWindow(targetWindow) { targetWindow.document.write('

      SVG file printed. Please close this window.

      '); targetWindow.close(); } function svgembed_printContent(path) { // Open window and load content var svgembed_print = window.open('', '_printwindow', 'location=no,height=400,width=600,scrollbars=yes,status=no'); svgembed_print.document.write(''); svgembed_print.document.close(); // Print setTimeout(function(){ svgembed_print.window.print(); }, 1000); setTimeout(function(){ closeSVGWindow(svgembed_print); }, 2000); } function svgembed_onMouseOver(object_id) { document.getElementById(object_id).className = document.getElementById(object_id).className + ' svgembed_print_border'; return false; } function svgembed_onMouseOut(object_id) { document.getElementById(object_id).className = document.getElementById(object_id).className.replace(' svgembed_print_border', ''); return false; } /* XXXXXXXXXX end of lib/plugins/svgembed/script.js XXXXXXXXXX */ /* XXXXXXXXXX begin of lib/plugins/tablelayout/script.js XXXXXXXXXX */ window.tablelayout = window.tablelayout || {}; (function (exports) { 'use strict'; var atomicrowIndex = null; exports.getNumberOfTableCols = function ($table) { var $rows = $table.find('tr'); var max = 0; $rows.each(function (index, row) { if (max < row.cells.length) { max = row.cells.length; atomicrowIndex = index; } }); return max; }; exports.floatTable = function ($table, direction) { if ($table.width() > jQuery('div.page').width()) { return; } var $parentDiv = $table.closest('div.table'); var $elements = jQuery([]); $elements = $elements.add($parentDiv.prev('div.plugin_tablelayout_placeholder')); $elements = $elements.add($parentDiv); $elements = $elements.add($parentDiv.next('div.secedit.editbutton_table')); $elements.wrapAll('
      '); $elements.parent('div.floatwrapper').addClass(direction); }; exports.applyStylesToTable = function ($table, layoutdata) { if (!layoutdata.colwidth) { layoutdata.colwidth = []; } exports.styleColumnWidths($table, layoutdata.colwidth); exports.fixColumnWidths($table); if (layoutdata.rowsHeader > 0 && layoutdata.rowsVisible > 0) { exports.freezeTableRows($table, layoutdata.rowsHeader, layoutdata.rowsVisible); } if (layoutdata.float === 'right' || layoutdata.float === 'left' || layoutdata.float === 'center') { exports.floatTable($table, layoutdata.float); } }; exports.fixColumnWidths = function ($table) { var $cols = $table.find('colgroup col'); var $atomicrow = $table.find('.row' + atomicrowIndex); $cols.each(function (index, col) { var width = $atomicrow['0'].cells.item(index).offsetWidth; if (!col.style.width) { jQuery(col).css('width', width); } }); $table.addClass('widthsfixed'); }; exports.styleColumnWidths = function ($table, colwidths) { var numCols = exports.getNumberOfTableCols($table); var $colgroup = jQuery(''); for (var i = 0; i < numCols; i += 1) { var $col = jQuery(''); if (colwidths[i]) { $col.css('width', colwidths[i]); } $colgroup.append($col); } $table.prepend($colgroup); if (colwidths.length === numCols) { // todo: should we throw an error if there are MORE widths defined than cols in the table? $table.addClass('flexiblewidth'); } }; exports.freezeTableRows = function ($table, rowsToFreeze, rowsVisible) { rowsToFreeze = parseInt(rowsToFreeze); rowsVisible = parseInt(rowsVisible); if ($table.find('tr').length <= rowsToFreeze + rowsVisible) { return; } var tableWidth = $table.width(); var $frozenTable = $table.clone(); $table.addClass('tablelayout_body'); $frozenTable.addClass('tablelayout_head'); var $frozenRows = $frozenTable.find('tr'); for (var i = $table.find('tr').length - 1; i >= rowsToFreeze; i -= 1) { jQuery($frozenRows[i]).remove(); } if (!$frozenTable.find('tbody').children().length) { $frozenTable.find('tbody').remove(); } var $tableRows = $table.find('tr'); for (i = 0; i < rowsToFreeze; i += 1) { jQuery($tableRows[i]).remove(); } $frozenTable.append($table.find('.searchSortRow')); if (!$table.find('thead').children().length) { $table.find('thead').remove(); } $table.parent().prepend($frozenTable); // move search above the table header if ($table.parent().hasClass('hasSearch')) { $table.parent().prepend($table.parent().find('.globalSearch')); } var SCROLLBAR_WIDTH = 17; $frozenTable.wrap(jQuery('
      ').width(tableWidth + SCROLLBAR_WIDTH)); var height = 0; for (i = rowsToFreeze; i < rowsToFreeze + rowsVisible; i += 1) { height += jQuery($tableRows[i]).height(); } var tableWrapper = jQuery('
      ').css({'overflow-y': 'scroll'}).height(height).width(tableWidth + SCROLLBAR_WIDTH); $table.wrap(tableWrapper); }; exports.initLayout = function (json) { var layout = {}; if (json) { layout = JSON.parse(json); } if (typeof layout.colwidth === 'undefined') { layout.colwidth = []; } return layout; }; exports.sortTable = function ($tableRows, sortColumnIndex, order) { var sortModifier = order === 'asc' ? 1 : -1; var compare = function compare(rowA, rowB) { var tda = jQuery(rowA).find('td,th').eq(sortColumnIndex).text().toLowerCase(); var tdb = jQuery(rowB).find('td,th').eq(sortColumnIndex).text().toLowerCase(); if (tda < tdb) { return -1 * sortModifier; } if (tda > tdb) { return sortModifier; } return 0; }; return $tableRows.sort(compare); }; /** * split all rowspans and colspans in a continuous set of table rows and multiply the content for all rows * * Please note that this functions modifies the argument as well. * * @param {jQuery[]} $tableRows jQuery set of continuoues table rows * * @return {jQuery[]} the adjust array of rows */ exports.splitMerges = function splitMerges($tableRows) { var $splitRows = $tableRows; $splitRows.find('td[colspan],th[colspan]').each(function (index, cell) { var $cell = jQuery(cell); var colspan = $cell.attr('colspan') - 1; $cell.removeAttr('colspan'); for (var i = 0; i < colspan; i += 1) { $cell.after($cell.clone(true, true)); } }); $splitRows.find('td[rowspan],th[rowspan]').each(function (index, cell) { var $cell = jQuery(cell); var rowspan = $cell.attr('rowspan') - 1; $cell.removeAttr('rowspan'); var colIndex = 0; $cell.prevAll('td,th').each(function () { colIndex += this.colSpan; }); for (var i = 0; i < rowspan; i += 1) { var $rowMissingCell = $cell.closest('tr').nextAll().eq(i); var $rowCells = $rowMissingCell.find('td,th'); if ($rowCells.length === colIndex) { $rowCells.last().after($cell.clone(true, true)); } else { $rowCells.eq(colIndex).before($cell.clone(true, true)); } } }); return $splitRows; }; return exports; }(window.tablelayout)); window.tablelayout = window.tablelayout || {}; jQuery(function () { 'use strict'; /** * Ensure that the current values are valid and trigger a preview * * @param {Event} event the submit form event * * @return {void} */ function handleLayoutFormSubmit(event) { event.preventDefault(); var $layoutcontainer = jQuery('#layoutcontainer'); var $layoutfield = jQuery('#dw__editform').find('input[name=tablelayout]'); var layout = window.tablelayout.initLayout($layoutfield.val()); // validation var rowsHeaderSource = $layoutcontainer.find('select[name="rowsHeaderSource"] :selected').val(); var rowsVisible = parseInt($layoutcontainer.find('input[name="rowsVisible"]').val()); var float = $layoutcontainer.find('select[name="float"]').val(); var MAX_HEADER_ROWS = 10; if (0 <= parseInt(rowsHeaderSource) && parseInt(rowsHeaderSource) <= MAX_HEADER_ROWS) { layout.rowsHeaderSource = rowsHeaderSource; } else { layout.rowsHeaderSource = 'Auto'; } if (!(rowsVisible && rowsVisible > 0)) { delete layout.rowsVisible; } else { layout.rowsVisible = rowsVisible; } if (float && (float === 'left' || float === 'right' || float === 'center')) { layout.float = float; } else { delete layout.float; } var tableSort = $layoutcontainer.find('input[name="tableSort"]').is(':checked'); layout.tableSort = tableSort; var tableSearch = $layoutcontainer.find('input[name="tableSearch"]').is(':checked'); layout.tableSearch = tableSearch; var tablePrint = $layoutcontainer.find('input[name="tablePrint"]').is(':checked'); layout.tablePrint = tablePrint; $layoutfield.val(JSON.stringify(layout)); jQuery('#dw__editform').find('button[name="do[preview]"]').click(); } /** * * @param {string} staticFormHTML the basic form html as returned by the server * * @return {void} */ function initializeLayoutForm(staticFormHTML) { var $layoutcontainer = jQuery('#layoutcontainer'); $layoutcontainer.html(staticFormHTML); $layoutcontainer.find('fieldset legend').click(function () { $layoutcontainer.find('fieldset').toggleClass('borderless'); $layoutcontainer.find('fieldset > div').slideToggle(); }); var $layoutfield = jQuery('#dw__editform').find('input[name=tablelayout]'); var layout = window.tablelayout.initLayout($layoutfield.val()); $layoutcontainer.find('select[name="rowsHeaderSource"]').val(layout.rowsHeaderSource); if (layout.rowsHeaderSource && layout.rowsVisible) { $layoutcontainer.find('input[name="rowsVisible"]').val(layout.rowsVisible); } if (layout.float) { $layoutcontainer.find('select[name="float"]').val(layout.float); } if (typeof layout.tableSort !== 'undefined' && layout.tableSort === true) { $layoutcontainer.find('input[name="tableSort"]').attr('checked', true); } if (typeof layout.tableSearch !== 'undefined' && layout.tableSearch === true) { $layoutcontainer.find('input[name="tableSearch"]').attr('checked', true); } if (typeof layout.tablePrint !== 'undefined' && layout.tablePrint === true) { $layoutcontainer.find('input[name="tablePrint"]').attr('checked', true); } $layoutcontainer.find('form').submit(handleLayoutFormSubmit); } if (!jQuery('#edittable__editor').length) { return; } jQuery('#dw__editform').before('
      ' + window.LANG.plugins.tablelayout.loading + '
      '); jQuery.get( window.DOKU_BASE + 'lib/exe/ajax.php', { call: 'plugin_tablelayout_form' } ).done(initializeLayoutForm).fail(function (jqXhr) { var $layoutcontainer = jQuery('#layoutcontainer'); $layoutcontainer.html(jqXhr.responseText); }); }); window.edittable_plugins = window.edittable_plugins || {}; window.tablelayout = window.tablelayout || {}; (function (edittable_plugins, tablelayout) { 'use strict'; var modifyHandsontableConfig = function (handsontable_config, $form) { var $layoutfield = $form.find('input[name=tablelayout]'); if (!$layoutfield.length) { return; } var colWidths = []; var layout = tablelayout.initLayout($layoutfield.val()); layout.colwidth.forEach(function (currentValue, index) { var undefinedValue; if (!currentValue || currentValue.substr(-'px'.length) !== 'px') { colWidths.push(undefinedValue); return; } colWidths[index] = parseInt(currentValue, 10); }); if (colWidths.length) { handsontable_config.manualColumnResize = colWidths; } if (layout.rowsHeader && layout.rowsVisible) { handsontable_config.fixedRowsTop = parseInt(layout.rowsHeader); } handsontable_config.afterColumnResize = function (col, width) { if ($layoutfield) { layout.colwidth[col] = parseInt(width, 10) + 'px'; $layoutfield.val(JSON.stringify(layout)); } }; var forcePreview = false; var originalBeforeRemoveCol = handsontable_config.beforeRemoveCol; handsontable_config.beforeRemoveCol = function (index, amount) { if (originalBeforeRemoveCol) { originalBeforeRemoveCol.call(this, index, amount); } layout.colwidth.splice(index, amount); $layoutfield.val(JSON.stringify(layout)); }; var originalAfterRemoveCol = handsontable_config.afterRemoveCol; handsontable_config.afterRemoveCol = function (index, amount) { if (originalAfterRemoveCol) { originalAfterRemoveCol.call(this, index, amount); } forcePreview = true; }; var originalAfterCreateCol = handsontable_config.afterCreateCol; handsontable_config.afterCreateCol = function (index, amount) { if (originalAfterCreateCol) { originalAfterCreateCol.call(this, index, amount); } layout.colwidth.splice(index, 0, null); $layoutfield.val(JSON.stringify(layout)); }; handsontable_config.afterRender = function () { if (forcePreview) { forcePreview = false; $form.find('button[name="do[preview]"]').click(); } }; }; edittable_plugins.tablelayout = {modifyHandsontableConfig: modifyHandsontableConfig}; }(window.edittable_plugins, window.tablelayout)); window.tablelayout = window.tablelayout || {}; jQuery(window).on('load', function () { 'use strict'; /** * * @param {jQuery} $secedit_form jQuery object of the section edit form associated with the table * * @return {void} */ function addPrintButtonToTable($secedit_form) { var range = $secedit_form.find('input[name="range"]').val(); var target = $secedit_form.closest('form').attr('action'); var layout = $secedit_form.find('input[name="tablelayout"]').val(); var params = [ 'do=tablelayout_printtable', 'range=' + encodeURIComponent(range), 'id=' + encodeURIComponent(window.JSINFO.id) ]; if (typeof layout !== 'undefined' && layout.length > 0) { var json = JSON.parse(layout); var colwidth = json.colwidth; params.push('colwidth=' + colwidth); } var href = target + '?' + params.join('&'); var $link = jQuery('' + window.LANG.plugins.tablelayout.print + '').attr({ 'href': href, 'target': '_blank' }).addClass('button print'); $secedit_form.closest('div.secedit').append($link); } /** * Add a row for the search fields and filter buttons below the table header * * @param {JQuery} $table jQuery-object of the table * @param {int} numHeaderRows the number of rows in the header of the table * @param {int} columnCount the number of columns in the table * @return {JQuery} the searchSortRow object, that has been added to the table */ function addSearchSortRow($table, numHeaderRows, columnCount) { var $searchSortRow = jQuery('' + '
      '.repeat(columnCount) + ''); var $lastHeaderRow; if ($table.hasClass('tablelayout_body')) { $lastHeaderRow = $table.closest('.table').find('table.tablelayout_head tr').last(); $lastHeaderRow.after($searchSortRow); } else if(numHeaderRows === 0) { $table.find('tr').first().before($searchSortRow); } else { $lastHeaderRow = $table.find('tr').slice(numHeaderRows - 1).first(); $lastHeaderRow.after($searchSortRow); } return $searchSortRow; } /** * * @param {JQuery} $table jQuery-object of the table * @param {JQuery} $searchSortRow the special row where the sort-buttons will be placed * @param {int} numHeaderRows the number of rows in the header of the table * * @return {void} */ function addSortFunctionality($table, $searchSortRow, numHeaderRows) { var $rowsToBeSorted; if ($table.hasClass('tablelayout_body')) { $rowsToBeSorted = $table.find('tr'); } else { $rowsToBeSorted = $table.find('tr').slice(parseInt(numHeaderRows) + 1); } var $tableSortRowCells = $searchSortRow.find('td > div,th > div'); $tableSortRowCells.append(jQuery('