1*9a366708SLORTET(function () { 2*9a366708SLORTET function escapeRegExp(text) { 3*9a366708SLORTET return String(text).replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); 4*9a366708SLORTET } 5*9a366708SLORTET 6*9a366708SLORTET function slugifyTitle(title, options) { 7*9a366708SLORTET const sep = options && options.sepchar ? options.sepchar : '_'; 8*9a366708SLORTET const sepPattern = new RegExp(escapeRegExp(sep) + '+', 'g'); 9*9a366708SLORTET const trimPattern = new RegExp('^' + escapeRegExp(sep) + '|' + escapeRegExp(sep) + '$', 'g'); 10*9a366708SLORTET 11*9a366708SLORTET return String(title || '') 12*9a366708SLORTET .normalize('NFD') 13*9a366708SLORTET .replace(/[\u0300-\u036f]/g, '') 14*9a366708SLORTET .replace(/['’]/g, '') 15*9a366708SLORTET .toLowerCase() 16*9a366708SLORTET .replace(/[^a-z0-9]+/g, sep) 17*9a366708SLORTET .replace(sepPattern, sep) 18*9a366708SLORTET .replace(trimPattern, ''); 19*9a366708SLORTET } 20*9a366708SLORTET 21*9a366708SLORTET function getStrings() { 22*9a366708SLORTET const lang = window.LANG && LANG.plugins && LANG.plugins.newpagefill ? LANG.plugins.newpagefill : {}; 23*9a366708SLORTET return { 24*9a366708SLORTET title: lang.dialog_title || 'Creer une nouvelle page', 25*9a366708SLORTET pageTitle: lang.dialog_page_title || 'Titre', 26*9a366708SLORTET pageId: lang.dialog_page_id || 'Identifiant', 27*9a366708SLORTET namespace: lang.dialog_namespace || 'Namespace', 28*9a366708SLORTET pageMode: lang.dialog_page_mode || 'Type de creation', 29*9a366708SLORTET pageModeStart: lang.dialog_page_mode_start || 'Page de demarrage', 30*9a366708SLORTET pageModeNone: lang.dialog_page_mode_none || 'Page directe', 31*9a366708SLORTET pageModeSame: lang.dialog_page_mode_same || 'Sous-page du meme nom', 32*9a366708SLORTET create: lang.dialog_create || 'Creer', 33*9a366708SLORTET cancel: lang.dialog_cancel || 'Annuler', 34*9a366708SLORTET required: lang.dialog_required || 'L identifiant est requis.' 35*9a366708SLORTET }; 36*9a366708SLORTET } 37*9a366708SLORTET 38*9a366708SLORTET function getPluginConfig() { 39*9a366708SLORTET return window.JSINFO && JSINFO.plugins && JSINFO.plugins.newpagefill 40*9a366708SLORTET ? JSINFO.plugins.newpagefill 41*9a366708SLORTET : {}; 42*9a366708SLORTET } 43*9a366708SLORTET 44*9a366708SLORTET function appendToUrl(base, params) { 45*9a366708SLORTET return base + (base.indexOf('?') >= 0 ? '&' : '?') + params; 46*9a366708SLORTET } 47*9a366708SLORTET 48*9a366708SLORTET function buildBaseHref(namespace, options) { 49*9a366708SLORTET const root = typeof DOKU_BASE !== 'undefined' && DOKU_BASE ? DOKU_BASE : '/'; 50*9a366708SLORTET const cleaned = String(namespace || '').trim().replace(/^:+|:+$/g, ''); 51*9a366708SLORTET 52*9a366708SLORTET if (options && Number(options.userewrite) === 1) { 53*9a366708SLORTET if (!cleaned) return root.replace(/\/$/, ''); 54*9a366708SLORTET return root.replace(/\/$/, '') + '/' + cleaned.split(':').map(encodeURIComponent).join('/'); 55*9a366708SLORTET } 56*9a366708SLORTET 57*9a366708SLORTET const base = root.replace(/\/$/, '/'); 58*9a366708SLORTET if (!cleaned) return base; 59*9a366708SLORTET return appendToUrl(base, 'id=' + encodeURIComponent(cleaned)); 60*9a366708SLORTET } 61*9a366708SLORTET 62*9a366708SLORTET function buildTargetPageId(namespace, pageId, start) { 63*9a366708SLORTET const parts = []; 64*9a366708SLORTET const cleanedNamespace = String(namespace || '').trim().replace(/^:+|:+$/g, ''); 65*9a366708SLORTET const cleanedPageId = String(pageId || '').trim().replace(/^:+|:+$/g, ''); 66*9a366708SLORTET const cleanedStart = String(start || '').trim().replace(/^:+|:+$/g, ''); 67*9a366708SLORTET 68*9a366708SLORTET if (cleanedNamespace) parts.push(cleanedNamespace); 69*9a366708SLORTET if (cleanedPageId) parts.push(cleanedPageId); 70*9a366708SLORTET if (cleanedStart) parts.push(cleanedStart); 71*9a366708SLORTET 72*9a366708SLORTET return parts.join(':'); 73*9a366708SLORTET } 74*9a366708SLORTET 75*9a366708SLORTET function resolveStartSegment(pageId, startOption, defaultStart, defaultMode) { 76*9a366708SLORTET if (startOption === null || typeof startOption === 'undefined') { 77*9a366708SLORTET startOption = defaultMode; 78*9a366708SLORTET } 79*9a366708SLORTET 80*9a366708SLORTET if (String(startOption).toLowerCase() === '@ask@' || String(startOption).toLowerCase() === 'ask') { 81*9a366708SLORTET return null; 82*9a366708SLORTET } 83*9a366708SLORTET 84*9a366708SLORTET if (startOption === true) { 85*9a366708SLORTET return String(defaultStart || '').trim(); 86*9a366708SLORTET } 87*9a366708SLORTET 88*9a366708SLORTET if (startOption === false || startOption === '' || String(startOption).toLowerCase() === 'none') { 89*9a366708SLORTET return ''; 90*9a366708SLORTET } 91*9a366708SLORTET 92*9a366708SLORTET if (String(startOption).toLowerCase() === '@same@' || String(startOption).toLowerCase() === 'same') { 93*9a366708SLORTET return String(pageId || '').trim(); 94*9a366708SLORTET } 95*9a366708SLORTET 96*9a366708SLORTET if (String(startOption).toLowerCase() === 'start') { 97*9a366708SLORTET return String(defaultStart || '').trim(); 98*9a366708SLORTET } 99*9a366708SLORTET 100*9a366708SLORTET return String(startOption).trim(); 101*9a366708SLORTET } 102*9a366708SLORTET 103*9a366708SLORTET function getDialog() { 104*9a366708SLORTET let overlay = document.getElementById('newpagefill_overlay'); 105*9a366708SLORTET if (overlay) return overlay; 106*9a366708SLORTET 107*9a366708SLORTET overlay = document.createElement('div'); 108*9a366708SLORTET overlay.id = 'newpagefill_overlay'; 109*9a366708SLORTET overlay.innerHTML = [ 110*9a366708SLORTET '<div class="newpagefill_dialog" role="dialog" aria-modal="true" aria-labelledby="newpagefill_title">', 111*9a366708SLORTET ' <h3 id="newpagefill_title"></h3>', 112*9a366708SLORTET ' <label class="newpagefill_label" for="newpagefill_input_title"></label>', 113*9a366708SLORTET ' <input id="newpagefill_input_title" type="text" autocomplete="off">', 114*9a366708SLORTET ' <label class="newpagefill_label" for="newpagefill_input_id"></label>', 115*9a366708SLORTET ' <input id="newpagefill_input_id" type="text" autocomplete="off" autocapitalize="off" spellcheck="false">', 116*9a366708SLORTET ' <div class="newpagefill_namespace_row">', 117*9a366708SLORTET ' <label class="newpagefill_label" for="newpagefill_input_namespace"></label>', 118*9a366708SLORTET ' <input id="newpagefill_input_namespace" type="text" autocomplete="off" autocapitalize="off" spellcheck="false">', 119*9a366708SLORTET ' </div>', 120*9a366708SLORTET ' <div class="newpagefill_mode_row">', 121*9a366708SLORTET ' <label class="newpagefill_label" for="newpagefill_input_mode"></label>', 122*9a366708SLORTET ' <select id="newpagefill_input_mode"></select>', 123*9a366708SLORTET ' </div>', 124*9a366708SLORTET ' <p class="newpagefill_error" aria-live="polite"></p>', 125*9a366708SLORTET ' <div class="newpagefill_actions">', 126*9a366708SLORTET ' <button type="button" class="newpagefill_cancel"></button>', 127*9a366708SLORTET ' <button type="button" class="newpagefill_create"></button>', 128*9a366708SLORTET ' </div>', 129*9a366708SLORTET '</div>' 130*9a366708SLORTET ].join(''); 131*9a366708SLORTET document.body.appendChild(overlay); 132*9a366708SLORTET 133*9a366708SLORTET overlay.addEventListener('click', function (event) { 134*9a366708SLORTET if (event.target === overlay) { 135*9a366708SLORTET overlay.classList.remove('is-open'); 136*9a366708SLORTET } 137*9a366708SLORTET }); 138*9a366708SLORTET 139*9a366708SLORTET return overlay; 140*9a366708SLORTET } 141*9a366708SLORTET 142*9a366708SLORTET function openCreatePageDialog(options) { 143*9a366708SLORTET const overlay = getDialog(); 144*9a366708SLORTET const strings = getStrings(); 145*9a366708SLORTET const titleEl = overlay.querySelector('#newpagefill_title'); 146*9a366708SLORTET const titleLabel = overlay.querySelector('label[for="newpagefill_input_title"]'); 147*9a366708SLORTET const namespaceRow = overlay.querySelector('.newpagefill_namespace_row'); 148*9a366708SLORTET const namespaceLabel = overlay.querySelector('label[for="newpagefill_input_namespace"]'); 149*9a366708SLORTET const modeRow = overlay.querySelector('.newpagefill_mode_row'); 150*9a366708SLORTET const modeLabel = overlay.querySelector('label[for="newpagefill_input_mode"]'); 151*9a366708SLORTET const idLabel = overlay.querySelector('label[for="newpagefill_input_id"]'); 152*9a366708SLORTET const titleInput = overlay.querySelector('#newpagefill_input_title'); 153*9a366708SLORTET const namespaceInput = overlay.querySelector('#newpagefill_input_namespace'); 154*9a366708SLORTET const modeInput = overlay.querySelector('#newpagefill_input_mode'); 155*9a366708SLORTET const idInput = overlay.querySelector('#newpagefill_input_id'); 156*9a366708SLORTET const errorEl = overlay.querySelector('.newpagefill_error'); 157*9a366708SLORTET const cancelBtn = overlay.querySelector('.newpagefill_cancel'); 158*9a366708SLORTET const createBtn = overlay.querySelector('.newpagefill_create'); 159*9a366708SLORTET const pluginConfig = getPluginConfig(); 160*9a366708SLORTET const config = { 161*9a366708SLORTET namespace: options && options.namespace ? options.namespace : '', 162*9a366708SLORTET sepchar: options && options.sepchar ? options.sepchar : (pluginConfig.sepchar || '_'), 163*9a366708SLORTET start: options && Object.prototype.hasOwnProperty.call(options, 'start') 164*9a366708SLORTET ? options.start 165*9a366708SLORTET : undefined, 166*9a366708SLORTET defaultStart: pluginConfig.start || 'start', 167*9a366708SLORTET defaultStartMode: pluginConfig.default_start_mode || 'start', 168*9a366708SLORTET initialTitle: options && options.initialTitle ? options.initialTitle : '', 169*9a366708SLORTET userewrite: options && typeof options.userewrite !== 'undefined' 170*9a366708SLORTET ? options.userewrite 171*9a366708SLORTET : pluginConfig.userewrite 172*9a366708SLORTET }; 173*9a366708SLORTET 174*9a366708SLORTET titleEl.textContent = strings.title; 175*9a366708SLORTET titleLabel.textContent = strings.pageTitle; 176*9a366708SLORTET namespaceLabel.textContent = strings.namespace; 177*9a366708SLORTET modeLabel.textContent = strings.pageMode; 178*9a366708SLORTET idLabel.textContent = strings.pageId; 179*9a366708SLORTET cancelBtn.textContent = strings.cancel; 180*9a366708SLORTET createBtn.textContent = strings.create; 181*9a366708SLORTET errorEl.textContent = ''; 182*9a366708SLORTET namespaceRow.style.display = config.namespace ? 'none' : ''; 183*9a366708SLORTET const shouldAskStartMode = 184*9a366708SLORTET String(config.start).toLowerCase() === '@ask@' || 185*9a366708SLORTET String(config.start).toLowerCase() === 'ask' || 186*9a366708SLORTET ((typeof config.start === 'undefined' || config.start === null) && config.defaultStartMode === 'ask'); 187*9a366708SLORTET 188*9a366708SLORTET modeRow.style.display = shouldAskStartMode ? '' : 'none'; 189*9a366708SLORTET modeInput.innerHTML = ''; 190*9a366708SLORTET [ 191*9a366708SLORTET {value: 'start', label: strings.pageModeStart}, 192*9a366708SLORTET {value: 'none', label: strings.pageModeNone}, 193*9a366708SLORTET {value: '@same@', label: strings.pageModeSame} 194*9a366708SLORTET ].forEach(function (option) { 195*9a366708SLORTET const el = document.createElement('option'); 196*9a366708SLORTET el.value = option.value; 197*9a366708SLORTET el.textContent = option.label; 198*9a366708SLORTET modeInput.appendChild(el); 199*9a366708SLORTET }); 200*9a366708SLORTET 201*9a366708SLORTET let idDirty = false; 202*9a366708SLORTET 203*9a366708SLORTET function updateSuggestedId() { 204*9a366708SLORTET if (idDirty) return; 205*9a366708SLORTET idInput.value = slugifyTitle(titleInput.value, config); 206*9a366708SLORTET } 207*9a366708SLORTET 208*9a366708SLORTET function closeDialog() { 209*9a366708SLORTET overlay.classList.remove('is-open'); 210*9a366708SLORTET document.removeEventListener('keydown', handleKeydown); 211*9a366708SLORTET } 212*9a366708SLORTET 213*9a366708SLORTET function submitDialog() { 214*9a366708SLORTET const titleValue = titleInput.value.trim(); 215*9a366708SLORTET const namespaceValue = namespaceInput.value.trim(); 216*9a366708SLORTET const idValue = idInput.value.trim(); 217*9a366708SLORTET if (!idValue) { 218*9a366708SLORTET errorEl.textContent = strings.required; 219*9a366708SLORTET idInput.focus(); 220*9a366708SLORTET return; 221*9a366708SLORTET } 222*9a366708SLORTET 223*9a366708SLORTET const namespace = namespaceValue || config.namespace; 224*9a366708SLORTET const startOption = shouldAskStartMode ? modeInput.value : config.start; 225*9a366708SLORTET const startSegment = resolveStartSegment(idValue, startOption, config.defaultStart, config.defaultStartMode); 226*9a366708SLORTET let targetUrl; 227*9a366708SLORTET 228*9a366708SLORTET if (Number(config.userewrite) === 1) { 229*9a366708SLORTET const baseHref = buildBaseHref(namespace, config); 230*9a366708SLORTET targetUrl = baseHref + '/' + encodeURIComponent(idValue); 231*9a366708SLORTET if (startSegment) { 232*9a366708SLORTET targetUrl += '/' + encodeURIComponent(startSegment); 233*9a366708SLORTET } 234*9a366708SLORTET } else { 235*9a366708SLORTET targetUrl = buildBaseHref('', config); 236*9a366708SLORTET targetUrl = appendToUrl(targetUrl, 'id=' + encodeURIComponent(buildTargetPageId(namespace, idValue, startSegment))); 237*9a366708SLORTET } 238*9a366708SLORTET 239*9a366708SLORTET targetUrl = appendToUrl(targetUrl, 'do=edit'); 240*9a366708SLORTET if (titleValue) { 241*9a366708SLORTET targetUrl = appendToUrl(targetUrl, 'title=' + encodeURIComponent(titleValue)); 242*9a366708SLORTET } 243*9a366708SLORTET 244*9a366708SLORTET window.location.href = targetUrl; 245*9a366708SLORTET } 246*9a366708SLORTET 247*9a366708SLORTET function handleKeydown(event) { 248*9a366708SLORTET if (!overlay.classList.contains('is-open')) return; 249*9a366708SLORTET if (event.key === 'Escape') { 250*9a366708SLORTET event.preventDefault(); 251*9a366708SLORTET closeDialog(); 252*9a366708SLORTET } 253*9a366708SLORTET if (event.key === 'Enter') { 254*9a366708SLORTET event.preventDefault(); 255*9a366708SLORTET submitDialog(); 256*9a366708SLORTET } 257*9a366708SLORTET } 258*9a366708SLORTET 259*9a366708SLORTET titleInput.value = config.initialTitle; 260*9a366708SLORTET namespaceInput.value = config.namespace; 261*9a366708SLORTET idInput.value = ''; 262*9a366708SLORTET idDirty = false; 263*9a366708SLORTET updateSuggestedId(); 264*9a366708SLORTET 265*9a366708SLORTET titleInput.oninput = function () { 266*9a366708SLORTET errorEl.textContent = ''; 267*9a366708SLORTET updateSuggestedId(); 268*9a366708SLORTET }; 269*9a366708SLORTET 270*9a366708SLORTET idInput.oninput = function () { 271*9a366708SLORTET errorEl.textContent = ''; 272*9a366708SLORTET idDirty = idInput.value.trim() !== slugifyTitle(titleInput.value, config); 273*9a366708SLORTET }; 274*9a366708SLORTET 275*9a366708SLORTET cancelBtn.onclick = closeDialog; 276*9a366708SLORTET createBtn.onclick = submitDialog; 277*9a366708SLORTET 278*9a366708SLORTET overlay.classList.add('is-open'); 279*9a366708SLORTET document.addEventListener('keydown', handleKeydown); 280*9a366708SLORTET window.setTimeout(() => titleInput.focus(), 0); 281*9a366708SLORTET } 282*9a366708SLORTET 283*9a366708SLORTET window.NewPageFill = { 284*9a366708SLORTET slugifyTitle, 285*9a366708SLORTET openCreatePageDialog 286*9a366708SLORTET }; 287*9a366708SLORTET})(); 288