{"version":3,"sources":["/var/www/htdocs/github.timshomepage.net/animeclient/frontEndSrc/js/sw.js","/var/www/htdocs/github.timshomepage.net/animeclient/frontEndSrc/js/anime-client.js","/var/www/htdocs/github.timshomepage.net/animeclient/frontEndSrc/js/events.js","/var/www/htdocs/github.timshomepage.net/animeclient/frontEndSrc/js/session-check.js","/var/www/htdocs/github.timshomepage.net/animeclient/frontEndSrc/js/template-helpers.js","/var/www/htdocs/github.timshomepage.net/animeclient/frontEndSrc/js/fns.js","/var/www/htdocs/github.timshomepage.net/animeclient/frontEndSrc/js/anime.js","/var/www/htdocs/github.timshomepage.net/animeclient/frontEndSrc/js/manga.js"],"sourcesContent":["// Start the service worker, if you can\nif ('serviceWorker' in navigator) {\n\tnavigator.serviceWorker.register('/sw.js').then(reg => {\n\t\tconsole.log('Service worker registered', reg.scope);\n\t}).catch(error => {\n\t\tconsole.error('Failed to register service worker', error);\n\t});\n}","// -------------------------------------------------------------------------\n// ! Base\n// -------------------------------------------------------------------------\n\nconst matches = (elm, selector) => {\n\tlet m = (elm.document || elm.ownerDocument).querySelectorAll(selector);\n\tlet i = matches.length;\n\twhile (--i >= 0 && m.item(i) !== elm) {};\n\treturn i > -1;\n}\n\nconst AnimeClient = {\n\t/**\n\t * Placeholder function\n\t */\n\tnoop: () => {},\n\t/**\n\t * DOM selector\n\t *\n\t * @param {string} selector - The dom selector string\n\t * @param {Element} [context]\n\t * @return array of dom elements\n\t */\n\t$(selector, context = null) {\n\t\tif (typeof selector !== 'string') {\n\t\t\treturn selector;\n\t\t}\n\n\t\tcontext = (context !== null && context.nodeType === 1)\n\t\t\t? context\n\t\t\t: document;\n\n\t\tlet elements = [];\n\t\tif (selector.match(/^#([\\w]+$)/)) {\n\t\t\telements.push(document.getElementById(selector.split('#')[1]));\n\t\t} else {\n\t\t\telements = [].slice.apply(context.querySelectorAll(selector));\n\t\t}\n\n\t\treturn elements;\n\t},\n\t/**\n\t * Does the selector exist on the current page?\n\t *\n\t * @param {string} selector\n\t * @returns {boolean}\n\t */\n\thasElement (selector) {\n\t\treturn AnimeClient.$(selector).length > 0;\n\t},\n\t/**\n\t * Scroll to the top of the Page\n\t *\n\t * @return {void}\n\t */\n\tscrollToTop () {\n\t\tconst el = AnimeClient.$('header')[0];\n\t\tel.scrollIntoView(true);\n\t},\n\t/**\n\t * Hide the selected element\n\t *\n\t * @param {string|Element|Element[]} sel - the selector of the element to hide\n\t * @return {void}\n\t */\n\thide (sel) {\n\t\tif (typeof sel === 'string') {\n\t\t\tsel = AnimeClient.$(sel);\n\t\t}\n\n\t\tif (Array.isArray(sel)) {\n\t\t\tsel.forEach(el => el.setAttribute('hidden', 'hidden'));\n\t\t} else {\n\t\t\tsel.setAttribute('hidden', 'hidden');\n\t\t}\n\t},\n\t/**\n\t * UnHide the selected element\n\t *\n\t * @param {string|Element|Element[]} sel - the selector of the element to hide\n\t * @return {void}\n\t */\n\tshow (sel) {\n\t\tif (typeof sel === 'string') {\n\t\t\tsel = AnimeClient.$(sel);\n\t\t}\n\n\t\tif (Array.isArray(sel)) {\n\t\t\tsel.forEach(el => el.removeAttribute('hidden'));\n\t\t} else {\n\t\t\tsel.removeAttribute('hidden');\n\t\t}\n\t},\n\t/**\n\t * Display a message box\n\t *\n\t * @param {string} type - message type: info, error, success\n\t * @param {string} message - the message itself\n\t * @return {void}\n\t */\n\tshowMessage (type, message) {\n\t\tlet template =\n\t\t\t`
\n\t\t\t\t\n\t\t\t\t${message}\n\t\t\t\t\n\t\t\t
`;\n\n\t\tlet sel = AnimeClient.$('.message');\n\t\tif (sel[0] !== undefined) {\n\t\t\tsel[0].remove();\n\t\t}\n\n\t\tAnimeClient.$('header')[0].insertAdjacentHTML('beforeend', template);\n\t},\n\t/**\n\t * Finds the closest parent element matching the passed selector\n\t *\n\t * @param {Element} current - the current Element\n\t * @param {string} parentSelector - selector for the parent element\n\t * @return {Element|null} - the parent element\n\t */\n\tclosestParent (current, parentSelector) {\n\t\tif (Element.prototype.closest !== undefined) {\n\t\t\treturn current.closest(parentSelector);\n\t\t}\n\n\t\twhile (current !== document.documentElement) {\n\t\t\tif (matches(current, parentSelector)) {\n\t\t\t\treturn current;\n\t\t\t}\n\n\t\t\tcurrent = current.parentElement;\n\t\t}\n\n\t\treturn null;\n\t},\n\t/**\n\t * Generate a full url from a relative path\n\t *\n\t * @param {string} path - url path\n\t * @return {string} - full url\n\t */\n\turl (path) {\n\t\tlet uri = `//${document.location.host}`;\n\t\turi += (path.charAt(0) === '/') ? path : `/${path}`;\n\n\t\treturn uri;\n\t},\n\t/**\n\t * Throttle execution of a function\n\t *\n\t * @see https://remysharp.com/2010/07/21/throttling-function-calls\n\t * @see https://jsfiddle.net/jonathansampson/m7G64/\n\t * @param {Number} interval - the minimum throttle time in ms\n\t * @param {Function} fn - the function to throttle\n\t * @param {Object} [scope] - the 'this' object for the function\n\t * @return {Function}\n\t */\n\tthrottle (interval, fn, scope) {\n\t\tlet wait = false;\n\t\treturn function (...args) {\n\t\t\tconst context = scope || this;\n\n\t\t\tif ( ! wait) {\n\t\t\t\tfn.apply(context, args);\n\t\t\t\twait = true;\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\twait = false;\n\t\t\t\t}, interval);\n\t\t\t}\n\t\t};\n\t},\n};\n\n// -------------------------------------------------------------------------\n// ! Events\n// -------------------------------------------------------------------------\n\nfunction addEvent(sel, event, listener) {\n\t// Recurse!\n\tif (! event.match(/^([\\w\\-]+)$/)) {\n\t\tevent.split(' ').forEach((evt) => {\n\t\t\taddEvent(sel, evt, listener);\n\t\t});\n\t}\n\n\tsel.addEventListener(event, listener, false);\n}\n\nfunction delegateEvent(sel, target, event, listener) {\n\t// Attach the listener to the parent\n\taddEvent(sel, event, (e) => {\n\t\t// Get live version of the target selector\n\t\tAnimeClient.$(target, sel).forEach((element) => {\n\t\t\tif(e.target == element) {\n\t\t\t\tlistener.call(element, e);\n\t\t\t\te.stopPropagation();\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Add an event listener\n *\n * @param {string|Element} sel - the parent selector to bind to\n * @param {string} event - event name(s) to bind\n * @param {string|Element|function} target - the element to directly bind the event to\n * @param {function} [listener] - event listener callback\n * @return {void}\n */\nAnimeClient.on = (sel, event, target, listener) => {\n\tif (listener === undefined) {\n\t\tlistener = target;\n\t\tAnimeClient.$(sel).forEach((el) => {\n\t\t\taddEvent(el, event, listener);\n\t\t});\n\t} else {\n\t\tAnimeClient.$(sel).forEach((el) => {\n\t\t\tdelegateEvent(el, target, event, listener);\n\t\t});\n\t}\n};\n\n// -------------------------------------------------------------------------\n// ! Ajax\n// -------------------------------------------------------------------------\n\n/**\n * Url encoding for non-get requests\n *\n * @param data\n * @returns {string}\n * @private\n */\nfunction ajaxSerialize(data) {\n\tlet pairs = [];\n\n\tObject.keys(data).forEach((name) => {\n\t\tlet value = data[name].toString();\n\n\t\tname = encodeURIComponent(name);\n\t\tvalue = encodeURIComponent(value);\n\n\t\tpairs.push(`${name}=${value}`);\n\t});\n\n\treturn pairs.join('&');\n}\n\n/**\n * Make an ajax request\n *\n * Config:{\n * \tdata: // data to send with the request\n * \ttype: // http verb of the request, defaults to GET\n * \tsuccess: // success callback\n * \terror: // error callback\n * }\n *\n * @param {string} url - the url to request\n * @param {Object} config - the configuration object\n * @return {XMLHttpRequest}\n */\nAnimeClient.ajax = (url, config) => {\n\t// Set some sane defaults\n\tconst defaultConfig = {\n\t\tdata: {},\n\t\ttype: 'GET',\n\t\tdataType: '',\n\t\tsuccess: AnimeClient.noop,\n\t\tmimeType: 'application/x-www-form-urlencoded',\n\t\terror: AnimeClient.noop\n\t}\n\n\tconfig = {\n\t\t...defaultConfig,\n\t\t...config,\n\t}\n\n\tlet request = new XMLHttpRequest();\n\tlet method = String(config.type).toUpperCase();\n\n\tif (method === 'GET') {\n\t\turl += (url.match(/\\?/))\n\t\t\t? ajaxSerialize(config.data)\n\t\t\t: `?${ajaxSerialize(config.data)}`;\n\t}\n\n\trequest.open(method, url);\n\n\trequest.onreadystatechange = () => {\n\t\tif (request.readyState === 4) {\n\t\t\tlet responseText = '';\n\n\t\t\tif (request.responseType === 'json') {\n\t\t\t\tresponseText = JSON.parse(request.responseText);\n\t\t\t} else {\n\t\t\t\tresponseText = request.responseText;\n\t\t\t}\n\n\t\t\tif (request.status > 299) {\n\t\t\t\tconfig.error.call(null, request.status, responseText, request.response);\n\t\t\t} else {\n\t\t\t\tconfig.success.call(null, responseText, request.status);\n\t\t\t}\n\t\t}\n\t};\n\n\tif (config.dataType === 'json') {\n\t\tconfig.data = JSON.stringify(config.data);\n\t\tconfig.mimeType = 'application/json';\n\t} else {\n\t\tconfig.data = ajaxSerialize(config.data);\n\t}\n\n\trequest.setRequestHeader('Content-Type', config.mimeType);\n\n\tif (method === 'GET') {\n\t\trequest.send(null);\n\t} else {\n\t\trequest.send(config.data);\n\t}\n\n\treturn request\n};\n\n/**\n * Do a get request\n *\n * @param {string} url\n * @param {object|function} data\n * @param {function} [callback]\n * @return {XMLHttpRequest}\n */\nAnimeClient.get = (url, data, callback = null) => {\n\tif (callback === null) {\n\t\tcallback = data;\n\t\tdata = {};\n\t}\n\n\treturn AnimeClient.ajax(url, {\n\t\tdata,\n\t\tsuccess: callback\n\t});\n};\n\n// -------------------------------------------------------------------------\n// Export\n// -------------------------------------------------------------------------\n\nexport default AnimeClient;","import _ from './anime-client.js';\n\n// ----------------------------------------------------------------------------\n// Event subscriptions\n// ----------------------------------------------------------------------------\n_.on('header', 'click', '.message', hide);\n_.on('form.js-delete', 'submit', confirmDelete);\n_.on('.js-clear-cache', 'click', clearAPICache);\n_.on('.vertical-tabs input', 'change', scrollToSection);\n_.on('.media-filter', 'input', filterMedia);\n\n// ----------------------------------------------------------------------------\n// Handler functions\n// ----------------------------------------------------------------------------\n\n/**\n * Hide the html element attached to the event\n *\n * @param {MouseEvent} event\n * @return void\n */\nfunction hide (event) {\n\t_.hide(event.target)\n}\n\n/**\n * Confirm deletion of an item\n *\n * @param {MouseEvent} event\n * @return void\n */\nfunction confirmDelete (event) {\n\tconst proceed = confirm('Are you ABSOLUTELY SURE you want to delete this item?');\n\n\tif (proceed === false) {\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t}\n}\n\n/**\n * Clear the API cache, and show a message if the cache is cleared\n *\n * @return void\n */\nfunction clearAPICache () {\n\t_.get('/cache_purge', () => {\n\t\t_.showMessage('success', 'Successfully purged api cache');\n\t});\n}\n\n/**\n * Scroll to the accordion/vertical tab section just opened\n *\n * @param {InputEvent} event\n * @return void\n */\nfunction scrollToSection (event) {\n\tconst el = event.currentTarget.parentElement;\n\tconst rect = el.getBoundingClientRect();\n\n\tconst top = rect.top + window.pageYOffset;\n\n\twindow.scrollTo({\n\t\ttop,\n\t\tbehavior: 'smooth',\n\t});\n}\n\n/**\n * Filter an anime or manga list\n *\n * @param {InputEvent} event\n * @return void\n */\nfunction filterMedia (event) {\n\tconst rawFilter = event.target.value;\n\tconst filter = new RegExp(rawFilter, 'i');\n\n\t// console.log('Filtering items by: ', filter);\n\n\tif (rawFilter !== '') {\n\t\t// Filter the cover view\n\t\t_.$('article.media').forEach(article => {\n\t\t\tconst titleLink = _.$('.name a', article)[0];\n\t\t\tconst title = String(titleLink.textContent).trim();\n\t\t\tif ( ! filter.test(title)) {\n\t\t\t\t_.hide(article);\n\t\t\t} else {\n\t\t\t\t_.show(article);\n\t\t\t}\n\t\t});\n\n\t\t// Filter the list view\n\t\t_.$('table.media-wrap tbody tr').forEach(tr => {\n\t\t\tconst titleCell = _.$('td.align-left', tr)[0];\n\t\t\tconst titleLink = _.$('a', titleCell)[0];\n\t\t\tconst linkTitle = String(titleLink.textContent).trim();\n\t\t\tconst textTitle = String(titleCell.textContent).trim();\n\t\t\tif ( ! (filter.test(linkTitle) || filter.test(textTitle))) {\n\t\t\t\t_.hide(tr);\n\t\t\t} else {\n\t\t\t\t_.show(tr);\n\t\t\t}\n\t\t});\n\t} else {\n\t\t_.show('article.media');\n\t\t_.show('table.media-wrap tbody tr');\n\t}\n}\n","import _ from './anime-client.js';\n\n(() => {\n\tlet hidden = null;\n\tlet visibilityChange = null;\n\n\tif (typeof document.hidden !== \"undefined\") {\n\t\thidden = \"hidden\";\n\t\tvisibilityChange = \"visibilitychange\";\n\t} else if (typeof document.msHidden !== \"undefined\") {\n\t\thidden = \"msHidden\";\n\t\tvisibilityChange = \"msvisibilitychange\";\n\t} else if (typeof document.webkitHidden !== \"undefined\") {\n\t\thidden = \"webkitHidden\";\n\t\tvisibilityChange = \"webkitvisibilitychange\";\n\t}\n\n\tfunction handleVisibilityChange() {\n\t\t// Check the user's session to see if they are currently logged-in\n\t\t// when the page becomes visible\n\t\tif ( ! document[hidden]) {\n\t\t\t_.get('/heartbeat', (beat) => {\n\t\t\t\tconst status = JSON.parse(beat)\n\n\t\t\t\t// If the session is expired, immediately reload so that\n\t\t\t\t// you can't attempt to do an action that requires authentication\n\t\t\t\tif (status.hasAuth !== true) {\n\t\t\t\t\tdocument.removeEventListener(visibilityChange, handleVisibilityChange, false);\n\t\t\t\t\tlocation.reload();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tif (hidden === null) {\n\t\tconsole.info('Page visibility API not supported, JS session check will not work');\n\t} else {\n\t\tdocument.addEventListener(visibilityChange, handleVisibilityChange, false);\n\t}\n})();","import _ from './anime-client.js';\n\n// Click on hidden MAL checkbox so\n// that MAL id is passed\n_.on('main', 'change', '.big-check', (e) => {\n\tconst id = e.target.id;\n\tdocument.getElementById(`mal_${id}`).checked = true;\n\tdocument.getElementById(`anilist_${id}`).checked = true;\n});\n\n/**\n * On search results with an existing library entry, this shows that fact, with an edit link for the existing\n * library entry\n *\n * @param {'anime'|'manga'} type\n * @param {Object} item\n * @param isCollection\n * @returns {String}\n */\nfunction renderEditLink (type, item, isCollection = false) {\n\tif (isCollection || item.libraryEntry === null) {\n\t\treturn '';\n\t}\n\n\treturn `\n\t\t
\n\t\t\t[ Already in List ]\n\t\t
\n\t\t
\n\t\t\t\n\t\t\t\tEdit\n\t\t\t\n\t\t
\n\t\t
 
\n\t`\n}\n\n/**\n * Show the search results for a media item\n *\n * @param {'anime'|'manga'} type\n * @param {Object} data\n * @param {boolean} isCollection\n * @returns {String}\n */\nexport function renderSearchResults (type, data, isCollection = false) {\n\treturn data.map(item => {\n\t\tconst titles = item.titles.join('
');\n\t\tlet disabled = item.libraryEntry !== null ? 'disabled' : '';\n\t\tconst editLink = renderEditLink(type, item, isCollection);\n\n\t\tif (isCollection) {\n\t\t\tdisabled = '';\n\t\t}\n\n\t\treturn `\n\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t${editLink}\n\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tInfo Page\n\t\t\t\t\t\t\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t
\n\t\t`;\n\t}).join('');\n}","/**\n * Make sure properties are in an easily splittable format\n *\n * @private\n * @param {String} props\n * @param {String} [sep='.'] The default separator\n * @return {String}\n */\nfunction _normalizeProperty(props, sep = '.') {\n\t// Since we split by period, and property lookup\n\t// is the same by dot or [], replace bracket lookups\n\t// with periods\n\treturn props.replace(/\\[(.*?)]/g, sep + '$1');\n}\n\n/**\n * Tell if a nested object has a given property (or array a given index)\n * given an object such as a.b.c.d = 5, hasNestedProperty(a, 'b.c.d') will return true.\n *\n * @param {Object} object the object to get the property from\n * @param {String} property the path to the property as a string\n * @returns {boolean} true when property in object, false otherwise\n */\nexport function hasNestedProperty(object, property) {\n\tif (object && typeof object === 'object') {\n\t\tif (typeof property === 'string' && property !== '') {\n\t\t\tproperty = _normalizeProperty(property);\n\n\t\t\tlet split = property.split('.');\n\t\t\treturn split.reduce((obj, prop, idx, array) => {\n\t\t\t\tif (idx === array.length - 1) {\n\t\t\t\t\treturn !!(obj && obj.hasOwnProperty(prop));\n\t\t\t\t}\n\n\t\t\t\treturn obj && obj[prop];\n\t\t\t}, object);\n\t\t} else if (typeof property === 'number') {\n\t\t\treturn property in object;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Get the value of a deeply nested property in an object\n *\n * @param {Object} object the object to get the property\n * @param {string} property the path to the property as a string\n * @param {string} [sep='.'] The default separator to split on\n * @return {*} the value of the property\n */\nexport function getNestedProperty(object, property, sep = '.') {\n\tif (isType('string', property) && property !== '') {\n\t\t// convert numbers to dot syntax\n\t\tproperty = _normalizeProperty(property, sep);\n\t\tconst levels = property.split(sep);\n\n\t\ttry {\n\t\t\treturn levels.reduce((obj, prop) => obj[prop], object);\n\t\t} catch (e) {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Reliably get the type of the value of a variable\n *\n * @param {*} x The variable to get the type of\n * @return {string} The name of the type\n */\nexport function getType(x) {\n\t// is it an array?\n\tif (Array.isArray(x)) {\n\t\treturn 'array';\n\t}\n\n\t// Use typeof for truthy primitives\n\tif (typeof x !== 'object') {\n\t\treturn (typeof x).toLowerCase();\n\t}\n\n\tconst type = function () {\n\t\treturn Object.prototype.toString.call(this).slice(8, -1);\n\t}\n\n\t// Otherwise, strip the type out of the '[Object x]' toString value\n\treturn type.call(x).toLowerCase();\n}\n\n/**\n * Check whether the value matches the passed type name\n *\n * @param {string} type Javascript type name\n * @param {*} val The value to type check\n * @return {boolean}\n */\nexport function isType(type, val) {\n\treturn getType(val) === String(type).toLowerCase();\n}","import _ from './anime-client.js'\nimport { renderSearchResults } from './template-helpers.js'\nimport { getNestedProperty, hasNestedProperty } from \"./fns\";\n\nconst search = (query, isCollection = false) => {\n\t// Show the loader\n\t_.show('.cssload-loader');\n\n\t// Do the api search\n\treturn _.get(_.url('/anime-collection/search'), { query }, (searchResults, status) => {\n\t\tsearchResults = JSON.parse(searchResults);\n\n\t\t// Hide the loader\n\t\t_.hide('.cssload-loader');\n\n\t\t// Show the results\n\t\t_.$('#series-list')[ 0 ].innerHTML = renderSearchResults('anime', searchResults, isCollection);\n\t});\n};\n\n// Anime list search\nif (_.hasElement('.anime #search')) {\n\tlet prevRequest = null;\n\n\t_.on('#search', 'input', _.throttle(250, (e) => {\n\t\tconst query = encodeURIComponent(e.target.value);\n\t\tif (query === '') {\n\t\t\treturn;\n\t\t}\n\n\t\tif (prevRequest !== null) {\n\t\t\tprevRequest.abort();\n\t\t}\n\n\t\tprevRequest = search(query);\n\t}));\n}\n\n// Anime collection search\nif (_.hasElement('#search-anime-collection')) {\n\tlet prevRequest = null;\n\n\t_.on('#search-anime-collection', 'input', _.throttle(250, (e) => {\n\t\tconst query = encodeURIComponent(e.target.value);\n\t\tif (query === '') {\n\t\t\treturn;\n\t\t}\n\n\t\tif (prevRequest !== null) {\n\t\t\tprevRequest.abort();\n\t\t}\n\n\t\tprevRequest = search(query, true);\n\t}));\n}\n\n// Action to increment episode count\n_.on('body.anime.list', 'click', '.plus-one', (e) => {\n\tlet parentSel = _.closestParent(e.target, 'article');\n\tlet watchedCount = parseInt(_.$('.completed_number', parentSel)[ 0 ].textContent, 10) || 0;\n\tlet totalCount = parseInt(_.$('.total_number', parentSel)[ 0 ].textContent, 10);\n\tlet title = _.$('.name a', parentSel)[ 0 ].textContent;\n\n\t// Setup the update data\n\tlet data = {\n\t\tid: parentSel.dataset.kitsuId,\n\t\tanilist_id: parentSel.dataset.anilistId,\n\t\tmal_id: parentSel.dataset.malId,\n\t\tdata: {\n\t\t\tprogress: watchedCount + 1\n\t\t}\n\t};\n\n\tconst displayMessage = (type, message) => {\n\t\t_.hide('#loading-shadow');\n\t\t_.showMessage(type, `${message} ${title}`);\n\t\t_.scrollToTop();\n\t}\n\n\tconst showError = () => displayMessage('error', 'Failed to update');\n\n\t// If the episode count is 0, and incremented,\n\t// change status to currently watching\n\tif (isNaN(watchedCount) || watchedCount === 0) {\n\t\tdata.data.status = 'CURRENT';\n\t}\n\n\t// If you increment at the last episode, mark as completed\n\tif ((!isNaN(watchedCount)) && (watchedCount + 1) === totalCount) {\n\t\tdata.data.status = 'COMPLETED';\n\t}\n\n\t_.show('#loading-shadow');\n\n\t// okay, lets actually make some changes!\n\t_.ajax(_.url('/anime/increment'), {\n\t\tdata,\n\t\tdataType: 'json',\n\t\ttype: 'POST',\n\t\tsuccess: (res) => {\n\t\t\ttry {\n\t\t\t\tconst resData = JSON.parse(res);\n\n\t\t\t\t// Do a rough sanity check for weird errors\n\t\t\t\tlet updatedProgress = getNestedProperty(resData, 'data.libraryEntry.update.libraryEntry.progress');\n\t\t\t\tif (hasNestedProperty(resData, 'error') || updatedProgress !== data.data.progress) {\n\t\t\t\t\tshowError();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// We've completed the series\n\t\t\t\tif (getNestedProperty(resData, 'data.libraryEntry.update.libraryEntry.status') === 'COMPLETED') {\n\t\t\t\t\t_.hide(parentSel);\n\t\t\t\t\tdisplayMessage('success', 'Completed')\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Just a normal update\n\t\t\t\t_.$('.completed_number', parentSel)[ 0 ].textContent = ++watchedCount;\n\t\t\t\tdisplayMessage('success', 'Updated');\n\t\t\t} catch (_) {\n\t\t\t\tshowError();\n\t\t\t}\n\t\t},\n\t\terror: showError,\n\t});\n});","import _ from './anime-client.js'\nimport { renderSearchResults } from './template-helpers.js'\nimport { getNestedProperty, hasNestedProperty } from \"./fns\";\n\nconst search = (query) => {\n\t_.show('.cssload-loader');\n\treturn _.get(_.url('/manga/search'), { query }, (searchResults, status) => {\n\t\tsearchResults = JSON.parse(searchResults);\n\t\t_.hide('.cssload-loader');\n\t\t_.$('#series-list')[ 0 ].innerHTML = renderSearchResults('manga', searchResults);\n\t});\n};\n\nif (_.hasElement('.manga #search')) {\n\tlet prevRequest = null\n\n\t_.on('#search', 'input', _.throttle(250, (e) => {\n\t\tlet query = encodeURIComponent(e.target.value);\n\t\tif (query === '') {\n\t\t\treturn;\n\t\t}\n\n\t\tif (prevRequest !== null) {\n\t\t\tprevRequest.abort();\n\t\t}\n\n\t\tprevRequest = search(query);\n\t}));\n}\n\n/**\n * Javascript for editing manga, if logged in\n */\n_.on('.manga.list', 'click', '.edit-buttons button', (e) => {\n\tlet thisSel = e.target;\n\tlet parentSel = _.closestParent(e.target, 'article');\n\tlet type = thisSel.classList.contains('plus-one-chapter') ? 'chapter' : 'volume';\n\tlet completed = parseInt(_.$(`.${type}s_read`, parentSel)[ 0 ].textContent, 10) || 0;\n\tlet total = parseInt(_.$(`.${type}_count`, parentSel)[ 0 ].textContent, 10);\n\tlet title = _.$('.name', parentSel)[ 0 ].textContent;\n\n\tif (isNaN(completed)) {\n\t\tcompleted = 0;\n\t}\n\n\t// Setup the update data\n\tlet data = {\n\t\tid: parentSel.dataset.kitsuId,\n\t\tanilist_id: parentSel.dataset.anilistId,\n\t\tmal_id: parentSel.dataset.malId,\n\t\tdata: {\n\t\t\tprogress: completed\n\t\t}\n\t};\n\n\tconst displayMessage = (type, message) => {\n\t\t_.hide('#loading-shadow');\n\t\t_.showMessage(type, `${message} ${title}`);\n\t\t_.scrollToTop();\n\t}\n\n\tconst showError = () => displayMessage('error', 'Failed to update');\n\n\t// If the episode count is 0, and incremented,\n\t// change status to currently reading\n\tif (isNaN(completed) || completed === 0) {\n\t\tdata.data.status = 'CURRENT';\n\t}\n\n\t// If you increment at the last chapter, mark as completed\n\tif ((!isNaN(completed)) && (completed + 1) === total) {\n\t\tdata.data.status = 'COMPLETED';\n\t}\n\n\t// Update the total count\n\tdata.data.progress = ++completed;\n\n\t_.show('#loading-shadow');\n\n\t_.ajax(_.url('/manga/increment'), {\n\t\tdata,\n\t\tdataType: 'json',\n\t\ttype: 'POST',\n\t\tmimeType: 'application/json',\n\t\tsuccess: (res) => {\n\t\t\ttry {\n\t\t\t\tconst resData = JSON.parse(res);\n\n\t\t\t\t// Do a rough sanity check for weird errors\n\t\t\t\tlet updatedProgress = getNestedProperty(resData, 'data.libraryEntry.update.libraryEntry.progress');\n\t\t\t\tif (hasNestedProperty(resData, 'error') || updatedProgress !== data.data.progress) {\n\t\t\t\t\tshowError();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// We've completed the series\n\t\t\t\tif (getNestedProperty(resData, 'data.libraryEntry.update.libraryEntry.status') === 'COMPLETED') {\n\t\t\t\t\t_.hide(parentSel);\n\t\t\t\t\tdisplayMessage('success', 'Completed')\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Just a normal update\n\t\t\t\t_.$(`.${type}s_read`, parentSel)[ 0 ].textContent = String(completed);\n\t\t\t\tdisplayMessage('success', 'Updated');\n\n\t\t\t} catch (_) {\n\t\t\t\tshowError();\n\t\t\t}\n\t\t},\n\t\terror: showError,\n\t});\n});"],"names":[],"mappings":"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"}