2023-05-19 16:33:14 -04:00
function _define _property ( obj , key , value ) { if ( key in obj ) { Object . defineProperty ( obj , key , { value : value , enumerable : true , configurable : true , writable : true } ) } else { obj [ key ] = value } return obj } function _object _spread ( target ) { for ( var i = 1 ; i < arguments . length ; i ++ ) { var source = arguments [ i ] != null ? arguments [ i ] : { } ; var ownKeys = Object . keys ( source ) ; if ( typeof Object . getOwnPropertySymbols === "function" ) { ownKeys = ownKeys . concat ( Object . getOwnPropertySymbols ( source ) . filter ( function ( sym ) { return Object . getOwnPropertyDescriptor ( source , sym ) . enumerable } ) ) } ownKeys . forEach ( function ( key ) { _define _property ( target , key , source [ key ] ) } ) } return target } if ( "serviceWorker" in navigator ) navigator . serviceWorker . register ( "/sw.js" ) . then ( reg => { console . log ( "Service worker registered" , reg . scope ) } ) . catch ( error => { console . error ( "Failed to register service worker" , error ) } ) ; const matches = ( elm , selector ) => { let m = ( elm . document || elm . ownerDocument ) . querySelectorAll ( selector ) ; let i = matches . length ; while ( -- i >= 0 && m . item ( i ) !== elm ) ; return i > - 1 } ; const AnimeClient = { noop : ( ) => { } , $ ( selector , context = null ) { if ( typeof selector !== "string" ) return selector ; context = context !== null && context . nodeType === 1 ? context : document ; let elements = [ ] ; if ( selector . match ( /^#([\w]+$)/ ) ) elements . push ( document . getElementById ( selector . split ( "#" ) [ 1 ] ) ) ; else elements = [ ] . slice . apply ( context . querySelectorAll ( selector ) ) ; return elements } , hasElement ( selector ) { return AnimeClient . $ ( selector ) . length > 0 } , scrollToTop ( ) { const el = AnimeClient . $ ( "header" ) [ 0 ] ; el . scrollIntoView ( true ) } , hide ( sel ) { if ( typeof sel === "string" ) sel = AnimeClient . $ ( sel ) ; if ( Array . isArray ( sel ) ) sel . forEach ( el => el . setAttribute ( "hidden" , "hidden" ) ) ; else sel . setAttribute ( "hidden" , "hidden" ) } , show ( sel ) { if ( typeof sel === "string" ) sel = AnimeClient . $ ( sel ) ; if ( Array . isArray ( sel ) ) sel . forEach ( el => el . removeAttribute ( "hidden" ) ) ; else sel . removeAttribute ( "hidden" ) } , showMessage ( type , message ) { let template = ` <div class='message ${ type } '>
2023-03-17 11:09:43 -04:00
< span class = 'icon' > < / s p a n >
$ { message }
< span class = 'close' > < / s p a n >
2023-05-19 16:33:14 -04:00
< /div>`;let sel=AnimeClient.$(".message");if(sel[0]!==undefined)sel[0].remove();AnimeClient.$("header")[0].insertAdjacentHTML("beforeend",template)},closestParent(current,parentSelector){if(Element.prototype.closest!==undefined)return current.closest(parentSelector);while(current!==document.documentElement){if(matches(current,parentSelector))return current;current=current.parentElement}return null},url(path){let uri=`/ / $ { document . location . host } ` ;uri+=path.charAt(0)==="/"?path: ` / $ { path } ` ;return uri},throttle(interval,fn,scope){let wait=false;return function(...args){const context=scope||this;if(!wait){fn.apply(context,args);wait=true;setTimeout(function(){wait=false},interval)}}}};function addEvent(sel,event,listener){if(!event.match(/^([ \w \- ]+) $ /))event.split(" ").forEach(evt=>{addEvent(sel,evt,listener)});sel.addEventListener(event,listener,false)}function delegateEvent(sel,target,event,listener){addEvent(sel,event,e=>{AnimeClient. $ (target,sel).forEach(element=>{if(e.target==element){listener.call(element,e);e.stopPropagation()}})})}AnimeClient.on=(sel,event,target,listener)=>{if(listener===undefined){listener=target;AnimeClient. $ (sel).forEach(el=>{addEvent(el,event,listener)})}else AnimeClient. $ (sel).forEach(el=>{delegateEvent(el,target,event,listener)})};function ajaxSerialize(data){let pairs=[];Object.keys(data).forEach(name=>{let value=data[name].toString();name=encodeURIComponent(name);value=encodeURIComponent(value);pairs.push( ` $ { name } = $ { value } ` )});return pairs.join("&")}AnimeClient.ajax=(url,config)=>{const defaultConfig={data:{},type:"GET",dataType:"",success:AnimeClient.noop,mimeType:"application/x-www-form-urlencoded",error:AnimeClient.noop};config=_object_spread({},defaultConfig,config);let request=new XMLHttpRequest;let method=String(config.type).toUpperCase();if(method==="GET")url+=url.match(/ \? /)?ajaxSerialize(config.data): ` ? $ { ajaxSerialize ( config . data ) } ` ;request.open(method,url);request.onreadystatechange=()=>{if(request.readyState===4){let responseText="";if(request.responseType==="json")responseText=JSON.parse(request.responseText);else responseText=request.responseText;if(request.status>299)config.error.call(null,request.status,responseText,request.response);else config.success.call(null,responseText,request.status)}};if(config.dataType==="json"){config.data=JSON.stringify(config.data);config.mimeType="application/json"}else config.data=ajaxSerialize(config.data);request.setRequestHeader("Content-Type",config.mimeType);if(method==="GET")request.send(null);else request.send(config.data);return request};AnimeClient.get=(url,data,callback=null)=>{if(callback===null){callback=data;data={}}return AnimeClient.ajax(url,{data,success:callback})};AnimeClient.on("header","click",".message",hide);AnimeClient.on("form.js-delete","submit",confirmDelete);AnimeClient.on(".js-clear-cache","click",clearAPICache);AnimeClient.on(".vertical-tabs input","change",scrollToSection);AnimeClient.on(".media-filter","input",filterMedia);function hide(event){AnimeClient.hide(event.target)}function confirmDelete(event){const proceed=confirm("Are you ABSOLUTELY SURE you want to delete this item?");if(proceed===false){event.preventDefault();event.stopPropagation()}}function clearAPICache(){AnimeClient.get("/cache_purge",()=>{AnimeClient.showMessage("success","Successfully purged api cache")})}function scrollToSection(event){const el=event.currentTarget.parentElement;const rect=el.getBoundingClientRect();const top=rect.top+window.pageYOffset;window.scrollTo({top,behavior:"smooth"})}function filterMedia(event){const rawFilter=event.target.value;const filter=new RegExp(rawFilter,"i");if(rawFilter!==""){AnimeClient. $ ("article.media").forEach(article=>{const titleLink=AnimeClient. $ (".name a",article)[0];const title=String(titleLink.textContent).trim();if(!filter.test(title))AnimeClient.hide(article);else AnimeClient.show(article)});AnimeClient. $ ("table.media-wrap tbody tr").forEach(tr=>{const titleCell=AnimeClient. $ ("td.align-left",tr)[0];const titleLink=AnimeClient. $ ("a",titleCell)[0];const linkTitle=String(titleLink.textContent).tri
2023-03-17 11:09:43 -04:00
< div class = "row" >
< span class = "edit" > < big > [ Already in List ] < / b i g > < / s p a n >
< / d i v >
< div class = "row" >
< span class = "edit" >
< a class = "bracketed" href = "/${type}/edit/${item.libraryEntry.id}/${item.libraryEntry.status}" > Edit < / a >
< / s p a n >
< / d i v >
< div class = "row" > < span class = "edit" > & nbsp ; < / s p a n > < / d i v >
` }function renderSearchResults(type,data,isCollection=false){return data.map(item=>{const titles=item.titles.join("<br />");let disabled=item.libraryEntry!==null?"disabled":"";const editLink=renderEditLink(type,item,isCollection);if(isCollection)disabled="";return `
< article class = "media search ${disabled}" >
< div class = "name" >
< input type = "radio" class = "mal-check" id = "anilist_${item.slug}" name = "anilist_id" value = "${item.anilist_id}" $ { disabled } / >
< input type = "radio" class = "mal-check" id = "mal_${item.slug}" name = "mal_id" value = "${item.mal_id}" $ { disabled } / >
< input type = "radio" class = "big-check" id = "${item.slug}" name = "id" value = "${item.id}" $ { disabled } / >
< label for = "${item.slug}" >
< img src = "${item.coverImage}" alt = "" width = "220" / >
< span class = "name" >
$ { item . canonicalTitle } < br / >
< small > $ { titles } < / s m a l l >
< / s p a n >
< / l a b e l >
< / d i v >
< div class = "table" >
$ { editLink }
< div class = "row" >
< span class = "edit" >
< a class = "bracketed" href = "/${type}/details/${item.slug}" > Info Page < / a >
< / s p a n >
< / d i v >
< / d i v >
< / a r t i c l e >
2023-05-19 16:33:14 -04:00
` }).join("")}function _normalizeProperty(props,sep="."){return props.replace(/ \[ (.*?)]/g,sep+" $ 1")}function hasNestedProperty(object,property){if(object&&typeof object==="object"){if(typeof property==="string"&&property!==""){property=_normalizeProperty(property);let split=property.split(".");return split.reduce((obj,prop,idx,array)=>{if(idx===array.length-1)return!!(obj&&obj.hasOwnProperty(prop));return obj&&obj[prop]},object)}else if(typeof property==="number")return property in object}return false}function getNestedProperty(object,property,sep="."){if(isType("string",property)&&property!==""){property=_normalizeProperty(property,sep);const levels=property.split(sep);try{return levels.reduce((obj,prop)=>obj[prop],object)}catch(e){return undefined}}return null}function getType(x){if(Array.isArray(x))return"array";if(typeof x!=="object")return(typeof x).toLowerCase();const type=function(){return Object.prototype.toString.call(this).slice(8,-1)};return type.call(x).toLowerCase()}function isType(type,val){return getType(val)===String(type).toLowerCase()}const search=(query,isCollection=false)=>{AnimeClient.show(".cssload-loader");return AnimeClient.get(AnimeClient.url("/anime-collection/search"),{query},(searchResults,status)=>{searchResults=JSON.parse(searchResults);AnimeClient.hide(".cssload-loader");AnimeClient. $ ("#series-list")[0].innerHTML=renderSearchResults("anime",searchResults,isCollection)})};if(AnimeClient.hasElement(".anime #search")){let prevRequest=null;AnimeClient.on("#search","input",AnimeClient.throttle(250,e=>{const query=encodeURIComponent(e.target.value);if(query==="")return;if(prevRequest!==null)prevRequest.abort();prevRequest=search(query)}))}if(AnimeClient.hasElement("#search-anime-collection")){let prevRequest=null;AnimeClient.on("#search-anime-collection","input",AnimeClient.throttle(250,e=>{const query=encodeURIComponent(e.target.value);if(query==="")return;if(prevRequest!==null)prevRequest.abort();prevRequest=search(query,true)}))}AnimeClient.on("body.anime.list","click",".plus-one",e=>{let parentSel=AnimeClient.closestParent(e.target,"article");let watchedCount=parseInt(AnimeClient. $ (".completed_number",parentSel)[0].textContent,10)||0;let totalCount=parseInt(AnimeClient. $ (".total_number",parentSel)[0].textContent,10);let title=AnimeClient. $ (".name a",parentSel)[0].textContent;let data={id:parentSel.dataset.kitsuId,anilist_id:parentSel.dataset.anilistId,mal_id:parentSel.dataset.malId,data:{progress:watchedCount+1}};const displayMessage=(type,message)=>{AnimeClient.hide("#loading-shadow");AnimeClient.showMessage(type, ` $ { message } $ { title } ` );AnimeClient.scrollToTop()};const showError=()=>displayMessage("error","Failed to update");if(isNaN(watchedCount)||watchedCount===0)data.data.status="CURRENT";if(!isNaN(watchedCount)&&watchedCount+1===totalCount)data.data.status="COMPLETED";AnimeClient.show("#loading-shadow");AnimeClient.ajax(AnimeClient.url("/anime/increment"),{data,dataType:"json",type:"POST",success:res=>{try{const resData=JSON.parse(res);let updatedProgress=getNestedProperty(resData,"data.libraryEntry.update.libraryEntry.progress");if(hasNestedProperty(resData,"error")||updatedProgress!==data.data.progress){showError();return}if(getNestedProperty(resData,"data.libraryEntry.update.libraryEntry.status")==="COMPLETED"){AnimeClient.hide(parentSel);displayMessage("success","Completed");return}AnimeClient. $ (".completed_number",parentSel)[0].textContent=++watchedCount;displayMessage("success","Updated")}catch(_){showError()}},error:showError})});const search1=query=>{AnimeClient.show(".cssload-loader");return AnimeClient.get(AnimeClient.url("/manga/search"),{query},(searchResults,status)=>{searchResults=JSON.parse(searchResults);AnimeClient.hide(".cssload-loader");AnimeClient. $ ("#series-list")[0].innerHTML=renderSearchResults("manga",searchResults)})};if(AnimeClient.hasElement(".manga #search")){let prevRequest=null;AnimeClient.on("#search","input",AnimeClient.throttle(250,e=>{let query=encodeURIComponent(e.target.value);if(query==="")return;if(prevRequest!==null)prevRequest.abort();prevRequest=