1let editorSaveInterval,editors=[];class Editor{constructor(t,e,i,a,n="Editor"){switch(this.editorWindow=t,this.entity=e,this.fieldName=i,this.dirty=!1,a){case"full":this.history=new EditorHistory(this),$(this.editorWindow).off("keydown").on("keydown",t=>this.KeyDownOverrides(t)).on("keydown",t=>this.SetDirty()),$(this.editorWindow).off("paste").on("paste",t=>this.CleanPaste(t));let t=void 0!==e[i]?e[i]:e.settings[i];$(this.editorWindow).attr("contenteditable",!0).attr("placeholder",n).html(t),""==$(this.editorWindow).html()&&$(this.editorWindow).html("<p><br /></p>"),this.RenderFIBs(),this.ribbon=new Ribbon(this),this.tray=new Tray(this),this.AutoSaveOff(),this.AutoSaveOn(),$(this.editorWindow).on("click",t=>this.SetActiveElementFromClick(t));break;case"richtext":$(this.editorWindow).attr("contenteditable",!0).attr("data-format","richtext").attr("placeholder",n).addClass("editable-element").off("keydown").on("keydown",t=>this.SetDirty()).on("keydown",t=>{this.KeyDownOverridesSimple(t)}).off("blur").on("blur",t=>this.SaveIfDirty());break;default:$(this.editorWindow).attr("contenteditable","plaintext-only").attr("placeholder",n).addClass("editable-element").off("keydown").on("keydown",t=>this.SetDirty()).on("keydown",t=>{this.KeyDownOverridesSimple(t)}).off("blur").on("blur",t=>this.SaveIfDirty())}MandatoryCleanUp(this.editorWindow),this.SetDirty(),this.RenderFIBs(),this.activeElement=this.editorWindow,editors.push(this)}RenderFIBs(){$(this.editorWindow).find('input[data-role="fib"]').each((t,e)=>{$(e).val($(e).attr("data-value")),$(e).off("input").on("input",t=>{$(t.target).attr("data-value",$(t.target).val())})})}Destroy(){$(this.editorWindow).off().removeAttr("contenteditable").removeAttr("placeholder").removeClass("editable-element"),void 0!==editorSaveInterval&&clearInterval(editorSaveInterval),void 0!==this.ribbon&&this.ribbon.Destroy(),void 0!==this.ribbon&&this.tray.Destroy()}SetActiveElementFromClick(t){return this.SetActiveElement(t.target),this.tray.contextMenu.Show(),this.GetActiveElement()}SetActiveElement(t){return 0==$(t).parents(this.editorWindow).length&&(t=this.editorWindow),this.activeElement=t,this.activeElement}SetActiveElementAndPulse(t){this.SetActiveElement(t),this.PulseElement(t),ScrollTo(t)}GetActiveElement(){return null==this.activeElement||null==this.activeElement?this.SetA
1ctiveElement(this.editorWindow):this.activeElement}SetClean(){this.dirty&&(this.dirty=!1,void 0!==this.ribbon&&$(this.ribbon.element).find("#save-status").addClass("bi-check-lg").removeClass("bi-floppy2").removeClass("btn-danger").text("Saved"))}RemoveCitationManagementLinks(t){let e=0;return $(t).find("a").each((t,i)=>{$(i).attr("href").startsWith("https://www.zotero")&&($(i).replaceWith($(i).html()),e++)}),e>0&&Toast("Removed Links","A total of "+e+" links were removed."),t}RemoveStyles(t){return this.SaveState(),$(t).removeAttr("style"),$(t).find("[style]").removeAttr("style"),Toast("Removed Styles",'The "style" attribute was removed from the element and its children.'),t}RemoveClasses(t){return this.SaveState(),$(t).removeAttr("class"),$(t).find("[class]").removeAttr("class"),Toast("Removed Classes",'The "class" attribute was removed from the element and its children.'),t}UnwrapParagraphChildren(t){return this.UnwrapChildrenOfType(t,"p")}UnwrapBoldChildren(t){return t=this.UnwrapChildrenOfType(t,"b"),this.UnwrapChildrenOfType(t,"strong")}UnwrapChildrenOfType(t,e){return this.SaveState(),$(t).find(e).each((t,e)=>{$(e).replaceWith($(e).html())}),t}RemoveSpans(t){this.SaveState();let e=0;return $(t).is("span")&&(t=$($(t).replaceWith($(t).html()))[0],e++),$(t).find("span").each((t,i)=>{$(i).is("[data-glossary-term-id]")||($(i).replaceWith($(i).html()),e++)}),Toast("Removed Spans","A total of "+e+" spans were removed."),t}async ConvertBase64ImageStringsToFiles(t){$(t).find("img").each(async(t,e)=>{$(e).attr("src").startsWith("data:image/png;base64")&&(await ConvertBase64ImageStringToFile(e,current_book.book_id),Toast("Resaved Image","The image was resaved as a file."))}),$(t).is("img")&&$(t).attr("src").startsWith("data:image/png;base64")&&(await ConvertBase64ImageStringToFile(t,current_book.book_id),Toast("Resaved Image","The image was resaved as a file."),this.tray.Update())}async ResaveExternalImagesLocally(t){if(console.log("Starting resave"),$(t).find("img").each(async(t,e)=>{if(!$(e).attr("src").startsWith("/")){console.log("Resaving "+$(e).attr("src"));let t=await SaveImageLocally($(e).attr("src"),current_book.book_id);console.log("done"),$(e).attr("src",t),Toast("Resaved Image","The image was resaved locally.")}}),$(t).is("img")&&!$(t).attr("src").startsWith("/")){console.log("Resaving "+$(t).attr("src"));let e=await SaveImageLocally($(t).attr("src"),current_book.book_id);console.log("done"),$(t).attr("src",e),Toast("Resaved Image","The image was resaved locally.")}}FindReferences(t){let e=$(this.editorWindow).find("h2:contains('References')").nextAll("p");return e.addClass("reference"),Toast("References Found","A total of "+e.length+" references were found."),t}RemoveEmptyParagraphs(t){let e=$(this.editorWindow).find("p:empty"),i=e.length;return e.remove(),$(this.editorWindow).find("p").filter(function(){return"Â "===$(this).text().trim()}).each(function(){i++,$(this).remove()}),Toast("Removed Empty Paragraphs","A total of "+i+" empty paragraphs were removed."),t}DeGooglifyLinks(t){let e=0;return $(this.editorWindow).find('a[href^="https://www.google.com/url"]').each(function(){var t=new URL($(this).attr("href")).searchParams.get("q");t&&($(this).attr("href",t),e++)}),Toast("De-Googlify References","A total of "+e+" links were de-Googlified."),t}CleanHeadings(t){this.SaveState();let e=0;return $(t).is("h2,h3,h4,h5,h6")&&($(t).removeAttr("style").removeAttr("align"),$(t).find("em,b,i,strong").each((t,i)=>{$(i).replaceWith($(i).html()),e++})),$(t).find("h2,h3,h4,h5,h6").removeAttr("style").removeAttr("align").find("em,b,i,strong").each((t,i)=>{$(i).replaceWith($(i).html()),e++}),Toast("Removed Subelements","A total of "+e+" subelements were removed."),t}RemoveNBSPs(t){$(t).html(function(t,e){return e.replace(/ /g," ")})}WrapLinksInATags(t){return this.SaveState(),$(t).html(WrapLinksInATags($(t).html())),this.SetDirty(),t}FindImageMissingAlt(){let t=$(this.editorWindow).find("img:not([alt])");if(t.length>0){let e=t[0];this.SetActiveElement(e),ScrollTo(e),this.PulseElement(e),Toast("Image Found","A total of "+t.length+' images with missing "alt" attributes were found. The first image has been selected.',"bg-warning text-light"),setTimeout(this.PromptForImageAlt,0,e,this)}else Toast("No Images Found",'No images with missing "alt" attributes were found.',"bg-success text-light")}async PromptForImageAlt(t,e){let i=$(t).attr("src"),a=window.prompt('Found an image at "'+i+'". Would you like to add an alt tag?',"");null!=a&&""!=a&&(console.log(a),$(t).attr("alt",a),null!=e&&e.FindImageMissingAlt())}SetDirty(){this.dirty||(this.dirty=!0,void 0!==this.ribbon&&$(this.ribbon.element).find("#save-status").removeClass("bi-check-lg").addClass("bi-floppy2").addClass("btn-danger").text("Unsaved"))}
1SetCursorPosition(t=this.GetActiveElement(),e=!0){this.SetActiveElement(t);let i=document.createRange(),a=window.getSelection();i.selectNodeContents(t),i.collapse(e),a.removeAllRanges(),a.addRange(i),t.focus()}CleanPaste(t){t.preventDefault(),null!=this.history&&this.history.SaveState();const e=t.originalEvent.clipboardData||window.clipboardData,i=e.getData("text/html"),a=e.getData("text/plain");let n;if(i){const t=(new DOMParser).parseFromString(i,"text/html"),e=t=>{t.removeAttribute("style");for(const i of t.children)e(i)};e(t.body),n=t.body.innerHTML}else n=a;const r=window.getSelection();if(r.rangeCount>0){const t=r.getRangeAt(0),e=document.createDocumentFragment(),i=document.createElement("div");for(i.innerHTML=n;i.firstChild;)e.appendChild(i.firstChild);t.deleteContents(),t.insertNode(e),t.collapse(!1),r.removeAllRanges(),r.addRange(t)}}AutoSave(){this.SaveIfDirty()}ToggleEditor(){ToggleEditor()}SaveIfDirty(){this.dirty&&this.Save()}ToggleAutoSave(){$(this.ribbon.element).find('[data-ribbon-action="ToggleAutoSave"]').each((t,e)=>{void 0===editorSaveInterval?this.AutoSaveOn(e):this.AutoSaveOff(e)})}AutoSaveOff(t=null){null!==t&&($(t).removeClass("bi-toggle-on"),$(t).addClass("bi-toggle-off"),$(t).removeClass("text-primary"),Toast("Auto Save Off","Auto save was turned off.","bg-warning text-dark","bi-x-lg")),void 0!==editorSaveInterval&&clearInterval(editorSaveInterval)}AutoSaveOn(t=null){null!==t&&($(t).removeClass("bi-toggle-off"),$(t).addClass("bi-toggle-on"),$(t).addClass("text-primary"),Toast("Auto Save On","Auto save was turned on.","bg-success","bi-check-lg")),void 0!==editorSaveInterval&&clearInterval(editorSaveInterval),editorSaveInterval=setInterval(()=>{this.AutoSave()},6e4)}GetElementFromCaretPosition(){let t=window.getSelection().anchorNode;return null!=t&&(3===t.nodeType&&(t=t.parentNode),0==$(t).parents(this.editorWindow).length&&(t=null)),null==t&&(t=this.editorWindow),t}SaveState(){null!=this.history&&this.history.SaveState()}ToggleBold(t){return this.SaveState(),ToggleRangeElement(t,"strong","fw-bold")}ToggleItalic(t){return this.SaveState(),ToggleRangeElement(t,"em","fst-italic")}ToggleUnderline(t){return this.SaveState(),ToggleRangeElement(t,"span","text-decoration-underline","text-decoration-underline")}ToggleStrikethrough(t){return this.SaveState(),ToggleRangeElement(t,"span","text-decoration-line-through","text-decoration-line-through")}ToggleSubscript(t){return this.SaveState(),ToggleRangeElement(t,"sub")}ToggleSuperscript(t){return this.SaveState(),ToggleRangeElement(t,"sup")}ToggleLink(t){return this.SaveState(),ToggleRangeElement(t,"a",null,null,{href:"#"})}ToggleGlossaryTerm(t){return this.SaveState(),ToggleRangeElement(t,"span",null,null,{"data-glossary-term-id":0})}ToggleIndexTerm(t){this.SaveState();let e=ToggleRangeElement(t,"span",null,null,{"data-index-term":!0});return $(e).attr("data-index-term",$(e).text()),$(e)[0]}ToggleFootnote(t){return this.SaveState(),ToggleRangeElement(t,"sup",null,null,{"data-footnote-id":0})}Undo(){return null!=this.editor.history&&this.history.Undo(),this.GetActiveElement()}Redo(){return null!=this.editor.history&&this.history.Redo(),this.GetActiveElement()}MoveUp(t){return this.SaveState(),$(t).prev().length>0&&$(t).insertBefore($(t).prev()),ScrollTo(t),this.PulseElement(t),t}ParagraphAbove(t){this.SaveState();let e=$("<p><br /></p>")[0];return $(e).insertBefore(t),t=this.SetActiveElement(e),this.PulseElement(t),t}ParagraphBelow(t){this.SaveState();let e=$("<p><br /></p>")[0];return $(e).insertAfter(t),t=this.SetActiveElement(e),this.PulseElement(t),t}Clone(t){this.SaveState();let e=$(t).clone()[0];return $(e).insertAfter(t),t=this.SetActiveElement(e),$(t).removeAttr("id"),$(t).find("*").removeAttr("id"),this.PulseElement(t),t}MoveToTop(t){return this.SaveState(),$(t).parent().prepend(t),ScrollTo(t),this.PulseElement(t),t}MoveDown(t){return this.SaveState(),$(t).next().length&&$(t).insertAfter($(t).next()),ScrollTo(t),this.PulseElement(t),t}MoveToBottom(t){return this.SaveState(),$(t).parent().append(t),ScrollTo(t),this.PulseElement(t),t}MoveIn(t){return this.SaveState(),$(t).prev().length>0&&$(t).prev().append(t),ScrollTo(t),this.PulseElement(t),t}MoveOut(t){return this.SaveState(),$(t).parent().is(this.editorWindow)||$(t).parent().after(t),ScrollTo(t),this.PulseElement(t),t}Expand(t){this.SaveState();let e=$(t).next();return e.length>0&&$(t).append(e),this.PulseElement(e),t}Contract(t){this.SaveState();let e=$(t).children();return e.length>0&&e.last().insertAfter(t),this.PulseElement(e),t}IndentList(t,e=1){if(!$(t).is("li"))return t;if(e>0)$(t).wrap("<ul></ul>");else{let e=$(t).parentsUntil(this.editorWindow,"ul,ol");if(e.length>1){let i=$($(e).eq(0).html());$(e).eq(0).replaceWith(i),t=i.find("li").last()}}return t}EmphasizeAPATitles(t){return $(t).find(".reference").each((t,e)=>{$(e).html(EmphasizeAPATitle($(e).html()))}),t}async CleanUp(t){this.SaveState();let e=["style","class","height","width","data-mce-style","data-mce-src","data-anchor-name"];switch($(t).prop("tagName")){case"DIV":break;case"FIGURE":case"IMG":$(t).removeAttr("class");break;default:for(let i of e)$(t).removeAttr(i)}return $(t).children().each(async(t,e)=>{await CleanUp(e)}),t}PulseElement(t){return $(t).removeAttr("data-pulse").attr("data-pulse",!0),setTimeout(()=>{$(t).removeAttr("data-pulse")},1e3),this.GetActiveElement()}
1OpenInCodeEditor(t){return this.SetActiveElement(t),this.tray.codeEditor.Show(),t}Delete(t){if(this.SaveState(),!$(t).is(this.editorWindow)&&$(t).parent(this.editorWindow).length>0){let e=$(t).parent();return $(t).remove(),e[0]}return Toast("Access Denied","That element cannot be deleted.","danger"),null}Unwrap(t,e=!0){if(this.SaveState(),!$(t).is(this.editorWindow)&&$(t).parent(this.editorWindow).length>0){let e=$(t).parent();return $(t).replaceWith($(t).html()),e[0]}return Toast("Access Denied","That element cannot be unwrapped.","danger"),null}ChangeTag(t,e){this.SaveState();let i=$(t).prop("tagName");if(i!==e){console.log("Changing from "+i+" to "+e);let a=$("<"+e+"/>");if(void 0!==$(t)[0].attributes)for(let e=0;e<$(t)[0].attributes.length;e++){let i=$(t)[0].attributes[e];1==i.specified&&a.attr(i.name,i.value)}$(t).after(a);let n=$(t).html();return a.html(n),$(t).remove(),a.get(0)}return t}async Save(){$(this.editorWindow).attr("disabled",!0),$(this.editorWindow).find("[data-pulse]").removeAttr("data-pulse");let t=null;t=["INPUT","TEXTAREA"].includes($(this.editorWindow).prop("tagName"))?$(this.editorWindow).val():"code"==$(this.editorWindow).attr("data-format")?$(this.editorWindow).text():($(this.editorWindow).attr("data-format"),$(this.editorWindow).html());let e={};e[this.fieldName]=t;try{await SaveSetting(this.entity.type,this.entity.id,e),$(this.editorWindow).removeAttr("disabled"),this.SetClean(),Toast("Saved","The content was successfully saved.","bg-success")}catch(t){return console.error(t),Toast("Error Saving",t,"bg-danger"),null}return this.GetActiveElement()}KeyDownOverridesSimple(t){if("Enter"===t.key)t.preventDefault(),this.SaveIfDirty()}KeyDownOverrides(t){switch(t.key){case"ArrowDown":case"ArrowUp":case"ArrowRight":case"ArrowLeft":setTimeout(()=>{let t=this.GetElementFromCaretPosition();this.SetActiveElement(t),this.tray.Update()},0);break;case"Enter":setTimeout(()=>{let t=this.GetElementFromCaretPosition();"DIV"==$(t).prop("tagName")&&(t=this.ChangeTag(t,"p")),this.SetActiveElement(t),this.tray.Update()},0);break;case"Backspace":case"Delete":console.log("Hit delete / backspace"),setTimeout(()=>{this.SetActiveElement(this.GetElementFromCaretPosition()),$(this.GetActiveElement()).find("span[style]").not("[class]").each((t,e)=>{this.Unwrap(e)}),this.tray.Update()},0)}if(t.metaKey)switch(t.key){case"z":t.preventDefault(),t.shiftKey?this.history.Redo():this.history.Undo();break;case"b":setTimeout(()=>{this.SetActiveElement(this.GetElementFromCaretPosition()),$(this.GetActiveElement()).is("b")?(this.SetCursorPosition(this.ChangeTag(this.GetActiveElement(),"strong")),this.tray.Update()):$(this.GetActiveElement()).is("strong")&&(this.SetActiveElement(Unwrap(this.GetActiveElement())),this.tray.Update())},0);break;case"i":setTimeout(()=>{this.SetActiveElement(this.GetElementFromCaretPosition()),$(this.GetActiveElement()).is("i")?(this.SetCursorPosition(this.ChangeTag(this.GetActiveElement(),"em")),this.tray.Update()):$(selthisf.GetActiveElement()).is("em")&&(this.SetActiveElement(Unwrap(this.GetActiveElement())),this.tray.Update())},0);break;case"u":setTimeout(()=>{this.SetActiveElement(this.GetElementFromCaretPosition()),$(this.GetActiveElement()).is("u")?(this.SetCursorPosition(this.ChangeTag(this.activeElement,"span")),$(this.GetActiveElement()).addClass("text-decoration-underline"),this.tray.Update()):$(this.activeElement).is("span.text-decoration-underline")&&(this.SetActiveElement(Unwrap(this.GetActiveElement())),this.tray.Update())},0);break;case"k":setTimeout(()=>{this.SetActiveElement(this.ToggleLink(this.GetElementFromCaretPosition())),this.tray.Update()},0)}}}class AuthorshipTable{constructor(t,e){this.entity=t,this.element=e,this.list=$(this.element).find("#author-list"),this.search=$(this.element).find("#author-search"),this.searchResults=$(this.element).find("#author-search-results")}DoAuthorRow(t){let e=$("<div></div>").addClass("d-flex flex-row align-items-center border rounded my-1").text(t.name).attr("data-entity-type","author").attr("data-entity-id",t.author_id),i=($("<img>").attr("src",t.bio_pic).addClass("rounded-circle me-2 border").css({"max-height":"40px"}).prependTo(e),$("<a></a>").attr("href","/author/"+t.author_id+"/view").attr("target","_blank").addClass("bi-person btn ms-auto rounded-end-0").appendTo(e),$("<grip></grip>").addClass("btn bi-arrows-vertical").attr("data-role","grip").prependTo(e),$("<button></button>").addClass("btn rounded-0").appendTo(e));return 1==t.shadow_author?i.removeClass("bi-eye").addClass("bi-eye-slash"):i.removeClass("bi-eye-slash").addClass("bi-eye"),i.on("click",async t=>{if($(t.target).is("[disabled]"))return;$(t.target).attr("disabled",!0);let e=$(t.target).hasClass("bi-eye")?1:0;await ChangeAuthorVisibility(this.entity,$(t.target).closest('[data-entity-type="author"][data-entity-id]').attr("data-entity-id"),e),$(t.target).toggleClass("bi-eye").toggleClass("bi-eye-slash"),$(t.target).removeAttr("disabled")}),$("<button></button>").addClass("btn text-danger bi-x-lg rounded-start-0").appendTo(e).on("click",async t=>{await RemoveAuthor(this.entity,$(t.target).closest('[data-entity-type="author"][data-entity-id]').attr("data-entity-id")),$(t.target).off("click"),$(t.target).parent().remove()}),e}Render(){this.list.empty(),this.searchResults.empty(),this.search.val("");for(let t of this.entity.authorships)this.list.append(this.DoAuthorRow(t));this.search.on("input",async t=>{clearTimeout(searchTimeout);let e=$(t.target).val();e.length>0?searchTimeout=setTimeout(async t=>{this.searchResults.empty();let i=await Search(e,["authors"],20,{method:"show_all"});for(let t in i.authors){let e=i.authors[t],a=$("<button></button>").text(e.name).addClass("btn btn-light text-start m-1 bi-plus-lg icon-text-link w-100").attr("data-entity-type","author").attr("data-entity-id",e.author_id);this.searchResults.append(a),a.on("click",async t=>{let e=$(t.target).closest('[data-entity-type="author"][data-entity-id]').attr("data-entity-id"),i=await AddAuthor(this.entity,e);switch(console.log(i),this.entity.type){case"chapter":this.entity=await GetChapterFromID(this.entity.id,!0),this.Render();break;case"book":this.entity=await GetBook(this.entity.id,!0),this.Render()}})}},searchDelay):this.searchResults.empty()}),$(this.list).sortable({handle:'grip[data-role="grip"]',items:"div[data-entity-id]",axis:"y",revert:!0,scrollSpeed:6,opacity:.8,update:async t=>{let e=t.target;$(e).sortable("disable");let i=[];$(e).children("div[data-entity-id]").each(function(){i.push($(this).attr("data-entity-id"))});try{await SortAuthors(this.entity,i)&&Toast("Author Order Saved","The author order has been saved.","bg-success text-light")}finally{$(e).sortable("enable")}}})}}class KeywordEditor{constructor(t,e){this.container=t,this.entity=e,console.log(this.entity),this.searchBox=$(this.container).find("#keyword-search"),this.resultsContainer=$(this.container).find("#keyword-search-results").empty(),this.keywordListContainer=$(this.container).find("#keyword-list"),this.generatorBtn=$(this.container).find("#keyword-generator-btn")}async Initialize(){this.InitKeywordList(),this.InitSearchBox(),$(this.container).find('[data-role="create-keyword"]').off("
1click").on("click",{searchBox:this.searchBox},async t=>{await CreateKeywords($(t.data.searchBox).val()),$(t.data.searchBox).trigger("input")}),this.generatorBtn.off("click").on("click",{keywordEditor:this},async t=>{switch(console.log("Generating keywords"),$(t.data.keywordEditor.keywordListContainer).html(Spinner()),console.log(t.data.keywordEditor.entity),t.data.keywordEditor.entity.type){case"chapter":await GenerateChapterKeywords(t.data.keywordEditor.entity.chapter_id),current_chapter=await GetChapterFromID(t.data.keywordEditor.entity.chapter_id,!0),t.data.keywordEditor.entity=current_chapter;break;case"book":await GenerateBookKeywords(t.data.keywordEditor.entity.book_id),current_book=await GetBook(t.data.keywordEditor.entity.book_id,!0),t.data.keywordEditor.entity=current_book;break;default:return void console.warn("Invalid type "+t.data.keywordEditor.entity.type)}t.data.keywordEditor.InitKeywordList(),Toast("Keywords Generated","The keywords were generated.")})}InitKeywordList(){this.keywordListContainer.empty();for(let t of this.entity.keyword_links){let e=$("<button></button>");e.attr("class","btn btn-light rounded-pill mx-1 px-3 my-1 keyword").text(t.keyword_display).attr("data-entity-id",t.keyword_id).appendTo(this.keywordListContainer),$('<span class="bi-x-lg ms-2"></span>').appendTo(e),e.on("click",{keyword_id:t.keyword_id,entity:this.entity},async t=>{await RemoveKeyword(t.data.keyword_id,t.data.entity.type,t.data.entity.id),$(e).remove()})}}InitSearchBox(){$(this.searchBox).off("input").on("input",{searchBox:this.searchBox,resultsContainer:this.resultsContainer,keywordEditor:this},async function(t){clearTimeout(searchTimeout);let e=$(t.data.searchBox).val();e.length>0?(t.data.resultsContainer.empty().append(SpinnerLG()),searchTimeout=setTimeout(async function(){let i=await KeywordSearch(e);t.data.resultsContainer.empty();for(let e of i){$("<button></button>").addClass("m-1 btn btn-primary bi-plus-lg rounded-pill icon-text-link").text(e.keyword_display).appendTo(t.data.resultsContainer).on("click",{keyword_id:e.keyword_id,keyword_display:e.keyword_display,keywordEditor:t.data.keywordEditor},function(t){AddKeyword(t.data.keyword_id),$(this).fadeOut(),0==$(t.data.keywordEditor.keywordListContainer).find('[data-entity-id="'+t.data.keyword_id+'"]').length&&t.data.keywordEditor.entity.keyword_links.push({keyword_id:t.data.keyword_id,keyword_display:t.data.keyword_display}),t.data.keywordEditor.InitKeywordList()})}},searchDelay)):(clearTimeout(searchTimeout),t.data.resultsContainer.empty())})}}async function ToggleEditor(t){if(console.log("Toggling editor"),0==editors.length){let e=$(t).closest("[data-entity-type][data-entity-id]").attr("data-entity-type"),i=$(t).closest("[data-entity-type][data-entity-id]").attr("data-entity-id");switch(console.log("Enabling editor on "+e+" "+i),e){case"chapter":console.log("Enabling chapter editor");let t=await GetChapterFromID(i);new Editor($("#chapter-contents")[0],t,"text","full","Place your content here..."),new Editor($("#chapter-title")[0],t,"title","simple","Title"),new Editor($("#chapter-subtitle")[0],t,"subtitle","simple","Subtitle"),new Editor($("#order-number")[0],t,"order_number","simple","Number"),new Editor($("#abstract")[0],t,"abstract","simple","Abstract"),$("#abstract_wrapper").show().addClass("d-flex");let e=$("<button></button>").addClass("btn bi-lightning-charge bi-teal my-5").attr("data-bs-title","Generate with AI").attr("data-bs-placement","left").appendTo($("#abstract_wrapper")[0]);RegisterTooltips("#abstract_wrapper"),$(e).on("click",()=>{current_chapter.GenerateAbstract()});break;case"book":let a=await GetBook(i);new Editor($("#main-upper h1")[0],a,"title","simple","Book Title"),new Editor($("#main-upper #subtitle")[0],a,"subtitle","simple","Subtitle"),HasSetting(a,"si_title")&&new Editor($("#main-upper #si-title")[0],a,"si_title","simple","Special Issue Title"),new Editor($("#main-upper #abstract")[0],a,"abstract","simple","Abstract"),HasSetting(a,"announcement")&&new Editor($("#main-upper #announcement")[0],a,"announcement","simple","Announcement"),HasSetting(a,"editor_notes")&&new Editor($("#main-upper #editor-notes")[0],a,"editor_notes","simple","Editor Notes"),HasSetting(a,"si_editors")&&new Editor($("#main-upper #si-editors")[0],a,"si_editors","simple","Special Issue Editors"),new TOCEditor($("#main #toc")[0],a),new CoverUploader($("#book_cover_img")[0],a);break;case"page":console.log("Enabling page editor");let n=await GetPage(i);new Editor($("#page-contents")[0],n,"text","full","Page Body","full"),new Editor($("#page-title")[0],n,"title","simple","Title");break;case"author":console.log("Enabling author editor");let r=await GetAuthor(i);new Editor($("#author-name")[0],r,"name","simple","Name"),new Editor($("#author-affiliation")[0],r,"affiliation","simple","Affiliation"),new Editor($("#author-bio")[0],r,"bio","simple","Bio"),new AuthorImageUploader($("#author-image")[0],r),$('[data-entity-type="article"]').each(async(t,e)=>{const i=$(e).find(".article-citation")[0]||e,a=$(e).find(".article-year")[0];if(""==$(i).text().trim())return console.log(e),await DeleteArticle(r.id,$(e).attr("data-entity-id")),void $(e).remove();
1$(e).find(".article-editor-controls").removeClass("d-none"),a&&new Editor(a,articles[$(e).attr("data-entity-id")],"year","simple","Year"),new Editor(i,articles[$(e).attr("data-entity-id")],"citation","richtext","Citation")})}$('button[data-action="ToggleEditor"]').removeClass("bi-pencil-fill").addClass("bi-x-lg"),$("#chapter-editor-button").remove(),$("#ask-ai-fab").hide(),"function"==typeof CloseAIChat&&CloseAIChat()}else DisableEditors(),RenderFromPath(window.location.pathname,!0)}async function DisableEditors(){for(let t of editors)null!=t&&t.Destroy();editors=[],$('button[data-action="ToggleEditor"]').addClass("bi-pencil-fill").removeClass("bi-x-lg"),$("#ask-ai-fab").data("chapter-id")&&$("#ask-ai-fab").data("ai-enabled")&&$("#ask-ai-fab").show()}async function RenderSettingHeading(t,e){let i=$("<th></th>").attr("colspan",2).text(e).addClass("fs-4 pt-3"),a=$("<tr></tr>").append(i);t.append(a)}async function RenderSettingRole(t,e,i,a){let n=e.roles.includes(a),r=$("<tr><th></th><td></td></tr>"),s=r.children("th"),o=r.children("td").first();s.first().html(i).off("click").on("click",function(){$(this).next("td").find("input, textarea, select").first().focus()}),input=$("<input></input>").addClass("form-check-input m-0 fs-3 mb-2").attr("type","checkbox").attr("role","switch");let l=$('<div class="form-check form-switch"></div>');n&&$(input).prop("checked",!0),l.append(input).appendTo(o),input.off("change").on("change",{id:e.id,role:a},async t=>{$(t.target).is(":checked")?await GrantRole(t.data.id,t.data.role):await RevokeRole(t.data.id,t.data.role)}),t.append(r)}async function RenderSettingRoleSelect(t,e,i,a){let n=$("<tr><th></th><td></td></tr>"),r=n.children("th"),s=n.children("td").first();r.first().html(i).off("click").on("click",function(){$(this).next("td").find("input, textarea, select").first().focus()}),input=$("<select></select>").addClass("form-select m-0 fs-5 mb-2").appendTo(s);let o=[];for(let t of a){o.push(t.value);let i=$("<option></option>").text(t.label).val(t.value).appendTo(input);e.roles.includes(t.value)&&i.attr("selected",!0)}input.off("change").on("change",{id:e.id,roles:o},async t=>{await GrantRole(t.data.id,$(t.target).val(),{conflicts:t.data.roles})}),t.append(n)}async function RenderSetting(t,e,i,a,n="text",r=[]){let s=e[i];null==s&&(s=e.settings[i]),null==s&&(s="");let o=$("<tr><th></th><td></td></tr>"),l=o.children("th"),d=null,h=o.children("td").first();l.first().html(a).off("click").on("click",function(){$(this).next("td").find("input, textarea, select").first().focus()});let c=null;switch(n){case"select":let t=$("<select></select>");t.addClass("form-select");for(let a of r){let n=$("<option></option>");n.val(a.value).html(a.label),a.value!=e.settings[i]&&a.value!=e[i]||n.attr("selected",!0),t.append(n)}h.append(t),t.off("change").on("change",async function(){let t={};t[i]=$(this).val(),$(this).attr("disabled",!0),SaveSetting(e.type,e.id,t)?$(this).removeAttr("disabled"):$(this).addClass("is-invalid")});break;case"switch":c=$("<input></input>").addClass("form-check-input m-0 fs-3 mb-2").attr("type","checkbox").attr("role","switch"),d=$('<div class="form-check form-switch"></div>'),1==s&&$(c).prop("checked",!0),d.append(c).appendTo(h),c.off("change").on("change",async function(){let t={};t[i]=$(this).is(":checked")?1:0,$(this).attr("disabled",!0),await SaveSetting(e.type,e.id,t)?$(this).removeAttr("disabled"):$(this).addClass("is-invalid")});break;case"switch-invert":c=$("<input></input>").addClass("form-check-input m-0 fs-3 mb-2").attr("type","checkbox").attr("role","switch"),d=$('<div class="form-check form-switch"></div>'),null!=s&&0!=s||$(c).prop("checked",!0),d.append(c).appendTo(h),c.off("change").on("change",async function(){let t={};t[i]=$(this).is(":checked")?0:1,$(this).attr("disabled",!0),await SaveSetting(e.type,e.id,t)?$(this).removeAttr("disabled"):$(this).addClass("is-invalid")});break;case"move-chapter":if(c=$("<select></select>").addClass("form-select").addClass("rounded-start-0").attr("data-entity-id",e.id),null!==current_user){for(let t of await GetBookLinksForAuthor(current_user.id)){let i=$("<option></option>").text(t.text).attr("value",t.entity_id).appendTo(c);t.entity_id==e.book_id&&i.attr("selected",!0)}h.append(c),c.off("change").on("change",async function(){$(this).attr("disabled",!0),await MoveChapter($(this).closest("[data-entity-id]").attr("data-entity-id"),$(this).val())?(Toast("Content Moved","The content was moved to a new publication.","bg-success text-light"),$(this).removeAttr("disabled")):$(this).addClass("is-invalid")})}break;case"rename-chapter":c=$("<input></input>"),c.val(s).addClass("rounded-start-0").addClass("form-control").attr("required",!0),h.append(c).attr("data-field",i),c.off("change").on("change",async function(){if(""==$(this).val())return;$(this).removeClass("is-invalid"),$(this).attr("disabled",!0);let t=$(this).val();console.log("Changing the chapter URI to "+t),await RenameChapter(e.id,e.book_id,t)?(Toast("Address Changed","The address (location or URI) was successfully changed.","bg-success text-light"),$(this).removeAttr("disabled")):($(this).removeAttr("disabled"),$(this).addClass("is-invalid"))});break;case"rename-book":c=$("<input></input>"),c.val(s).addClass("rounded-start-0").addClass("form-control").attr("required",!0),h.append(c).attr("data-field",i),c.off("change").on("change",async function(){if(""!=$(this).val()){$(this).removeClass("is-invalid"),$(this).attr("disabled",!0);try{await RenameBook(e.id,$(this).val())?(Toast("Address Changed","The address (location or URI) was successfully changed.","bg-success text-light"),$(this).removeAttr("disabled")):($(this).removeAttr("disabled"),$(this).addClass("is-invalid")),$(this).val(current_book.short_name)}catch(t){console.error(t),$(this).removeAttr("disabled"),$(this).addClass("is-invalid"),Toast("Error",t,"bg-danger text-light")}}});break;case"button":let n=$("<button></button>").text(a).addClass("btn btn-primary").attr("data-action",r[0]);r.length>0&&n.attr("data-action-value",r[1]),h.append(n);break;case"textarea":c=$("<textarea></textarea>").attr("rows",4);default:null==c&&(c=$("<input></input>")),c.val(s).addClass("rounded-start-0"),h.append(c).attr("data-field",i),c.addClass("form-control").off("change").on("change",async function(){let t={};t[i]=$(this).val(),$(this).attr("disabled",!0),await SaveSetting(e.type,e.id,t)?$(this).removeAttr("disabled"):$(this).addClass("is-invalid")})}t.append(o)}class Tray{constructor(t){this.editor=t,this.Initialize()}async Initialize(){0==$("#editor-tray").length&&$(await GetTemplate("editor-tray")).insertAfter($("#main-window")[0]),this.element=$("#editor-tray")[0],$("body").addClass("tray-active"),RegisterTooltips(this.element),
10==$("#editor-tray-controls").length&&$(await GetTemplate("editor-tray-controls")).insertAfter(this.element),this.controls=$("#editor-tray-controls")[0],RegisterTooltips(this.controls),this.codeEditor=new CodeEditor(this,$(this.element).find("#editor-tray-code-box")[0]),this.contextMenu=new ContextMenu(this,$(this.element).find("#editor-tray-context-menu")[0]),this.functionsMenu=$(this.element).find("#editor-tray-functions")[0],this.snippetMenu=$(this.element).find("#editor-tray-snippets")[0],this.outlineEditor=new OutlineEditor(this,$(this.element).find("#editor-tray-outline")[0]),this.revisionMenu=new RevisionMenu(this,$(this.element).find("#editor-tray-revisions-list")[0]),$(this.snippetMenu).find("button").on("click",t=>this.InsertSnippet(t)),$(this.controls).find("button").on("click",t=>this.SwitchSubtray(t)),$(this.element).find("[data-tray-action]").off().on("click",t=>this.TrayAction(t)),this.SwitchSubtray({target:$("#editor-tray-snippets")[0]}),$(this.element).find("#editor-tray-add-element-filter").off("input").on("input",t=>{let e=$(t.target).attr("data-target"),i=$(e),a=$(t.target).val().toLowerCase();$(i).find("button").each((t,e)=>{$(e).text().toLowerCase().includes(a)?$(e).show():$(e).hide()})})}Destroy(){$(this.element).remove(),$(this.controls).remove(),$("body").removeClass("tray-active")}async TrayAction(t){console.log("Trying "+$(t.target).attr("data-tray-action"));let e=$(t.target).attr("data-parent-offset");try{let i=this.editor.GetActiveElement();e>0&&(i=$(this.editor.GetActiveElement()).parents()[e-1]);let a=$(t.target).attr("data-tray-action");this.editor.SetCursorPosition(await this.editor[a](i)),"Save"==a||this.editor.SetDirty(),this.editor.tray.Update()}catch(t){console.error(t)}}SwitchSubtray(t){switch($(t.target).attr("data-target")){case"#editor-tray-context-menu":this.editor.tray.contextMenu.Show();break;case"#editor-tray-code-box":this.editor.tray.codeEditor.Show();break;case"#editor-tray-outline":this.editor.tray.outlineEditor.Show();break;case"#editor-tray-revisions-list":this.editor.tray.revisionMenu.Show();break;case"#editor-tray-functions":$(this.editor.tray.functionsMenu).addClass("d-flex").show().siblings("div").removeClass("d-flex").hide(),$(this.editor.tray.controls).find('[data-target="#editor-tray-functions"]').addClass("active").siblings("button").removeClass("active");break;default:$(this.editor.tray.snippetMenu).addClass("d-flex").show().siblings("div").removeClass("d-flex").hide(),$(this.editor.tray.snippetMenu).find("input").first().focus(),$(this.editor.tray.controls).find('[data-target="#editor-tray-snippets"]').addClass("active").siblings("button").removeClass("active")}}Update(){$(this.contextMenu.element).is(":visible")?this.contextMenu.Update():$(this.codeEditor.element).is(":visible")&&this.codeEditor.Update()}InsertSnippet(t){let e=t.target;$(e).is("button")||(e=$(e).parent("button").first());let i=$($(e).find("textarea").val());if("inline"==$(e).attr("data-insert-type")){let t=window.getSelection().getRangeAt(0);var a=t.startContainer,n=t.endContainer;let e=t.extractContents();a===n?(t.insertNode(i[0]),i.is("input")&&i.attr("data-value",$(e).text()).val($(e).text())):Toast("Not Allowed","Running that function on multiple elements is not allowed. Please make sure that your highlighted selection is limited to a single element.","bg-warning text-dark")}else 0==$(this.editor.GetActiveElement()).parents("[contenteditable]").length?(console.log("Appending to window"),$(this.editor.editorWindow).append(i)):(console.log("Appending to element"),$(this.editor.GetActiveElement()).is(":block")||this.editor.SetActiveElement($(this.editor.GetActiveElement()).parents("p,div,ul,ol,dl")[0]),console.log(this.editor.GetActiveElement()),$(this.editor.GetActiveElement()).is("[contenteditable]")?$(this.editor.GetActiveElement()).append(i):$(this.editor.GetActiveElement()).after(i));for(this.editor.SetActiveElement(i[0]);$(this.editor.GetActiveElement()).children().length>0;){let t=$(this.editor.GetActiveElement()).children()[0];if($(t).is("br"))break;this.editor.SetActiveElement(t)}this.editor.history.SaveState(),this.editor.SetCursorPosition(),this.editor.RenderFIBs(),this.editor.tray.contextMenu.Show(),ScrollTo(this.editor.GetActiveElement()),this.editor.PulseElement(this.editor.GetActiveElement()),this.editor.SetDirty()}}class RevisionMenu{constructor(t,e){this.tray=t,this.element=e}async Show(){$(this.element).find("#revision-list").empty().append(SpinnerXL()),$(this.element).addClass("d-flex").show().siblings("div").removeClass("d-flex").hide(),$(this.tray.controls).find('[data-target="#'+this.element.i
1d+'"]').addClass("active").siblings("button").removeClass("active"),this.Update()}async Update(){let t=$(this.element).find("#revision-list"),e=await GetRevisions(this.tray.editor.entity.id,!0);t.empty();for(let i of e){let e=$("<button></button>").text(this.FormatDate(i.created)+" by "+i.author_name).addClass("btn text-start w-100 bi-clock-history icon-text-link");t.append(e),$(e).on("click",{revision:i},t=>{$(this.tray.editor.editorWindow).html(t.data.revision.text),this.tray.editor.SetDirty()})}}FormatDate(t){const e=new Date(t),i=new Intl.DateTimeFormat("en-US",{year:"numeric",month:"2-digit",day:"2-digit",hour:"numeric",minute:"2-digit",hour12:!0,timeZoneName:"short"}).formatToParts(e);return`${i.find(t=>"month"===t.type).value}/${i.find(t=>"day"===t.type).value}/${i.find(t=>"year"===t.type).value} @ ${i.find(t=>"hour"===t.type).value}:${i.find(t=>"minute"===t.type).value}${i.find(t=>"dayPeriod"===t.type).value.toLowerCase()}`}}class OutlineEditor{constructor(t,e){this.tray=t,this.element=e}async Show(){$(this.element).addClass("d-flex").show().siblings("div").removeClass("d-flex").hide(),$(this.tray.controls).find('[data-target="#'+this.element.id+'"]').addClass("active").siblings("button").removeClass("active"),this.Update()}async Update(){let t=$(this.element).find("#outline-content")[0];$(t).empty(),$("#chapter-contents").find("h2,h3,h4,h5,h6").each((e,i)=>{let a=$("<div></div>").addClass("d-flex").appendTo(t);$("<button></button>").text($(i).text()).addClass("btn flex-grow-1 text-start").appendTo(a).on("click",{element:i,editor:this.tray.editor},t=>{ScrollTo(t.data.element),t.data.editor.SetActiveElement(i)}),$(i).is("h3")?$(a).css("padding-left","30px"):$(i).is("h4")?$(a).css("padding-left","60px"):$(i).is("h5")?$(a).css("padding-left","90px"):$(i).is("h6")&&$(a).css("padding-left","120px")})}}class CodeEditor{constructor(t,e){this.tray=t,this.editor=t.editor,this.element=e,this.breadcrumb=$(this.element).find("#code-box-parents")[0],this.editorWindow=$(this.element).find("div[contenteditable]")[0],$(this.element).find('[data-custom-action="ApplyCode"]').on("click",t=>this.ApplyCode(t))}Show(){$(this.element).addClass("d-flex").show().siblings("div").removeClass("d-flex").hide(),$(this.tray.controls).find('[data-target="#'+this.element.id+'"]').addClass("active").siblings("button").removeClass("active"),this.Update()}async Update(){if($(this.breadcrumb).empty(),$(this.editor.GetActiveElement()).is(this.editor.editorWindow))$(this.editorWindow).html(formatHTML(this.editor.GetActiveElement().innerHTML));else{let t,e=0;$(this.editor.GetActiveElement()).parentsUntil(this.editor.editorWindow).each((i,a)=>{t=$("<button></button>").addClass("btn").attr("data-parent-offset",e++).text($(a).prop("tagName")).prependTo(this.breadcrumb),t.on("click",t=>{this.editor.SetActiveElement($(this.editor.GetActiveElement()).parentsUntil(this.editor.editorWindow)[$(t.target).attr("data-parent-offset")]),this.Update()})}),t=$("<button></button>").addClass("btn").text("/").prependTo(this.breadcrumb),t.on("click",t=>{this.editor.SetActiveElement(this.editor.editorWindow),console.log(this.editor.GetActiveElement()),this.Update()}),$(this.editorWindow).html(formatHTML(this.editor.GetActiveElement().outerHTML))}}ApplyCode(t){try{let t=$(this.editorWindow).text();t=t.replace(/\s{2,}/g," "),console.log(t);let e=$(t);$(this.editor.GetActiveElement()).is(this.editor.editorWindow)?$(this.editor.GetActiveElement()).empty().append(e):($(this.editor.GetActiveElement()).replaceWith(e),this.editor.SetActiveElement(e[0])),this.editor.SetDirty({data:{editor:this.editor}}),this.editor.tray.codeEditor.Update()}catch(t){console.warn(t),Toast("Parsing Error","There was an error parsing the HTML.","bg-danger text-light")}}}class ContextMenu{constructor(t,e){this.tray=t,this.editor=t.editor,this.element=e,this.contents=$(this.element).find("#context-menu-contents")[0]}Show(){$(this.element).addClass("d-flex").show().siblings("div").removeClass("d-flex").hide(),$(this.tray.controls).find('[data-target="#'+this.element.id+'"]').addClass("active").siblings("button").removeClass("active"),this.Update()}async Update(){console.log("Doing context menu.");const t=this;if($(this.contents).empty(),$(this.editor.GetActiveElement()).is(this.editor.editorWindow))return void $("<div></div>").addClass("alert alert-dark").text("Please click on an element to adjust its settings.").appendTo(this.contents);let e=$(await this.Block(this.editor.GetActiveElement())).appendTo(this.contents),i=1;$(this.editor.GetActiveElement()).parentsUntil(this.editor.editorWindow).each(async(a,n)=>{let r=await t.Block(n,i++);r.append(e).appendTo(this.contents),e=r})}async Block(t,e=0){let i,a,n=$("<div></div>").addClass("context-menu-block"),r=$("<div></div>").addClass("context-menu-block-contents").appendTo(n),s=$(t).prop("tagName"),o="bi-fonts";switch($(t).prop("tagName")){case"OL":case"UL":$(t).hasClass("practice_quiz")?(s="Practice Quiz",o="bi-list"):(s="List",o="bi-list",r.append(this.ElementTagIconSelector(t,"Style",[{icon:"bi-list-ul",value:"UL"},{icon:"bi-list-ol",value:"OL"}])));break;case"BUTTON":r.append(this.ElementTextInput(t,"Text")),r.append(this.ElementClassIconSelector(t,"Size",[{icon:"bi-size-md",value:"fs-5"},{icon:"bi-size-lg",value:"fs-4"},{icon:"bi-size-xl",value:"fs-3"}],!0,!0)),r.append(await this.ElementColorChart(t,"color","Font")),r.append(await this.ElementColorChart(t,"background-color","Backgroun
1d")),r.append(await this.ElementColorChart(t,"border-color","Border"));break;case"BLOCKQUOTE":s="Blockquote",o="bi-quote",r.append(this.ElementTagIconSelector(t,"Type",[{icon:"bi-paragraph",value:"P"},{icon:"bi-quote",value:"BLOCKQUOTE"}])),r.append(this.ElementClassIconSelector(t,"Alignment",[{icon:"bi-text-left",value:"text-start"},{icon:"bi-text-center",value:"text-center"},{icon:"bi-text-right",value:"text-end"}],!0,!0)),r.append(this.ElementClassIconSelector(t,"Style",[{icon:"bi-type-bold",value:"fw-bold"},{icon:"bi-type-italic",value:"fst-italic"},{icon:"bi-type-underline",value:"text-decoration-underline"}],!1,!0)),r.append(this.ElementClassIconSelector(t,"Size",[{icon:"bi-size-md",value:"fs-5"},{icon:"bi-size-lg",value:"fs-4"},{icon:"bi-size-xl",value:"fs-3"}],!0,!0));break;case"P":$(t).hasClass("reference")?(s="Reference",o="bi-list-columns-reverse"):(s="Paragraph",o="bi-paragraph"),r.append(this.ElementTagSelector(t,"Type",[{label:"Paragraph",value:"P"},{label:"Blockquote",value:"BLOCKQUOTE"},{label:"Caption",value:"FIGCAPTION"},{label:"Heading",value:"H2"},{label:"List",value:"UL,LI"},{label:"Layer",value:"DIV"}])),r.append(this.ElementClassIconSelector(t,"Style",[{icon:"bi-type-bold",value:"fw-bold"},{icon:"bi-type-italic",value:"fst-italic"},{icon:"bi-type-underline",value:"text-decoration-underline"},{icon:"bi-list-columns-reverse",value:"reference"}],!1,!0)),r.append(this.ElementClassIconSelector(t,"Size",[{icon:"bi-size-sm",value:"fs-6"},{icon:"bi-size-md",value:"fs-5"},{icon:"bi-size-lg",value:"fs-4"},{icon:"bi-size-xl",value:"fs-3"}],!0,!0)),r.append(this.ElementClassIconSelector(t,"Alignment",[{icon:"bi-text-left",value:"text-start"},{icon:"bi-text-center",value:"text-center"},{icon:"bi-text-right",value:"text-end"}],!0,!0)),r.append(this.ElementAttrInput(t,"id","ID")),a=this.CollapsibleBox("Colors"),r.append(a),$(a).children("div").last().append(await this.ElementColorChart(t,"color","Font")),$(a).children("div").last().append(await this.ElementColorChart(t,"background-color","Background"));break;case"FIGCAPTION":s="Caption",r.append(this.ElementClassIconSelector(t,"Alignment",[{icon:"bi-text-left",value:"text-start"},{icon:"bi-text-center",value:"text-center"},{icon:"bi-text-right",value:"text-end"}],!0,!0));break;case"DL":s="Definition List";break;case"TABLE":r.append(this.ElementClassIconSelector(t,null,[{icon:"bi-border-outer",value:"border"},{icon:"bi-border-top",value:"border-top"},{icon:"bi-border-bottom",value:"border-bottom"},{icon:"bi-border-left",value:"border-start"},{icon:"bi-border-right",value:"border-end"}])),r.append(await this.ElementAttrInput(t,"class","Class","The Class attribute for the element. Classes are used for formatting with CSS, and they should use underscores (_) or dashes (-) instead of spaces."));break;case"TD":case"TH":r.append(this.ElementTagSelector(t,"Type",[{label:"Cell",value:"TD"},{label:"Heading",value:"TH"}])),r.append(this.ElementClassIconSelector(t,null,[{icon:"bi-border-outer",value:"border"},{icon:"bi-border-top",value:"border-top"},{icon:"bi-border-bottom",value:"border-bottom"},{icon:"bi-border-left",value:"border-start"},{icon:"bi-border-right",value:"border-end"}]));let e=$("<div></div>").addClass("btn-group w-100 my-1 mt-2").appendTo(r)[0],n=$("<button></button>").addClass("btn btn-dark bi-plus-lg icon-text-link text-start").text("Insert Row").appendTo(e)[0];$(n).on("click",{element:t},t=>{this.editor.history.SaveState();let e=$(t.data.element).parent("tr")[0],i=$(e).children("td,th").length,a=$("<tr></tr>")[0],n=0;for(;n++<i;)$("<td><br /></td>").appendTo(a);$(a).insertAfter(e),this.editor.SetActiveElement($(a).find("td").last()),this.editor.PulseElement(this.editor.GetActiveElement()),this.Update()});let l=$("<button></button>").addClass("btn btn-dark bi-trash icon-text-link text-start").text("Delete Row").appendTo(e)[0];$(l).on("click",{element:t},t=>{this.editor.history.SaveState();let e=$(t.data.element).parent("tr")[0];this.editor.SetActiveElement($(t.data.element).parents("table").eq(0).find("td").first()),$(e).remove(),this.editor.PulseElement(this.editor.GetActiveElement()),this.Update()});let d=$("<div></div>").addClass("btn-group w-100 my-1").appendTo(r)[0],h=$("<button></button>").addClass("btn btn-dark bi-plus-lg icon-text-link text-start").text("Insert Column").appendTo(d)[0];$(h).on("click",{element:t},t=>{this.editor.history.SaveState();let e=$(t.data.element).parents("table")[0],i=$(t.data.element).prevAll("td,th").length;console.log(i),$(e).find("tr").each((t,e)=>{$("<td>[data]</td>").insertAfter($(e).find("td,th")[i])}),this.editor.SetActiveElement($(e).find("tr").first().find("td,th").last()),this.editor.PulseElement(this.editor.GetActiveElement()),this.Update()});let c=$("<button></button>").addClass("btn btn-dark bi-trash icon-text-link text-start").text("Delete Column").appendTo(d)[0];$(c).on("click",{element:t},t=>{this.editor.history.SaveState();let e=$(t.data.element).parents("table")[0],i=$(t.data.element).prevAll("td,th").length;$(e).find("tr").each((t,e)=>{$(e).find("td,th").eq(i).remove()}),this.editor.SetActiveElement($(e).find("tr").first().find("td,th").first()),this.editor.PulseElement(this.editor.GetActiveElement()),this.Update()});break;case"DT":s="Term";break;case"DD":s="Definition";break;case"FIGURE":s="Figure",o="bi-bounding-box";break;case"IMG":s="Image",o="bi-image";let u=$("<button>").addClass("btn btn-success bi-image icon-text-link fs-4 mt-3 mb-4 w-100").text("Browse / Upload");if($(u).on("click",async t=>{let e=await GetModal("modal-image");e.Toggle();let i=[],a=this.editor.entity;
1"chapter"==a.type&&(a=await GetBook(a.book_id)),i=await GetEntityImages(a);let n=$(e.element).find("#modal-image-contents");n.empty();for(let t of i){let i=$("<button></button>").addClass("col btn").appendTo(n);$("<img>").attr("src",t).addClass("img-fluid").appendTo(i);i.on("click",{modal:e},t=>{let i=HasAttr($(t.target),"src")?$(t.target).attr("src"):$(t.target).find("[src]").first().attr("src");$(this.editor.GetActiveElement()).attr("src",i),this.editor.SetDirty(),this.Update(),e.Toggle()})}$(e.element).find("input#image-upload-field").off().on("input",async t=>{let i=await UploadImage("/"+a.type+"/"+a.id+"/saveImage",t.target.files[0]);$(this.editor.GetActiveElement()).attr("src",i.public_path),this.editor.SetDirty(),this.Update(),e.Toggle()})}),r.append(u),r.append(this.ElementAttrInput(t,"src","URL")),$(t).attr("src").startsWith("data:image/png;base64,")){console.log("Found base64 image"),$("<button></button>").addClass("btn btn-primary").text("Resave as File").appendTo(r).on("click",{element:t,book_id:this.tray.editor.entity.book_id},async t=>{await ConvertBase64ImageStringToFile(t.data.element,t.data.book_id),this.Update()})}r.append(this.ElementAttrInput(t,"alt","Alt Text")),r.append(this.ElementClassIconSelector(t,"Size",[{icon:"bi-size-sm",value:"img-sm"},{icon:"bi-size-md",value:"img-md"},{icon:"bi-size-lg",value:"img-lg"},{icon:"bi-arrows",value:"img-fluid"}],!0,!0)),r.append(this.ElementClassIconSelector(t,"Placement",[{icon:"bi-image-left",value:"img-left"},{icon:"bi-image-center",value:"img-center"},{icon:"bi-image-right",value:"img-right"}],!0,!0)),r.append(this.ElementClassIconSelector(t,"Margins",[{icon:"bi-size-xs",value:"mx-1"},{icon:"bi-size-sm",value:"mx-2"},{icon:"bi-size-md",value:"mx-3"},{icon:"bi-size-lg",value:"mx-4"}],!0,!0)),r.append(this.ElementClassIconSelector(t,"Style",[{icon:"bi-file-image",value:"img-thumbnail"},{icon:"bi-shadows",value:"shadow"},{icon:"bi-border-width",value:"border"}],!1,!0));break;case"DIV":if($(t).attr("data-template"))switch($(t).attr("data-template")){case"youtube":s="YouTube Video",i=this.ElementAttrInput(t,"data-youtube-id","YouTube ID"),r.append(i),$(i).find("input").off("input").on("input",{element:t,attr:"data-youtube-id"},t=>{$(t.target).val().startsWith("http")&&($(t.target).val(ExtractYouTubeID($(t.target).val())),Toast("Input Changed","The input has been changed from a URL to an ID.","bg-warning text-dark")),$(t.data.element).attr(t.data.attr,$(t.target).val()),$("#youtube-thumbnail").empty().append($("<img>").addClass("img-fluid rounded").attr("src","https://img.youtube.com/vi/"+$(t.target).val()+"/0.jpg")),this.editor.SetDirty(),this.editor.history.SaveState()}),$("<div></div>").attr("id","youtube-thumbnail").appendTo(r).append($("<img>").addClass("img-fluid rounded").attr("src","https://img.youtube.com/vi/"+$(t).attr("data-youtube-id")+"/0.jpg"));break;case"author-bio":this.ElementAttrInput(t,"data-entity-id","Author ID").appendTo(r);break;case"google_doc":s="Google Doc",i=$(this.ElementAttrInput(t,"data-gdoc-url","Google Doc URL")).find("input")[0],r.append(i),$("<div></div>").addClass("alert alert-dark").text('Please ensure that the Google Doc is publicly shared to "Anyone with the link".').appendTo(r);$("<p></p>").text("This Google Doc will appear in an iFrame, or you can import it as HTML instead.").appendTo(r);let e=$("<button></button>").text("Import as HTML").addClass("btn btn-outline-dark").appendTo(r);$(e).on("click",{input:i,target:t},async t=>{try{$(t.target).off().attr("disabled",!0),console.log("Importing Google Doc.");let e=$(t.data.input).val(),i=ExtractGoogleDocID(e),a=CleanGoogleDocHTML(await FetchGoogleDocAsHtml(i)),n=$(t.data.target).replaceWith(a);this.editor.SetActiveElement(n),this.editor.tray.Update(),this.editor.SetDirty(),this.editor.history.SaveState(),Toast("GDoc Imported","The Google Doc was successfully imported.","bg-success")}catch(t){console.error(t),Toast("Import Error","There was an error importing the Google Doc.","bg-danger")}});break;case"iframe":s="Generic IFrame",r.append(this.ElementAttrInput(t,"data-iframe-src","Website to Embed"));break;default:s="Custom Element"}else"equation"==$(t).attr("data-type")?(s="Equation",0==$(t).find("div,math").length&&r.append(this.ElementTextInput(t,"LaTeX Equation"))):$(t).hasClass("callout")?(s="Callout Box",o="bi-card-heading",a=this.CollapsibleBox("Colors"),r.append(a),$(a).children("div").last().append(await this.ElementColorChart(t,"color","Font")),$(a).children("div").last().append(await this.ElementColorChart(t,"background-color","Backgroun
1d"))):$(t).hasClass("accordion-body")?r.append(await this.ElementColorChart(t,"border-color","Border")):(r.append(this.ElementTagSelector(t,"Type",[{label:"Paragraph",value:"P"},{label:"Heading",value:"H2"},{label:"Layer",value:"DIV"}])),$("<div></div>").addClass("alert alert-warning small").text("This layer may not be serving a good purpose. Consider unwrapping it or converting it to a paragraph.").appendTo(r));break;case"INPUT":$(t).is('[data-role="fib"]')&&(s="Fill-in-the-Blank");break;case"STRONG":s="Bold",a=this.CollapsibleBox("Colors"),r.append(a),$(a).children("div").last().append(await this.ElementColorChart(t,"color","Font")),$(a).children("div").last().append(await this.ElementColorChart(t,"background-color","Background"));let p=$("<button></button>").text("Convert to Glossary Term").addClass("btn btn-outline-dark").appendTo(r);$(p).on("click",{target:t,editor:this.editor},async t=>{let e=$("<span></span>").attr("data-glossary-term-id",0).text($(t.data.target).text());$(t.data.target).replaceWith(e),t.data.editor.SetActiveElement(e),t.data.editor.tray.Update()});break;case"EM":s="Italic",a=this.CollapsibleBox("Colors"),r.append(a),$(a).children("div").last().append(await this.ElementColorChart(t,"color","Font")),$(a).children("div").last().append(await this.ElementColorChart(t,"background-color","Background"));break;case"H2":case"H3":case"H4":case"H5":case"H6":s="Heading",r.append(this.ElementTagSelector(t,"Level",[{label:"Level 2",value:"H2"},{label:"Level 3",value:"H3"},{label:"Level 4",value:"H4"},{label:"Level 5",value:"H5"},{label:"Level 6",value:"H6"},{label:"Paragraph",value:"P"}])),r.append(this.ElementClassIconSelector(t,"Alignment",[{icon:"bi-text-left",value:"text-start"},{icon:"bi-text-center",value:"text-center"},{icon:"bi-text-right",value:"text-end"}],!0,!0)),r.append(this.ElementClassIconSelector(t,"Padding",[{icon:"bi-size-xs",value:"p-1"},{icon:"bi-size-sm",value:"p-2"},{icon:"bi-size-md",value:"p-3"},{icon:"bi-size-lg",value:"p-4"}],!0,!0)),a=this.CollapsibleBox("Colors"),r.append(a),$(a).children("div").last().append(await this.ElementColorChart(t,"color","Font")),$(a).children("div").last().append(await this.ElementColorChart(t,"background-color","Background")),r.append(await this.ElementAttrInput(t,"id","ID","The ID for the element. IDs should be unique and alphanumeric, and they should use underscores (_) or dashes (-) instead of spaces.")),r.append(await this.ElementAttrInput(t,"class","Class","The Class attribute for the element. Classes are used for formatting with CSS, and they should use underscores (_) or dashes (-) instead of spaces.")),r.append(await this.ElementAttrInput(t,"style","Style","The Style attribute defines custom CSS for the element."));break;case"LI":if($(t).hasClass("pq-active"))r.append(this.ElementAttrSelector(t,"data-etb-pq-value","Key",[{label:"Correct",value:1},{label:"Incorrect",value:0}]));else{s="Item";let e=$("<div></div>").addClass("input-group d-flex flex-row my-1").appendTo(r);$("<span></span>").text("Indentation").addClass("input-group-text").appendTo(e),$("<button></button>").addClass("bi-unindent btn flex-grow-1").appendTo(e).on("click",e=>{this.editor.IndentList(t,-1),this.editor.SetDirty(),this.editor.tray.Update()}),$("<button></button>").addClass("bi-indent btn flex-grow-1").appendTo(e).on("click",e=>{this.editor.IndentList(t,1),this.editor.SetDirty(),this.editor.tray.Update()}),e=$("<div></div>").addClass("input-group d-flex flex-row my-1").appendTo(r),$("<span></span>").text("Order").addClass("input-group-text").appendTo(e),$("<button></button>").addClass("bi-arrow-up btn flex-grow-1").appendTo(e).on("click",e=>{this.editor.MoveUp(t),this.editor.SetDirty(),this.editor.tray.Update()}),$("<button></button>").addClass("bi-arrow-down btn flex-grow-1").appendTo(e).on("click",e=>{this.editor.MoveDown(t),this.editor.SetDirty(),this.editor.tray.Update()})}break;case"A":s="Link",o="bi-link-45deg",r.append(this.ElementAttrInput(t,"href","URL","The location where you would like the link to go. This can either be a full URL or a hashtag (#) followed by the ID of the element (for an anchor link).")),r.append(this.ElementAttrSelector(t,"target","Target",[{label:"Same Window / Tab",value:"_self"},{label:"New Window / Tab",value:"_blank"}])),r.append(this.ElementTextInput(t,"Text")),r.append(await this.ElementAttrInput(t,"class","Class","The Class attribute for the element. Classes are used for formatting with CSS, and they should use underscores (_) or dashes (-) instead of space
1s."));break;case"SPAN":if($(t).is("[data-glossary-term-id]")){o="bi-eyeglasses";$(t).attr("data-glossary-term-id");s="Glossary Term",r.append(this.ElementTextInput(t,"Text"));let e=await GetBookGlossaryTerms(current_book),i=MapOptions(e,"term_id","word");i.unshift({label:"Select an existing glossary term",value:0});let a=this.ElementAttrSelector(t,"data-glossary-term-id","Term",i);r.append(a);let n=$("<div></div>").addClass("d-flex flex-row").appendTo(r),l=$("<button></button>").addClass("btn btn-sm btn-outline-dark bi-arrow-clockwise icon-text-link rounded-end-0").text("Refresh the Glossary").appendTo(n);$("<a></a>").addClass("btn btn-sm btn-outline-dark text-light bi-pencil icon-text-link rounded-start-0").text("Edit the Glossary").attr("href","/"+current_book.short_name+"/glossary").attr("target","_blank").appendTo(n);$(l).on("click",async t=>{await GetBookGlossaryTerms(current_book,!0),this.Update()})}else if($(t).is("[data-index-term]")){o="bi-search",s="Related Content Link",r.append(this.ElementTextInput(t,"Visible Text")),r.append(this.ElementAttrInput(t,"data-index-term","Search Term")),$("<button></button>").addClass("btn btn-primary").text("Preview").appendTo(r).on("click",{element:t},t=>{ShowIndexModal(this.tray.editor.entity,t.data.element)})}else{$("<div></div>").addClass("alert alert-warning small").text("A span is normally bloat code that is inserted by programs like MS Word. Unless you need the span, you should unwrap it.").appendTo(r);let e=$("<div></div>").addClass("input-group").appendTo(r);$("<button></button>").addClass("btn btn-secondary").text("Unwrap").appendTo(e).on("click",{element:t,editor:this.editor},async t=>{let e=$(t.data.element).parent()[0];console.log(e),t.data.editor.Unwrap(t.data.element),t.data.editor.SetActiveElement(e),t.data.editor.tray.Update()}),$("<button></button>").addClass("btn btn-warning text-dark").text("Unwrap All").appendTo(e).on("click",{element:t,editor:this.editor},async t=>{let e=$(t.data.element).parent()[0];t.data.editor.RemoveSpans(t.data.editor.editorWindow),t.data.editor.SetActiveElement(e),t.data.editor.tray.Update()}),r.append(this.ElementTagSelector(t,"Tag Type",[{label:"Non-Semantic Span",value:"SPAN"},{label:"Bold",value:"STRONG"},{label:"Italic",value:"EM"}])),r.append(await this.ElementColorChart(t,"color","Font"))}}let l=$(await RenderTemplate("editor-tray-contextmenu-heading",{label:s,icon:o,parentOffset:e}));return l.prependTo(n),$(l).find("[data-tray-action]").off().on("click",t=>this.tray.TrayAction(t)),RegisterTooltips(r),n}ElementTagIconSelector(t,e,i){let a=$("<div></div>").addClass("input-group d-flex flex-row my-1");$("<span></span>").addClass("input-group-text").text(e).appendTo(a);for(let e of i){let i=$("<button></button>").attr("data-value",e.value).addClass("btn flex-grow-1").addClass(e.icon).appendTo(a);e.value==$(t).prop("tagName")&&i.addClass("active"),i.on("click",{element:t},t=>{this.editor.SetActiveElement(this.editor.ChangeTag(t.data.element,$(t.target).attr("data-value"))),this.editor.tray.Update(),this.editor.SetDirty(),this.editor.history.SaveState()})}return a}ElementTagSelector(t,e,i){let a=$("<div></div>").addClass("input-group my-1");$("<span></span>").addClass("input-group-text").text(e).appendTo(a);let n=$("<select></select>").addClass("form-select").appendTo(a);for(let e of i){let i=$("<option></option>").attr("value",e.value).text(e.label).appendTo(n);e.value==$(t).prop("tagName")&&i.attr("selected","true")}return n.on("change",{element:t},e=>{let i=$(e.target).val();if(i.includes(",")){let e=i.split(",");for(let a in e)a<e.length-1?$(t).wrap("<"+e[a]+"></"+e[a]+">"):i=e[a]}this.editor.SetActiveElement(this.editor.ChangeTag(e.data.element,i)),this.editor.tray.Update(),this.editor.SetDirty(),this.editor.history.SaveState()}),a}ElementAttrSelector(t,e,i,a){let n=$("<div></div>");$("<label></label>").text(i).appendTo(n);let r=$("<select></select>").addClass("form-select mb-2").val($(t).attr(e)).appendTo(n);for(let i of a){let a=$("<option></option>").attr("value",i.value).text(i.label).appendTo(r);i.value==$(t).attr(e)&&a.attr("selected","true")}return r.on("change",{element:t,attr:e},t=>{$(t.data.element).attr(t.data.attr,$(t.target).val()),this.editor.SetDirty(),this.editor.history.SaveState()}),n}ElementClassIconSelector(t,e,i,a=!1,n=!1){let r=$("<div></div>").addClass("input-group d-flex flex-row my-1");null!==e&&$("<span></span>").addClass("input-group-text").text(e).appendTo(r);for(let e of i){let n=$("<button></button>").attr("data-value",e.value).addClass("btn flex-grow-1").addClass(e.icon).appendTo(r);$(t).hasClass(e.value)&&n.addClass("active"),n.on("click",{options:i,element:t},t=>{if(a)for(let e of t.data.options)$(t.data.element).removeClass(e.value);$(t.data.element).toggleClass($(t.target).attr("data-value")),this.editor.tray.Update(),this.editor.SetDirty(),this.editor.history.SaveState()})}if(n){$("<button></button>").addClass("btn flex-grow-1 bi-x-lg").appendTo(r).on("click",{options:i,element:t},t=>{for(let e of t.data.options)$(t.data.element).removeClass(e.value);this.editor.tray.Update(),this.editor.SetDirty(),this.editor.history.SaveState()})}return r}ElementAttrInput(t,e,i,a=null){let n=$("<div></div>"),r=$("<label></label>").text(i).appendTo(n);if(null!==a){$("<i></i>").addClass("bi-question-circle ms-2").attr("data-bs-title",a).appendTo(r)}return $("<input>").addClass("form-control mb-2").val($(t).attr(e)).appendTo(n).on("input",{element:t,attr:e},t=>{$(t.data.element).attr(t.data.attr,$(t.target).val()),this.editor.SetDirty(),this.editor.history.SaveState()}),n}ElementTextInput(t,e){let i=$("<div></div>");return $("<label></label>").text(e).appendTo(i),$("<input>").addClass("form-control mb-2").val($(t).text()).appendTo(i).on("input",{element:t},t=>{$(t.data.element).text($(t.target).val()),this.editor.SetDirty(),this.editor.history.SaveState()}),i}
1CollapsibleBox(t,e){let i=UniqueID(),a=$("<div></div>"),n=$("<button></button>").text(t).addClass("btn w-100 text-start bi-chevron-right icon-text-link").appendTo(a).attr("data-bs-toggle","collapse").attr("data-bs-target","#"+i),r=$("<div></div>").addClass("collapse").attr("id",i).appendTo(a);return n.off("click").on("click",t=>{$(t.target).toggleClass("bi-chevron-right").toggleClass("bi-chevron-down")}),r.append(e),a[0]}async ElementColorChart(t,e,i){let a=$("<div></div>").addClass("my-2"),n=$("<div></div>").addClass("d-flex py-1 align-items-center").appendTo(a);$("<label></label>").addClass("flex-grow-1").text(i).appendTo(n);$("<div></div>").addClass("me-2").css("height","1em").css("width","1em").css("background-color",$(t).css(e)).appendTo(n);let r=$("<input>").addClass("text-center").attr("data-bs-theme","dark").css("font-size",".6em").val($(t).css(e)).appendTo(n),s=$("<button></button>").addClass("btn btn-sm py-0 bi-x").appendTo(n),o=$(await RenderTemplate("editor-color-chart"));return o.appendTo(a),o.find(".js-color").on("click",{element:t,field:e},t=>{$(t.data.element).css(t.data.field,$(t.target).attr("data-hex")),this.editor.SetDirty(),this.editor.history.SaveState(),this.Update()}),s.on("click",{element:t,field:e},t=>{$(t.data.element).css(t.data.field,""),this.editor.SetDirty(),this.editor.history.SaveState(),this.Update()}),r.on("input",{element:t,field:e},t=>{$(t.data.element).css(t.data.field,$(r).val()),this.editor.SetDirty(),this.editor.history.SaveState(),this.Update()}),a}}class Ribbon{constructor(t){this.editor=t,this.Initialize()}async Initialize(){0==$("#editor-ribbon").length&&$(await GetTemplate("editor-ribbon")).insertBefore(this.editor.editorWindow),this.element=$("#editor-ribbon")[0],RegisterTooltips(this.element),$(this.element).find("[data-ribbon-action]").on("click",async t=>{console.log("Trying "+$(t.target).attr("data-ribbon-action"));try{let e=$(t.target).attr("data-ribbon-action");switch(e){case"Undo":case"Redo":this.editor.SetCursorPosition(await this.editor.history[e](this.editor.GetActiveElement()));break;default:this.editor.SetCursorPosition(await this.editor[e](this.editor.GetActiveElement()))}"Save"==e||"ToggleAutoSave"==e?this.editor.tray.Update():(this.editor.tray.contextMenu.Show(),this.editor.SetDirty())}catch(t){console.error(t)}})}Destroy(){$(this.element).remove()}}class CoverUploader{constructor(t,e){this.preview=t,this.entity=e,this.Initialize()}async Initialize(){this.input=$("<input>").attr("type","file").attr("accept","image/*").attr("id","cover-uploader").addClass("d-none").insertAfter(this.preview)[0],this.label=$("<label></label>").text("Upload Cover").addClass("btn btn-primary fs-4 bi-upload icon-text-link w-100").attr("for","cover-uploader").insertAfter(this.input),$(this.input).on("input",async t=>{let e=await UploadImage("/book/"+this.entity.id+"/saveCover",this.input.files[0]);return e.public_path=window.location.origin+"/images/book_cover_images/"+e.filename,$(this.preview).attr("src",e.public_path),e.public_path})}}class AuthorImageUploader{constructor(t,e){this.preview=t,this.entity=e,this.Initialize()}async Initialize(){this.input=$("<input>").attr("type","file").attr("accept","image/*").attr("id","image-uploader").addClass("d-none").insertAfter(this.preview)[0],this.label=$("<label></label>").text("Upload Image").addClass("btn btn-primary fs-4 bi-upload icon-text-link w-100 mb-5").attr("for","image-uploader").insertAfter(this.input),$(this.input).on("input",async t=>{let e=await UploadImage("/author/"+this.entity.id+"/saveImage",this.input.files[0]);return $(this.preview).attr("src",e.public_path),GetAuthor(this.entity.id,!0),e.public_path})}}async function ConvertBase64ImageStringToFile(t,e){try{const i=UniqueID("img")+".png",a=DataURLtoFile($(t).attr("src"),i);let n=await UploadImage("/book/"+e+"/saveImage",a);return $(t).attr("src",n.public_path),!0}catch(t){return console.error(t),!1}}class TOCEditor{constructor(t,e){this.editorWindow=t,this.book=e,this.dragging=null,this.tocStartX=0,this.Initialize(),editors.push(this)}async Initialize(){$(this.editorWindow).empty(),this.ribbon=$(await RenderTemplate("book-toc-ribbon",this.book))[0],$(this.ribbon).appendTo(this.editorWindow),$(this.ribbon).find("[data-ribbon-action]").on("click",async t=>{try{return await this[$(t.target).attr("data-ribbon-action")]()}catch(t){return console.error(t),t}});for(let t of this.book.chapter_links){t.book_short_name=this.book.short_name;let e=$(await RenderTemplate("book-toc-row-edit",t));e.css({"margin-left":20*t.chapter_level+"px"}).attr("data-children",t.children.join(",")).appendTo($("#book-nav-links")),$(this.editorWindow).append(e),$(e).find('[data-role="grip"]').off().on("mousedown",t=>{this.dragging=t.target,this.tocStartX=t.pageX}),$(e).find("input").off("change").on("change",t=>{console.log("Saving"),SaveSettingFromElement(t.target)})}$(this.editorWindow).sortable({handle:'grip[data-role="grip"]',items:"div[data-entity-id]",axis:"y",scrollSpeed:6,opacity:.8,start:t=>{$(this.editorWindow).on("mousemove",t=>this.Dragging(t))},stop:t=>{this.dragging=null,$(this.editorWindow).find("[data-chapter-level-target]").each((t,e)=>{$(e).attr("data-chapter-level",$(e).attr("data-chapter-level-target")).removeAttr("data-chapter-level-target")}),$(this.editorWindow).off("mousemove"),this.SetDirty()},update:t=>{}})}async Save(){$(this.editorWindow).sortable("disable");try{let t=[];$(this.editorWindow).children("div").each((e,i)=>{if(!HasAttr(i,"data-entity-id"))return;let a={};a.id=$(i).attr("data-entity-id"),a.chapter_level=$(i).attr("data-chapter-level"),t.pu
1sh(a)}),await SortBookChapters(t)&&(this.SetClean(),Toast("Chapter Order Saved","The chapter order has been saved.","bg-success text-light"))}finally{$(this.editorWindow).sortable("enable")}}SetClean(){this.dirty&&(console.log("Setting clean"),this.dirty=!1,void 0!==this.ribbon&&$(this.ribbon).find("#save-status").addClass("bi-check-lg").removeClass("bi-floppy2").removeClass("btn-danger").text("Saved"))}SetDirty(){this.dirty||(console.log("Setting dirty"),this.dirty=!0,void 0!==this.ribbon&&$(this.ribbon).find("#save-status").removeClass("bi-check-lg").addClass("bi-floppy2").addClass("btn-danger").text("Unsaved"))}Destroy(){$(this.editorWindow).sortable("destroy")}Dragging(t){if(null!==this.dragging&&$(this.dragging).hasClass("bi-arrows-move")){let e=t.pageX-this.tocStartX,i=parseInt($(this.dragging).parent().attr("data-chapter-level"));i+=Math.round(e/20),i<0&&(i=0),i>4&&(i=4),$(this.dragging).parent().css({"margin-left":20*i+"px"}).attr("data-chapter-level-target",i)}}}function ToggleRangeElement(t,e,i=null,a=null,n={}){if($(t).is(e)){console.log(t);let e=$(t).parent()[0];return $(t).replaceWith($(t).html()),e.normalize(),e}if(IsRangeSelected()){let t=window.getSelection().getRangeAt(0);if(t.startContainer===t.endContainer){let i=t.extractContents(),r=document.createElement(e);r.appendChild(i);for(let t in n)$(r).attr(t,n[t]);return t.insertNode(r),null!==a&&$(r).addClass(a),r}Toast("Not Allowed","Running that function on multiple elements is not allowed. Please make sure that your highlighted selection is limited to a single element.","bg-warning text-dark")}else null!==i&&$(t).toggleClass(i);return t}function Align(t,e=null){null!==t&&($(t).removeClass("text-start").removeClass("text-end").removeClass("text-center"),null!==e&&""!=e&&$(t).addClass("text-"+e))}function SelectParent(t=activeElement){if(null===t)return;let e=$(t).parent();null==e||$(e).is("[contenteditable]")?Toast("Missing Parent","There was no available parent to select.","bg-warning text-dark","bi-x-lg"):(PulseElement(e),SetCursorPosition(e))}function SelectChild(t=activeElement){if(null===t)return;let e=$(t).children().first();null!==e&&e.length>0&&(PulseElement(e),SetCursorPosition(e))}function SelectSibling(t=1,e=activeElement){if(null===e)return;let i=null;i=1==t?$(e).next():$(e).prev(),null!=i&&0!=i.length||(i=e),PulseElement(i),SetCursorPosition(i)}function ChangeStyle(t=null,e=null,i={},a=!0,n=activeElement){if(null===n)return;let r=n;$(n).each(function(){let a=this;null!==t&&(a=ChangeTag(t,$(n))),null!==e&&$(a).attr("class",e);for(let t in i)$(a).attr(t,i[t]);r=a}),PulseElement(r),SetCursorPosition(r)}function IncrementHeading(t=1,e=activeElement){if(null===e)return;let i=$(e).prop("tagName");i.startsWith("H")||(i=-1==t?"H2":"H6");var a=Clamp(parseInt(i.substring(1))+t,2,6);e=ChangeTag("h"+a),PulseElement(e),SetCursorPosition(e)}function ExpandList(t=activeElement){list=$(t).closest("ul,ol"),0!=list.length&&(ChangeTag("li",$(list).next()),Expand(list))}function ContractList(t=activeElement){list=$(t).closest("ul,ol"),0!=list.length&&(ChangeTag("p",$(list).children().last()),Contract(list))}function ToggleList(t="ul",e=activeElement){if(null!==e)if($(e).is("li")){let i=$(e).parents("ol,ul").first();$(e).parents("ol,ul").length>0?$(i).is(t)?($(i).children("li").each(function(){ChangeTag("p",this)}),e=$($(i).html()),$(i).replaceWith(e)):(i=ChangeTag(t,i),e=$(i).children("li").first()):$(e).wrap("<"+t+"></"+t+">"),SetCursorPosition(e)}else e=ChangeTag("li",e),$(e).wrap("<"+t+"></"+t+">"),SetCursorPosition(e)}function IsRangeSelected(){const t=window.getSelection();return t&&t.rangeCount>0&&!t.isCollapsed}function ReplaceRangeWithHTML(t){if(!IsRangeSelected())return null;let e=window.getSelection().getRangeAt(0);if(e.startContainer===e.endContainer){let i=e.extractContents(),a=document.createElement(t);return a.appendChild(i),e.insertNode(a),a}return Toast("Not Allowed","Running that function on multiple elements is not allowed. Please make sure that your highlighted selection is limited to a single element.","bg-warning text-dark"),null}function UnwrapAllSpans(){$('main [data-field="text"]').find(":not(span)").find("span").each(function(){let t=$(this).html();$(this).replaceWith(t)})}function UnwrapPsInLIs(){$('main [data-field="text"]').find("li").children("p").each(function(){let t=$(this).html();$(this).parent().html(t)})}function UnwrapPsInTDs(){$('main [data-field="text"]').find("td,th").children("p").each(function(){let t=$(this).html();$(this).parent().html(t)})}function UnwrapPsInBlockquotes(){$('main [data-field="text"]').find("blockquote").children("p").each(function(){let t=$(this).html();$(this).parent().html(t)})}function DeleteEmptiesWithin(t="*"){$('main [data-field="text"]').find(t).each(function(){($(this).is(":empty")||""==$(this).text().trim())&&($(this).is("img, iframe, figure")||$(this).remove())})}function RemoveAllStyles(){$('main [data-field="text"]').find("*").removeAttr("style").removeAttr("data-mce-style").removeAttr("data-mce-src").removeAttr("data-mce-href")}function ChangeColor(t=null,e=activeElement){$(e).removeClass(["text-dark","text-light","text-primary","text-secondary","text-success","text-info","text-warning","text-danger","text-white","text-rainbow","bg-dark","bg-light","bg-primary","bg-secondary","bg-success","bg-info","bg-warning","bg-danger","bg-rainbow","bg-white","bg-dark-subtle","bg-light-subtle","bg-primary-subtle","bg-secondary-subtle","bg-success-subtle","bg-info-subtle","bg-warning-subtle","bg-danger-subtle"]),null!=t&&$(e).addClass(t)}function IncrementMargin(t=1,e=activeElement){let i=getClassInteger(e,"m");$(e).removeClass(["m-1","m-2","m-3","m-4","m-5"]),null==i&&(i=0),0!==t&&(i=Clamp(i+t,0,5),i>0&&$(e).addClass("m-"+i))}function IncrementPadding(t=1,e=activeElement){let i=getClassInteger(e,"p");$(e).removeClass(["p-1","p-2","p-3","p-4","p-5"]),null==i&&(i=0),0!==t&&(i=Clamp(i+t,0,5),i>0&&$(e).addClass("p-"+i))}function IncrementRounded(t=activeElement,e=1){let i="rounded",a=getClassInteger(t,i);$(t).removeClass(["rounded-1","rounded-2","rounded-3","rounded-4","rounded-5"]),null==a&&(a=0),0!==e&&(a=Clamp(a+e,0,5),a>0&&$(t).addClass(i+"-"+a))}function SizeImage(t,e,i=activeElement){if(!$(i).is("figure"))return;let a=$(i).children("img").first();if(null===a)return;let n=$(a).hasClass("img-thumbnail"),r=$(a).hasClass("shadow");$(i).attr("class",t),$(a).attr("class",e),n&&$(a).addClass("img-thumbnail"),r&&$(a).addClass("shadow")}function Insert(t,e=null,i=!1,a=activeElement){s=window.getSelection().getRangeAt(0);let n=$(a),r=$(t);if(i){if(null==s)return;if(n.prop("tagName")!==r.prop("tagName")){let e=document.createRange();e.setStart($(n)[0],window.getSelection().startOffset);let i=e.createContextualFragment(t);s.insertNode(i)}else{console.log("Splitting the parent");var s=window.getSelection().getRangeAt(0),o=s.startOffset,l=$(n).html(),d=l.substring(0,o),h=l.substring(o);$(n).html(d);var c=$(n).clone();$(c).html(h),$(n).after(c),$(n).after(r)}}else 0!=$(n).html().length||$(n).is('main [data-field="text"]')?$(n).after(r):(console.log("Replacing parent"),$(n).replaceWith(r));$(r).attr("id",UniqueID($(r).prop("tagName"))),HideMenu("#range-menu"),SelectElement(r[0]),SetCursorPosition(r[0]),null!==e&&("#code-modal"==e?ShowSourceCode(null,"#"+$(r).attr("id")):$(e).modal("show"))}function ParentStyle(t=null,e=null,i={},a=activeElement){ChangeStyle(t,e,i,!1,$(a).parent())}function UpdateFootnote(){if(null===GetSelected())return;let t=$(GetSelected()).children("a").first().attr("href");if(console.log(t),void 0===t||"#"!==t.substring(0,1))return;let e=$(t);if(0==e.length){console.log("No target found. Creating one.");let e=$('<div class="footnote" id="'+t.substring(1)+'"><a href="#'+$(GetSelected()).attr("id")+'">#</a><p>
1New footnote here</p></div>'),i=$("#footnotes");0==i.length&&$('main [data-field="text"]').append('<div id="footnotes"><h2>Footnotes</h2></div>'),i=$("#footnotes"),i.append(e)}e=$(t),console.log(e),e.children("p").first().html($("#footnote-text").val()),etbUndo.saveState()}function UpdateFootnoteNumbers(){let t=$('main [data-field="text"]').find("sup a"),e=1,i=$("#footnotes");0==i.length&&$('main [data-field="text"]').append('<div id="footnotes"><h2>Footnotes</h2></div>'),i=$("#footnotes"),t.each(function(){let t=$(this).attr("href");void 0!==t&&"#"===t.substring(0,1)||next;let i=$(t);if(i.length>0){$(this).text(e);let t=$(i).children("a").first();t.length>0&&t.text(e),$("#footnotes").append(i),e++}}),1==e&&i.remove(),etbUndo.saveState()}function IsEditorDirty(){return $("[data-dirty]").length>0}function SaveDirty(){$("#toc[data-dirty]").each(function(){SaveTOC(this)}),$("[data-dirty][data-field]").each(async function(){await SaveSettingFromElement(this)?(SetClean(this),Toast("Saved","The content was saved.","bg-success text-light","bi-floppy2")):Toast("Error Saving","There was an error saving.","bg-danger text-light","bi-floppy2")})}async function SaveSettingFromElement(t){$(t).attr("disabled",!0),$(t).find("[data-pulse]").removeAttr("data-pulse");let e=$(t).attr("data-field"),i=$(t).attr("data-entity-type")?$(t).attr("data-entity-type"):$(t).closest("[data-entity-type]").attr("data-entity-type"),a=$(t).attr("data-entity-id")?$(t).attr("data-entity-id"):$(t).closest("[data-entity-id]").attr("data-entity-id"),n=null;n=["INPUT","TEXTAREA"].includes($(t).prop("tagName"))?$(t).val():"code"==$(t).attr("data-format")?$(t).text():$(t).html();let r={};r[e]=n;try{await SaveSetting(i,a,r),$(t).removeAttr("disabled")}catch(t){return!1}return!0}function MoveCaretToElement(t){const e=document.createRange(),i=window.getSelection();e.selectNodeContents($(t)[0]),e.collapse(!0),i.removeAllRanges(),i.addRange(e)}function RevertElement(t){let e=$(t).parent().next(),i=$(e).next();if(i.is("editable-element-original")){let t="code"==$(e).attr("data-format");t&&DisableCodeEditor(e),$(e).html(i.html()),t&&EnableCodeEditor(e),SetEditorClean(e)}else Toast("Revert Failed","There was an error attempting to revert the content.","bg-danger text-light","bi-alert-triangle");$(e).html()}function DeleteElement(t){let e=$(t).parent().next();$(e).empty()}function UniqueID(t=""){return t+"_"+(Math.random()+1).toString(36).substring(7)}function UnixTime(){return Math.floor(Date.now()/1e3)}function Clamp(t,e,i){return Math.min(Math.max(t,e),i)}function getClassInteger(t,e){let i=$(t).attr("class").split(" ");for(let t=0;t<i.length;t++){let a=i[t].match(new RegExp("^"+e+"-(\\d+)$"));if(a)return parseInt(a[1])}return null}function decodeHtml(t){return(new DOMParser).parseFromString(t,"text/html").documentElement.textContent}function EmphasizeAPATitle(t){if(t.includes("<em>"))return t;if((t.match(/\(/g)||[]).length<2||t.includes("(Ed"))return t;let e=t.split(/([.?])/);t="";let i=0,a=!1,n=!1;for(let r of e)a&&!n&&r.endsWith(".")&&(t+="</em>",n=!0),i>3&&!a&&(t+="<em>",a=!0,r.includes("(")&&(r=r.replace("(","</em>("),r+="</em>",n=!0)),t+=r,i>0&&i++,r.endsWith(")")&&(i=1);return a&&!n&&(t+="</em>"),t}function formatHTML(t){t=(t=(t=(t=(t=(t="<div>"+(t=(t=(t=(t=(t=(t=(t=t.replace(/ /g," ")).replace(/\s\s+/g," ")).replace(/[\u00A0-\u9999<>&]/gim,function(t){return"&#"+t.charCodeAt(0)+";"})).replace(/data-selected="(.*?)"/g,"")).replace(/>/g,">[br]")).replace(/</g,"[br]<")).replace(/\[br\]/g,"</div><div>"))+"</div>").replace(/class="(.*?)"/g,'class="<span class="code-editor-class">$1</span>"')).replace(/src="(.*?)"/g,'src="<span class="code-editor-src">$1</span>"')).replace(/href="(.*?)"/g,'href="<span class="code-editor-href">$1</span>"')).replace(/id="(.*?)"/g,'id="<span class="code-editor-id">$1</span>"')).replace(/alt="(.*?)"/g,'alt="<span class="code-editor-alt">$1</span>"'),indent=-1;let e=$("<div>"+t+"</div>");return $(e).find("div").each(function(){let t={"margin-left":20*(indent+1)+"px"};"</"==$(this).text().substring(0,2)?indent--:"<"==$(this).text().substring(0,1)&&"<img "!==$(this).text().substring(0,5)&&"<input "!==$(this).text().substring(0,7)&&"<br"!==$(this).text().substring(0,3)&&indent++,$(this).css(t)}),$(e).html()}function UpdateDataTypes(t){t.children().each(function(){UpdateDataType(this)})}function ExitEditor(){}function TFToInt(t){return t?1:0}function FormatHTML(t){t=(t=(t=(t=(t=(t=(t=(t=(t="<div>"+(t=(t=t.replace(/ /g," ")).replace(/[\u00A0-\u9999<>&]/gim,function(t){return"&#"+t.charCodeAt(0)+";"}))+"</div>").replace(/class="(.*?)"/g,'class="<span class="highlight">$1</span>"')).replace(/src="(.*?)"/g,'src="<span class="highlight">$1</span>"')).replace(/href="(.*?)"/g,'href="<span class="highlight">$1</span>"')).replace(/id="(.*?)"/g,'id="<span class="highlight">$1</span>
1"')).replace(/alt="(.*?)"/g,'alt="<span class="highlight">$1</span>"')).replace(/>/g,"</span>>[br]")).replace(/</g,'[br]<<span class="highlight">')).replace(/\[br\]/g,"</div><div>"),indent=-1;let e=$("<div>"+t+"</div>");return $(e).find("div").each(function(){let t={"margin-left":20*(indent+1)+"px"};"</"==$(this).text().substring(0,2)?indent--:"<"==$(this).text().substring(0,1)&&"<img "!==$(this).text().substring(0,5)&&"<input "!==$(this).text().substring(0,7)&&"<br"!==$(this).text().substring(0,3)&&indent++,$(this).css(t)}),$(e).html()}function WrapLinksInATags(t){const e=(new DOMParser).parseFromString(t,"text/html"),i=/\b(?:https?:\/\/|www\.)[^\s<>]+(?:\.[^\s<>]+)*(?:\/[^\s<>]*)?/gi;return Array.from(e.body.childNodes).forEach(function t(e){if(e.nodeType===Node.TEXT_NODE){const t=[...e.textContent.matchAll(i)];if(t.length>0){const i=document.createDocumentFragment();let a=0;t.forEach(t=>{const n=t.index,r=n+t[0].length;n>a&&i.appendChild(document.createTextNode(e.textContent.slice(a,n)));const s=document.createElement("a");s.href=t[0].startsWith("http")?t[0]:"http://"+t[0],s.textContent=t[0],i.appendChild(s),a=r}),a<e.textContent.length&&i.appendChild(document.createTextNode(e.textContent.slice(a))),e.replaceWith(i)}}else e.nodeType===Node.ELEMENT_NODE&&"a"!==e.tagName.toLowerCase()&&Array.from(e.childNodes).forEach(t)}),e.body.innerHTML}function MandatoryCleanUp(t){return $(t).find(".qe-editable").removeClass("qe-editable"),ChangeAllTags(t,"B","STRONG"),ChangeAllTags(t,"I","EM"),ChangeAllTags(t,"H1","H2"),RemoveAllAttrs(t,"data-mce-style"),RemoveAllAttrs(t,"data-mce-src"),RemoveAllAttrs(t,"width"),RemoveAllAttrs(t,"height"),$(t).find("input[data-etb-pq-value], input.pq-fill").each(function(){let t=$(this).attr("data-etb-pq-value")||"",e=$("<input></input>").attr("data-role","fib").attr("data-value",t);$(this).replaceWith(e)}),$(t).find("img").each((t,e)=>{let i=$(e).parent()[0];$(i).is("p")&&($(e).insertBefore(i),Toast("Image Moved","An imaged was moved out of a paragraph, per HTML requirements.","bg-warning"))}),$("[data-etb-glossary-term-id]").each(function(){$(this).attr("data-glossary-term-id",$(this).attr("data-etb-glossary-term-id")),$(this).removeAttr("data-etb-glossary-term-id")}),$(".card.answerKey").each(async(t,e)=>{let i=$('<button class="accordion-button fs-4" type="button">Accordion Button Text</button>'),a=$('<div class="accordion-body"><p><br /></p></div>'),n=$(e).children("a").eq(0).html();console.log(n);let r=$(e).children("div").eq(0).html();console.log(r),a.html(r),i.html(n),$(e).replaceWith(i),i.after(a),Toast("Accordion Updated","An accordion was updated to the new format.","bg-info")}),$("iframe").each((t,e)=>{if(void 0!==$(e).attr("src")&&null!==$(e).attr("src")&&$(e).attr("src").startsWith("//jsfiddle.net/")){let t=$("<a></a>").addClass("btn btn-jsfiddle").text("Try it out...").attr("href","https:"+$(e).attr("src")).attr("target","_blank");$(e).replaceWith(t)}}),$(t).find("[data-etb-glossary-term-id]").each(function(){$(this).attr("data-glossary-term-id",$(this).attr("data-etb-glossary-term-id"))}),$(t).find(".glossary-link,[data-anchor-name],[data-etb-glossary-term-id]").removeAttr("class").removeAttr("data-anchor-name").removeAttr("data-etb-glossary-term-id").removeAttr("title").removeAttr("data-bs-original-title").removeAttr("data-bs-toggle"),t}function ChangeAllTags(t,e,i){$(t).find(e).each(function(){$(this).replaceWith($("<"+i+"/>"+$(this).html()+"</"+i+">"))})}function RemoveAllAttrs(t,e){return $(t).find("["+e+"]").removeAttr(e),t}function DeleteTable(){let t=$(GetSelected()).is("table")?GetSelected():$(GetSelected()).parentsUntil('main [data-field="text"]',"table").first();null!=t&&($(t).remove(),SelectElement(null),etbUndo.saveState(),HideSelectorMenu())}function InsertRow(){let t=$(GetSelected()).is("tr")?GetSelected():$(GetSelected()).parents("tr").first();if(null==t)return;let e=$(t).clone();$(e).children("td,th").text("-"),$(t).after(e),etbUndo.saveState(),HideSelectorMenu()}function DeleteRow(){let t=$(GetSelected()).is("tr")?GetSelected():$(GetSelected()).parentsUntil('main [data-field="text"]',"tr").first();null!=t&&($(t).remove(),SelectElement(null),etbUndo.saveState(),HideSelectorMenu())}function InsertColumn(){let t=$(GetSelected()).index();$(GetSelected()).closest("table").find("tr").each(function(){let e=$(this),i=e.children().eq(t).clone();i.text("-"),$(i).insertAfter(e.children().eq(t))}),etbUndo.saveState()}function DeleteColumn(){let t=$(GetSelected()).index();$(GetSelected()).closest("table").find("tr").each(function(){$(this).children().eq(t).remove()}),SelectElement(null),etbUndo.saveState()}function MergeWithNextCell(){let t=$(GetSelected()).closest("td, th"),e=t.next();if(0==e.length)return;let i=parseInt(t.attr("colspan"))||1;t.attr("colspan",i+1),t.append(" "+e.html()),e.remove(),etbUndo.saveState()}window.addEventListener("beforeunload",function(t){IsEditorDirty()&&(t.preventDefault(),t.returnValue="Changes you made may
1not be saved.")}),$.expr[":"].block=function(t){return"block"===$(t).css("display")||"inline-block"===$(t).css("display")||"table"===$(t).css("display")||$(t).is("li,code")},$.expr[":"].heading=function(t){return $(t).is("h1,h2,h3,h4,h5,h6")},$.expr[":"].next=function(t){return!!$(t).next().length};class EditorHistory{constructor(t){this.editor=t,this.stack=[],this.currentIndex=-1,this.stackLimit=30,this.delayTime=500,this.lastSaveTime=-this.delayTime,this.timeout=null,this.SaveState()}SaveState(){console.log("Saving state"),this.currentIndex!==this.stack.length-1&&(this.stack=this.stack.slice(0,this.currentIndex+1)),this.stack.push(this.editor.editorWindow.innerHTML),this.currentIndex=this.stack.length-1,this.stack.length>this.stackLimit&&(this.stack.shift(),this.currentIndex--),console.log(this.currentIndex)}Undo(){console.log("Undoing"),this.currentIndex>1?(console.log("Undoing"),this.currentIndex--,console.log(this.currentIndex),this.editor.editorWindow.innerHTML=this.stack[this.currentIndex]):Toast("Undo Limit","There are no more actions to undo.","bg-warning text-dark")}Redo(){console.log("Redoing"),null!==this.timeout&&clearTimeout(this.timeout),this.currentIndex<this.stack.length-1?(console.log("Redoing"),this.currentIndex++,console.log(this.currentIndex),this.editor.editorWindow.innerHTML=this.stack[this.currentIndex]):Toast("Undo Limit","There are no more actions to redo.","bg-warning text-dark")}}function VideoError(t){Toast("Video Service Missing","The video could not be loaded from that service","danger"),etbDelete(t)}function UpdateVideo(t=GetSelected()){if(null===t)return;let e=null,i=$(t).children("img").first(),a=getYouTubeIDFromUrl($(t).attr("href"));if(null==e&&null!==a&&(e="youtube"),null==a&&(a=getVimeoIDFromUrl($(t).attr("href"))),null==e&&null!==a&&(e="vimeo"),null==a&&(a=getKalturaIDFromUrl($(t).attr("href"))),null==e&&null!==a&&(e="kaltura"),null==e)return void VideoError(t);$(t).attr("data-video-type",e),$(t).attr("data-video-id",a);let n=null;switch(e){case"youtube":n=getYouTubeLinkFromId(a),$(t).attr("href",n),i.attr("data-youtube-thumbnail-style","max"),i.attr("src","https://i3.ytimg.com/vi/"+a+"/maxresdefault.jpg"),i.on("load",function(){$(this).width()<=120&&"hq"!==$(this).attr("data-youtube-thumbnail-style")&&(console.log("Falling back to smaller image for "+a),i.attr("src","https://i3.ytimg.com/vi/"+v+"/hqdefault.jpg"),i.attr("data-youtube-thumbnail-style","hq")),i.off("load")});break;case"vimeo":return n=getVimeoLinkFromId(a),$(t).attr("href",n),new Promise(function(t,e){$.get("https://vimeo.com/api/v2/video/"+a+".json").done(function(e){console.log(e[0].thumbnail_large),i.attr("data-vimeo-thumbnail-style","large"),i.attr("src",e[0].thumbnail_large),t(i.parents().last())})});case"kaltura":let e=getKalturaPartnerFromUrl($(t).attr("href"));if(null==e)return console.error("Kaltura partner missing"),void VideoError(t);n=getKalturaLinkFromId(a),$(t).attr("href",n),$(t).attr("data-kaltura-partner",e),i.attr("data-kaltura-thumbnail-style","1200"),i.attr("src","https://cdnsecakmi.kaltura.com/p/"+e+"/thumbnail/entry_id/"+v+"/width/1200")}etbUndo.saveState()}class DOIXML{constructor(t){this.book=t}XMLString(t,e="",i={}){let a="<"+t;for(let t in i)a+=" "+t+'="'+i[t]+'"';a+=">";const n=document.createElement("textarea");return n.innerHTML=e,e=n.value,$(n).remove(),a+=e,a+="</"+t+">",a}async Render(){await GetCurrentUser();let t,e=this.XMLString("depositor",this.XMLString("depositor_name",current_user.name)+this.XMLString("email_address",current_user.settings.email)),i=this.XMLString("head",this.XMLString("doi_batch_id",UniqueID("DOI_"))+this.XMLString("timestamp",UnixTime())+e+this.XMLString("registrant",(await GetSite()).name));if("journal"===(null!=this.book.settings.publication_type?this.book.settings.publication_type:"book"))t=await this.RenderJournal();else t=await this.RenderBook();let a=this.XMLString("body",t),n=this.XMLString("doi_batch",i+a,{"xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance","xsi:schemaLocation":"http://www.crossref.org/schema/5.3.0 https://www.crossref.org/schemas/crossref5.3.0.xsd",xmlns:"http://www.crossref.org/schema/5.3.0","xmlns:jats":"http://www.ncbi.nlm.nih.gov/JATS1","xmlns:fr":"http://www.crossref.org/fundref.xsd","xmlns:mml":"http://www.w3.org/1998/Math/MathML",version:"5.3.0"});return n=n.replace(/&/g,"& "),'<?xml version="1.0" encoding="UTF-8"?>'+n}async RenderJournal(){let t=this.XMLString("doi_data",this.XMLString("doi",this.book.settings.doi)+this.XMLString("resource",(await GetSite()).base_url+this.book.short_name)),e=null!=this.book.settings.language_id?this.book.settings.language_id:"en",i=this.XMLString("journal_metadata",this.XMLString("full_title",this.book.title)+t,{language:e,reference_distribution_opts:"any"}),a="";null!=this.book.settings.published_year&&(a=this.XMLString("publication_date",this.XMLString("year",this.book.settings.published_year)));let n="";void 0!==this.book.settings.volume&&(n=this.XMLString("journal_volume",this.XMLString("volume",this.book.settings.volume)));let r="";void 0!==this.book.settings.issue&&(r=this.XMLString("issue",this.book.settings.issue));let s=this.XMLString("journal_issue",a+n+r),o="";for(let t of this.book.chapter_links){let e=await GetChapterFromID(t.id);1==e.published&&void 0!==e.settings.doi&&0!=e.settings.doi.length&&(o+=await this.RenderArticle(e))}return this.XMLString("journal",i+s+o)}async RenderArticle(t){let e=null!=t.settings.language_id?t.settings.language_id:null!=this.book.settings.language_id?this.book.settings.language_id:"en",i="";if(i+=this.XMLString("titles",this.XMLString("title",t.title)),t.authorships.length>0){let e="",a=0;for(let i of t.authorships){if(1==i.shadow_author)continue;let t=await GetAuthor(i.author_id);e+=await this.RenderAuthor(t,a++)}i+=this.XMLString("contributors",e)}if(null!=t.settings.abstract){i+=this.XMLString("jats:abstract",this.XMLString("jats:p",null!=t.settings.abstract?t.settings.abstract.replace(/<[^>]*>/g,""):""))}let a=void 0!==t.settings.published_year?t.settings.published_year:this.book.settings.published_year;return i+=this.XMLString("publication_date",this.XMLString("year",a),{media_type:"online"}),i+=this.XMLString("doi_data",this.XMLString("doi",t.settings.doi)+this.XMLString("resource",(await GetSite()).base_url+this.book.short_name+"/"+t.short_name)),this.XMLString("journal_article",i,{publication_type:"full_text",language:e,reference_distribution_opts:"any"})}async RenderChapter(t){let e=null!=t.settings.language_id?t.settings.language_id:null!=this.book.settings.language_id?this.book.settings.language_id:"en",i="";if(t.authorships.length>0){let e="",a=0;for(let i of t.authorships){if(1==i.shadow_author)continue;let t=await GetAuthor(i.author_id);e+=await this.RenderAuthor(t,a++)}i+=this.XMLString("contributors",e)}if(i+=this.XMLString("titles",this.XMLString("title",t.title)),null!=t.settings.abstract){i+=this.XMLString("jats:abstract",this.XMLString("jats:p",null!=t.settings.abstract?t.settings.abstract.replace(/<[^>]*>/g,""):""))}let a=void 0!==t.settings.published_year?t.settings.published_year:this.book.settings.published_year;return i+=this.XMLString("publication_date",this.XMLString("year",a),{media_type:"online"}),i+=this.XMLString("doi_data",this.XMLString("doi",t.settings.doi)+this.XMLString("resource",(await GetSite()).base_url+this.book.short_name+"/"+t.short_name)),this.XMLString("content_item",i,{publication_type:"full_text",language:e,component_type:"chapter"})}async RenderAuthor(t,e=0){let i=null!=t.settings.given_name?t.settings.given_name:"Unknown";i=this.XMLString("given_name",i);let a=null!=t.settings.surname?t.settings.surname:"Unknown";a=this.XMLString("surname",a);let n=i+a;if(void 0!==t.affiliation&&null!==t.affiliation&&t.affiliation.length>0){n+=this.XMLString("affiliations",this.XMLString("institution",this.XMLString("institution_name",t.affiliation)))}let r={contributor_role:"author"};return r.sequence=0==e?"first":"additional",this.XMLString("person_name",n,r)}async RenderBook(){let t="";if(this.book.authorships.length>0){let e="",i=0;for(let t of this.book.authorships){if(1==t.shadow_author)continue;let a=await GetAuthor(t.author_id);e+=await this.RenderAuthor(a,i++)}
1t=this.XMLString("contributors",e)}let e=this.XMLString("doi_data",this.XMLString("doi",this.book.settings.doi)+this.XMLString("resource",(await GetSite()).base_url+this.book.short_name)),i=this.XMLString("titles",this.XMLString("title",this.book.title)),a=this.XMLString("jats:abstract",this.XMLString("jats:p",null!=this.book.settings.abstract?this.book.settings.abstract.replace(/<[^>]*>/g,""):"")),n=this.XMLString("publication_date",this.XMLString("year",this.book.settings.published_year)),r=this.XMLString("acceptance_date",this.XMLString("year",this.book.settings.published_year)),s=null!=this.book.settings.language_id?this.book.settings.language_id:"en",o=this.XMLString("noisbn","",{reason:"archive_volume"}),l=this.XMLString("publisher",this.XMLString("publisher_name",(await GetSite()).name)),d=this.XMLString("book_metadata",t+i+a+n+r+o+l+e,{language:s}),h="";for(let t of this.book.chapter_links){let e=await GetChapterFromID(t.id);1==e.published&&void 0!==e.settings.doi&&0!=e.settings.doi.length&&(h+=await this.RenderChapter(e))}return this.XMLString("book",d+h,{book_type:"monograph"})}}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.