'use strict';class jsToolBar{constructor(textarea){if(!textarea){return;}
if(typeof document.selection==='undefined'&&typeof textarea.setSelectionRange==='undefined'){return;}
this.textarea=textarea;this.editor=document.createElement('div');this.editor.className='jstEditor';this.textarea.parentNode.insertBefore(this.editor,this.textarea);this.editor.appendChild(this.textarea);this.toolbar=document.createElement('div');this.toolbar.className='jstElements';if(this.toolbar_bottom){this.editor.parentNode.insertBefore(this.toolbar,this.editor.nextSibling);this.editor.parentNode.classList.add('toolbar_bottom');}else{this.editor.parentNode.insertBefore(this.toolbar,this.editor);this.editor.parentNode.classList.add('toolbar_top');}
this.context=null;this.toolNodes={};if(this.textarea&&this?.dynamic_height){this.dynamic={min:this.textarea.clientHeight+2,max:0,timer:false,};this.debounceFunction=(func,delay)=>{if(this.dynamic.timer){clearTimeout(this.dynamic.timer);}
this.dynamic.timer=setTimeout(func,delay);};this.adjustHeight=(el,min,max)=>{const outerHeight=Number.parseInt(window.getComputedStyle(el).height,10);const diff=outerHeight-el.clientHeight;el.style.height=0;let calculatedMax=max;if(calculatedMax===0){calculatedMax=window.innerHeight-100;}
el.style.height=`${Math.min(calculatedMax, Math.max(min, el.scrollHeight + diff))}px`;};this.textarea.addEventListener('input',()=>this.debounceFunction(this.adjustHeight(this.textarea,this.dynamic.min,this.dynamic.max),300),);this.adjustHeight(this.textarea,this.dynamic.min,this.dynamic.max);}}
getMode(){return this.mode;}
setMode(mode='xhtml'){this.mode=mode;}
switchMode(mode='xhtml'){this.draw(mode);}
button(toolName){const tool=this.elements[toolName];if(typeof tool.fn[this.mode]!=='function')return null;const button=new jsButton(tool.title,tool.fn[this.mode],this,`jstb_${toolName}`,tool.accesskey,tool.key,tool.shortkey,tool.shortkey_name,);if(tool.icon!==undefined){button.icon=tool.icon;if(tool.icon_dark!==undefined){button.icon_dark=tool.icon_dark;}}
return button;}
space(toolName){const tool=new jsSpace(toolName);if(this.elements[toolName].format!==undefined&&!this.elements[toolName].format[this.mode])return null;if(this.elements[toolName].width!==undefined){tool.width=this.elements[toolName].width;}
return tool;}
combo(toolName){const tool=this.elements[toolName];if(tool[this.mode]===undefined){return;}
const{length}=tool[this.mode].list;if(typeof tool[this.mode].fn!=='function'||length===0){return null;}
const options={};for(const opt of tool[this.mode].list){options[opt]=tool.options[opt];}
return new jsCombo(tool.title,options,this,tool[this.mode].fn);}
draw(mode){this.setMode(mode);while(this.toolbar.hasChildNodes()){this.toolbar.removeChild(this.toolbar.firstChild);}
this.toolNodes={};let element;let tool;let newTool;let currentGroup;const groupTemplate=new DOMParser().parseFromString(`<div class="jstGroup"></div>`,'text/html').body.firstChild;const groups=[];currentGroup=groupTemplate.cloneNode(true);for(const name in this.elements){element=this.elements[name];const disabled=element.type===undefined||element.type===''||(element.disabled!==undefined&&element.disabled)||(element.context!==undefined&&element.context!=null&&element.context!==this.context);if(!disabled&&typeof this[element.type]==='function'){newTool=false;const groupName=element?.group;tool=this[element.type](name);if(tool){if(element.type!=='space'){newTool=tool.draw();}else{if(currentGroup.childElementCount>0)groups.push(currentGroup);currentGroup=groupTemplate.cloneNode(true);}}
if(newTool){this.toolNodes[name]=newTool;for(const group of groups){if(group.getAttribute('name')===`jstg_${groupName}`){group.appendChild(newTool);newTool=false;break;}}
if(newTool){if(currentGroup.getAttribute('name')!==null&&currentGroup.getAttribute('name')!==`jstg_${groupName}`){groups.push(currentGroup);currentGroup=groupTemplate.cloneNode(true);}
currentGroup.appendChild(newTool);if(groupName!==undefined&&groupName!==''&&currentGroup.getAttribute('name')===null)
currentGroup.setAttribute('name',`jstg_${groupName}`);}}}}
if(currentGroup.childElementCount>0)groups.push(currentGroup);for(const group of groups){if(group.childElementCount>0)this.toolbar.appendChild(group);}}
singleTag(stag=null,etag=stag){if(!stag||!etag){return;}
this.encloseSelection(stag,etag);}
getCurrentSelection(){if(typeof document.selection!=='undefined'){return document.selection.createRange().text;}else if(typeof this.textarea.setSelectionRange!=='undefined'){return this.textarea.value.substring(this.textarea.selectionStart,this.textarea.selectionEnd);}
return'';}
encloseSelection(prefix='',suffix='',fn=null){this.textarea.focus();let start;let end;let sel;let scrollPos;let subst;let res;if(typeof document.selection!=='undefined'){sel=document.selection.createRange().text;}else if(typeof this.textarea.setSelectionRange!=='undefined'){start=this.textarea.selectionStart;end=this.textarea.selectionEnd;scrollPos=this.textarea.scrollTop;sel=this.textarea.value.substring(start,end);}
let cleanSuffix=suffix;if(sel.match(/ $/)){sel=sel.substring(0,sel.length-1);cleanSuffix=`${cleanSuffix} `;}
if(typeof fn==='function'){res=sel?fn.call(this,sel):fn('');}else{res=sel||'';}
subst=prefix+res+cleanSuffix;if(typeof document.selection!=='undefined'){document.selection.createRange().text=subst;this.textarea.caretPos-=suffix.length;}else if(typeof this.textarea.setSelectionRange!=='undefined'){this.textarea.value=this.textarea.value.substring(0,start)+subst+this.textarea.value.substring(end);if(sel||typeof fn==='function'){this.textarea.setSelectionRange(start+subst.length,start+subst.length);}else if(typeof fn!=='function'){this.textarea.setSelectionRange(start+prefix.length,start+prefix.length);}
this.textarea.scrollTop=scrollPos;}}
stripBaseURL(url){if(this.base_url!==''){const pos=url.indexOf(this.base_url);if(pos===0){return url.substring(this.base_url.length);}}
return url;}}
jsToolBar.prototype.base_url='';jsToolBar.prototype.mode='xhtml';jsToolBar.prototype.elements={};jsToolBar.prototype.toolbar_bottom=false;class jsButton{constructor(title,fn,scope,className,accesskey,key,shortkey,shortkey_name){this.title=title||null;this.fn=fn||(()=>{});this.scope=scope||null;this.className=className||null;this.accesskey=accesskey||null;this.key=key||null;this.shortkey=shortkey||null;this.shortkey_name=shortkey_name||null;}
draw(){if(!this.scope)return null;const button=document.createElement('button');button.setAttribute('type','button');if(this.className)button.className=this.className;button.title=this.title;button.id=`jstb_${(Math.random() + 1).toString(36).substring(5)}`;if(this.accesskey)button.accessKey=this.accesskey;if(this.shortkey||this.key){if(this.shortkey_name)button.title+=` (CTRL+${this.shortkey_name})`;this.scope.textarea.addEventListener('keydown',(event)=>{let doIt=false;if(this.key){if(event.key===this.key&&event.ctrlKey&&!event.altKey&&!event.metaKey){doIt=true;}}else if(this.shortkey){if(event.code===this.shortkey&&event.ctrlKey&&!event.altKey&&!event.metaKey){doIt=true;}}
if(doIt){button.click();event.preventDefault();return false;}});}
if(this.icon!==undefined){const iconLight=document.createElement('img');iconLight.setAttribute('src',this.icon);iconLight.setAttribute('alt',this.title);if(this.icon_dark===undefined){button.appendChild(iconLight);}else{iconLight.classList.add('light-only');button.appendChild(iconLight);const iconDark=document.createElement('img');iconDark.setAttribute('src',this.icon_dark);iconDark.setAttribute('alt',this.title);iconDark.classList.add('dark-only');button.appendChild(iconDark);}}
const span=document.createElement('span');span.appendChild(document.createTextNode(this.title));button.appendChild(span);if(typeof this.fn==='function'){button.onclick=(...args)=>{try{this.fn.apply(this.scope,args);}catch(e){}
return false;};}
return button;}}
class jsSpace{constructor(id){this.id=id||`jsts_${(Math.random() + 1).toString(36).substring(5)}`;this.width=null;}
draw(){const span=document.createElement('span');if(this.id)span.id=this.id;span.appendChild(document.createTextNode(String.fromCharCode(160)));span.className='jstSpacer';if(this.width)span.style.marginRight=`${this.width}px`;return span;}}
class jsCombo{constructor(title,options,scope,fn,className){this.title=title||null;this.options=options||null;this.scope=scope||null;this.fn=fn||(()=>{});this.className=className||null;}
draw(){if(!this.scope||!this.options)return null;const select=document.createElement('select');if(this.className)select.className=this.className;select.title=this.title;select.id=`jstc_${(Math.random() + 1).toString(36).substring(5)}`;for(const option in this.options){const optionElement=document.createElement('option');optionElement.value=option;optionElement.appendChild(document.createTextNode(this.options[option]));select.appendChild(optionElement);}
const This=this;select.onchange=function(){try{This.fn.call(This.scope,this.value);}catch(e){window.alert(e);}
return false;};return select;}}
class jsDialog{title;confirm_label;cancel_label;fields;constructor({title,confirm_label,cancel_label,fields}={}){this.title=title;this.confirm_label=confirm_label??'Ok';this.cancel_label=cancel_label??'Cancel';this.fields=fields;}
prompt(){if(!this.fields?.length)return Promise.resolve(null);const template=document.createElement('template');const fieldsHtml=this.fields.map((field)=>`<p class="field">${field.html}</p>`).join('');const html=(strings,...values)=>strings.reduce((accumulator,currentValue,currentIndex)=>accumulator+currentValue+(values[currentIndex]??''),'',);const title=this.title?`<h1>${this.title}</h1>`:'';template.innerHTML=html`
      <dialog class="jstDialog">
        ${title}
        <form method="dialog">
          ${fieldsHtml}
          <p class="form-buttons">
            <button name="cancel" class="reset">${this.cancel_label}</button>
            <button type="submit" name="confirm" class="submit">${this.confirm_label}</button>
          </p>
        </form>
      </dialog>
    `;const dialog=template.content.firstElementChild;const fields=dialog.querySelectorAll('.field input, .field select');let index=0;for(const field of fields){if(this.fields[index]?.default)field.value=this.fields[index].default;index++;}
document.body.appendChild(dialog);const getReturnValue=()=>JSON.stringify([...fields].map((field)=>field.value));return new Promise((resolve)=>{for(const field of fields){field.addEventListener('keydown',(event)=>{if(event.key!=='Enter'){return;}
event.preventDefault();dialog.returnValue=getReturnValue();dialog.close();});}
dialog.querySelector('button[name="confirm"]')?.addEventListener('click',(event)=>{event.preventDefault();dialog.returnValue=getReturnValue();dialog.close();});dialog.querySelector('button[name="cancel"]')?.addEventListener('click',()=>{dialog.dispatchEvent(new Event('cancel'));});dialog.addEventListener('cancel',function onCancel(event){event.preventDefault();dialog.removeEventListener('close',onCancel);dialog.returnValue=null;dialog.remove();resolve(null);});dialog.addEventListener('close',function onClose(event){event.preventDefault();dialog.removeEventListener('close',onClose);const result=dialog.returnValue;dialog.remove();resolve(result);});dialog.showModal();fields[0].focus();});}}
jsToolBar.prototype.elements.blocks={group:'header',type:'combo',title:'block format',options:{none:'-- none --',nonebis:'- block format -',p:'Paragraph',h1:'Header 1',h2:'Header 2',h3:'Header 3',h4:'Header 4',h5:'Header 5',h6:'Header 6',},xhtml:{list:['nonebis','p','h1','h2','h3','h4','h5','h6'],fn(opt){if(opt==='nonebis')this.textarea.focus();else
try{this.singleTag(`<${opt}>`,`</${opt}>`);}catch(e){}
this.toolNodes.blocks.value='nonebis';},},wiki:{list:['nonebis','h3','h4','h5'],fn(opt){switch(opt){case'nonebis':this.textarea.focus();break;case'h3':this.encloseSelection('!!!');break;case'h4':this.encloseSelection('!!');break;case'h5':this.encloseSelection('!');break;}
this.toolNodes.blocks.value='nonebis';},},};jsToolBar.prototype.elements.strong={group:'format',type:'button',title:'Strong emphasis',key:'b',shortkey_name:'B',fn:{wiki(){this.singleTag('__');},xhtml(){this.singleTag('<strong>','</strong>');},},};jsToolBar.prototype.elements.em={group:'format',type:'button',title:'Emphasis',key:'i',shortkey_name:'I',fn:{wiki(){this.singleTag("''");},xhtml(){this.singleTag('<em>','</em>');},},};jsToolBar.prototype.elements.ins={group:'format',type:'button',title:'Inserted',key:'u',shortkey_name:'U',fn:{wiki(){this.singleTag('++');},xhtml(){this.singleTag('<ins>','</ins>');},},};jsToolBar.prototype.elements.del={group:'format',type:'button',title:'Deleted',key:'d',shortkey_name:'D',fn:{wiki(){this.singleTag('--');},xhtml(){this.singleTag('<del>','</del>');},},};jsToolBar.prototype.elements.quote={group:'format',type:'button',title:'Inline quote',fn:{async wiki(){await this.elements.quote.prompt.call(this,(response)=>{let endTag='';if(response.lang){endTag=`${endTag}|${response.lang}`;}
if(response.cite){if(!response.lang){endTag=`${endTag}|`;}
endTag=`${endTag}|${response.cite}`;}
endTag=`${endTag}}}`;this.encloseSelection('{{',endTag);});},async xhtml(){await this.elements.quote.prompt.call(this,(response)=>{let startTag='<q';if(response.cite){startTag=`${startTag} cite="${response.cite}"`;}
if(response.lang){startTag=`${startTag} lang="${response.lang}"`;}
startTag=`${startTag}>`;this.encloseSelection(startTag,'</q>');});},},async prompt(callback=null){const dialog=new jsDialog({title:this.toolbar.querySelector('.jstb_quote')?.title||this.elements.quote.title,confirm_label:this.cite_dialog.ok,cancel_label:this.cite_dialog.cancel,fields:[{default:this.cite_dialog.fields.default_url,html:this.cite_dialog.fields.url,},{default:this.cite_dialog.fields.default_lang,html:this.cite_dialog.fields.language,},],});await dialog.prompt().then((choice)=>{if(choice&&callback){const response=JSON.parse(choice);callback({cite:this.stripBaseURL(response[0]),lang:response[1],});return;}
this.toolbar.querySelector('.jstb_quote').focus();});},};jsToolBar.prototype.elements.code={group:'format',type:'button',title:'Code',fn:{wiki(){this.singleTag('@@');},xhtml(){this.singleTag('<code>','</code>');},},};jsToolBar.prototype.elements.mark={group:'format',type:'button',title:'Mark',fn:{wiki(){this.singleTag('""');},xhtml(){this.singleTag('<mark>','</mark>');},},};jsToolBar.prototype.elements.br={group:'br',type:'button',title:'Line break',fn:{wiki(){this.encloseSelection('%%%\n','');},xhtml(){this.encloseSelection('<br>\n','');},},};jsToolBar.prototype.elements.blockquote={group:'block',type:'button',title:'Blockquote',fn:{xhtml(){this.singleTag('<blockquote>','</blockquote>');},wiki(){this.encloseSelection('\n','',(str)=>`> ${str.replace(/\r/g, '').replace(/\n/g, '\n> ')}`);},},};jsToolBar.prototype.elements.pre={group:'block',type:'button',title:'Preformated text',fn:{wiki(){this.singleTag('///\n','\n///');},xhtml(){this.singleTag('<pre>','</pre>');},},};jsToolBar.prototype.elements.ul={group:'block',type:'button',title:'Unordered list',fn:{wiki(){this.encloseSelection('','',(str)=>`* ${str.replace(/\r/g, '').replace(/\n/g, '\n* ')}`);},xhtml(){this.encloseSelection('','',(str)=>`<ul>\n <li>${str.replace(/\r/g, '').replace(/\n/g, '</li>\n <li>')}</li>\n</ul>`);},},};jsToolBar.prototype.elements.ol={group:'block',type:'button',title:'Ordered list',fn:{wiki(){this.encloseSelection('','',(str)=>`# ${str.replace(/\r/g, '').replace(/\n/g, '\n# ')}`);},xhtml(){this.encloseSelection('','',(str)=>`<ol>\n <li>${str.replace(/\r/g, '').replace(/\n/g, '</li>\n <li>')}</li>\n</ol>`);},},};jsToolBar.prototype.elements.link={group:'link',type:'button',title:'Link',fn:{},accesskey:'l',key:'l',shortkey_name:'L',href_prompt:'Please give page URL:',hreflang_prompt:'Language of this page:',default_hreflang:'',prompt(href='',hreflang=''){let language=hreflang||this.elements.link.default_hreflang;const url=window.prompt(this.elements.link.href_prompt,href);if(!url){return false;}
language=window.prompt(this.elements.link.hreflang_prompt,language);return{href:this.stripBaseURL(url),hreflang:language,};},};jsToolBar.prototype.elements.link.fn.xhtml=function(){const link=this.elements.link.prompt.call(this);if(!link){return;}
let stag=`<a href="${link.href}"`;if(link.hreflang){stag=`${stag} hreflang="${link.hreflang}"`;}
stag=`${stag}>`;const etag='</a>';this.encloseSelection(stag,etag);};jsToolBar.prototype.elements.link.fn.wiki=function(){const link=this.elements.link.prompt.call(this);if(!link){return;}
const stag='[';let etag=`|${link.href}`;if(link.hreflang){etag=`${etag}|${link.hreflang}`;}
etag=`${etag}]`;this.encloseSelection(stag,etag);};jsToolBar.prototype.elements.img={group:'media',type:'button',title:'External image',src_prompt:'Please give image URL:',fn:{},prompt(src=''){return this.stripBaseURL(window.prompt(this.elements.img.src_prompt,src));},};jsToolBar.prototype.elements.img.fn.xhtml=function(){const src=this.elements.img.prompt.call(this);if(src){this.encloseSelection('','',(str)=>(str?`<img src="${src}" alt="${str}">`:`<img src="${src}" alt="">`));}};jsToolBar.prototype.elements.img.fn.wiki=function(){const src=this.elements.img.prompt.call(this);if(src){this.encloseSelection('','',(str)=>(str?`((${src}|${str}))`:`((${src}))`));}};jsToolBar.prototype.elements.preview={group:'editor',type:'button',title:'Preview',key:'p',shortkey_name:'P',format:{wysiwyg:false,wiki:true,xhtml:false,},fn:{wiki(){dotclear.jsonServicesPost('wikiConvert',(data)=>{if(data.ret&&data.msg){const src=`<div class="wiki_preview"><div class="wiki_markup">${data.msg}</div></div>`;$.magnificPopup.open({items:{src,type:'inline',},});}},{wiki:this.textarea.value},);},},};