User:Blaster Niceshot/wikia.js

/** * RAILWAM * * Displays wiki's WAM data in right rail and allows user to log them. * Usable in personal or sitewide JS. * * @author User:Blaster Niceshot *        Suggested by User:Demotivator * * @version DEV (3) * * @todo V3+: Dashboard, datepicker, log old data, search logged data only, Monobook, WAM graphs, inline modules, on-load hooks */

'use strict'; // Import RailWAM Library mw.loader.implement('rw.api', ['/load.php?debug=false&lang=en&mode=articles&skin=oasis&missingCallback=importArticleMissing&articles=u%3Adev%3AMediaWiki%3ARailWAM%2Flib.js&only=scripts'], {}, {}); // CSS Styles // Import CSS and I18n-js window.importArticles(           {                type: "style",                article: "u:dev:MediaWiki:RailWAM/code.css"            },            {                type: "script",                article: "u:dev:I18n-js/code.js"            }        ); // CSS vars var bodyOverflow = $('body').css('overflow') || 'auto', bodyTextColor = $('body').css('color'), dbListItems = 6, headerBgColor = $('.wds-community-header').css('background-color'), headerTextColor = $('.wds-community-header .wds-tabs__tab-label').css('color'), linkTextColor = $('a:not([class]), a[class=""]').css('color'), pageBgColor = $('.WikiaPage .WikiaPageBackground').css('background-color'), windowWidth = window.innerWidth || document.body.clientWidth; // Add CSS mw.util.addCSS(           '#railwam-log-alert { background: ' + headerBgColor + '; color: ' + headerTextColor + '; }' +            '#railwam-log-link, #railwam-close-link, .railwam-done-link { background: ' + headerTextColor.replace('rgb', 'rgba').replace(')', ', 0.12)') + '; color:' + headerTextColor + '; }' +            '#railwam-time-num, #railwam-time-type { border-bottom: 1px solid ' + headerTextColor + '; color:' + headerTextColor + '; }' +            // FAQ modal            '#railwam-modal-body { background: ' + pageBgColor + '; width: ' + (0.7 * windowWidth) + 'px; }' +            '#railwam-modal-sidebar, #railwam-modal-footer { background: ' + headerBgColor + '; color: ' + headerTextColor + '; }' +            '#railwam-modal-footer > a { color: ' + headerTextColor +  '; }' +            '#railwam-modal-title { color: ' + bodyTextColor + '; }' +            '#railwam-modal-content-banner { color: ' + headerTextColor + '; background: ' + headerBgColor.replace('rgb', 'rgba').replace(')', ', 0.7)') + '; }' + '.railwam-modal-navlink { color: ' + linkTextColor + '; }' + '.railwam-modal-sidebar-item-mobile { background: ' + headerBgColor + ' ; }' + // Database 'input[name="railwam-database"]:checked ~ .railwam-database-check { background: ' + headerBgColor + '; }' + '#railwam-database-cancel { background: ' + headerBgColor.replace('rgb', 'rgba').replace(')', ', 0.12)') + '; color: ' + headerBgColor + '; }' + '.railwam-database-check { background: ' + pageBgColor + '; box-shadow: 0 0 0 2px ' + pageBgColor + ', ' + headerBgColor + ' 0 0 0 4px; }' + '.railwam-database-disabled { background: repeating-linear-gradient(45deg, transparent, transparent 10px, ' + headerBgColor.replace('rgb', 'rgba').replace(')', ', 0.1)') + ' 10px, ' + headerBgColor.replace('rgb', 'rgba').replace(')', ', 0.1)') + ' 20px); }' + '.railwam-database-entrytable:nth-child(even) { background-color: ' + headerBgColor.replace('rgb', 'rgba').replace(')', ', .05)') + ' }' + '.railwam-database-error { background: ' + headerBgColor.replace('rgb', 'rgba').replace(')', ', 0.7)') + '; color: ' + headerTextColor + '; }' + '#railwam-database-field, #railwam-database-select, #railwam-database-custom-input { background: ' + headerBgColor.replace('rgb', 'rgba').replace(')', ', 0.05)') + '; }' + '#railwam-database-searchbtn { background: ' + headerBgColor.replace('rgb', 'rgba').replace(')', ', 0.5)') + '; color: ' + headerTextColor + '; }' + '#railwam-database-searchby, .railwam-database-radio-container { width: ' + (100 / dbListItems) +'%; }' + '.railwam-database-spinner > g > circle { stroke: ' + headerBgColor + '; }' + '#railwam-database-tablehead-container { background: ' + headerBgColor + '; color: ' + headerTextColor + '; }' );   // Initialize railWAM object    window.railWAM = window.railWAM || {};    if (typeof window.railWAM.load !== 'undefined' || mw.config.get('skin') !== 'oasis' || typeof wgIsMainPage !== 'undefined') {        // Exit function to prevent second load.        return;    }    // MediaWiki values    var mwConfig = mw.config.get([ 'wgCityId', 'wgNamespaceNumber', 'wgPageName', 'wgServer', 'wgSiteName', 'wgUserLanguage', 'wgUserName', ]);   var anonFlag = typeof mwConfig.wgUserName === 'object' ? true : false,        botFlag = false,        maxDate,        minDate,        namespaceIndex,        wamDate = (Math.floor(new Date.getTime / 1000 / 86400) * 86400) - 86400,        railWAM = $.extend({ appendAfter: ['.content-review-module'], autoLogForUsers: [], botUsers: [], logPage: 'User:' + mwConfig.wgUserName + '/WAM Log', load: true, loadOnPage: '__*__', loadOnNamespace: '__*__', lang: mwConfig.wgUserLanguage, showLogAlert: true, showToAnons: true, top5000Mode: true, }, window.railWAM),       // FAQ dropdown arrow SVG definition        faqDropdownDef = '',        // WAM logo SVG definition        wamLogoDef = '<path id="railwam-modal-logo" stroke-width="0" d="M 8.63,2.95 C 8.63,2.95 11.40,1.60 11.40,1.60 11.40,1.60 10.98,4.79 10.98,4.79 10.98,4.79 10.25,9.48 10.25,9.48 10.25,9.48 9.91,11.72 9.91,11.72 9.91,11.72 9.67,12.76 9.67,12.76 9.67,12.76 8.84,13.34 8.84,13.34 8.84,13.34 7.14,14.17 7.14,14.17 7.14,14.17 5.19,9.80 5.19,9.80 5.19,9.80 3.41,5.75 3.41,5.75 3.41,5.75 8.63,2.95 8.63,2.95 Z M 11.20,11.93 C 11.20,11.93 12.05,8.31 12.05,8.31 12.05,8.31 12.65,6.24 12.65,6.24 12.65,6.24 14.38,5.24 14.38,5.24 14.38,5.24 18.00,3.41 18.00,3.41 17.86,4.18 16.79,5.90 16.38,6.71 16.38,6.71 14.10,10.97 14.10,10.97 13.83,11.45 13.42,12.41 13.08,12.76 12.79,13.04 11.21,13.84 10.76,14.06 10.76,14.06 11.20,11.93 11.20,11.93 Z M 3.73,10.33 C 3.73,10.33 5.84,14.06 5.84,14.06 6.01,14.35 6.59,15.22 6.52,15.53 6.45,15.83 5.72,16.17 5.43,16.18 5.26,16.19 5.15,16.14 5.01,16.06 5.01,16.06 1.49,13.54 1.49,13.54 0.97,13.16 0.30,12.83 0.00,12.25 0.00,12.25 3.73,10.33 3.73,10.33 Z" />'; // Append SVG definitions to document body $('body').append(' ' + faqDropdownDef + wamLogoDef + ' '); // Ensure appendAfter is an array railWAM.appendAfter = $.isArray(railWAM.appendAfter) === true ? railWAM.appendAfter : [railWAM.appendAfter.toString]; // Check if log edits should be marked as bot edits if ($.isArray(railWAM.botUsers) === true) { $.each(railWAM.botUsers, function(i, user) {           if (railWAM.botUsers[i] === mwConfig.userName) {                botFlag = true;                return;            }        }); } else { if (railWAM.botUsers === mwConfig.userName) { botFlag = true; }   }    // Retrieve index of namespace in array in user's settings if (typeof railWAM.loadOnNamespace === 'object') { namespaceIndex = railWAM.loadOnNamespace.indexOf(mwConfig.wgNamespaceNumber); } else { namespaceIndex = railWAM.loadOnNamespace.toString.indexOf(mwConfig.wgNamespaceNumber); }   // Replace spaces with underscores and get index of page name if (typeof railWAM.loadOnPage === 'object') { $.each(railWAM.loadOnPage, function(i, page) {           railWAM.loadOnPage[i] = page.toString.replace(/ /g, '_');        }); } else { railWAM.loadOnPage = railWAM.loadOnPage.toString.replace(/ /g, '_'); }   var pageIndex = railWAM.loadOnPage.indexOf(mwConfig.wgPageName); // i18n messages mw.hook('dev.i18n').add(function(i18n) {       window.dev.i18n.loadMessages('RailWAM').done(function(i18n) { // Set messages to language in user's settings. i18n.useLang(railWAM.lang); var local = { /**                * Parses numbers more strictly than Number. *                 * @param {string} n - Number as a string *                 * @returns {number} */               parseNum: function(n) { switch (typeof n) { case 'number': return n;                       case 'string': // Ensure that value matches number pattern if ((/^(\-|\+)?([0-9]+(\.[0-9]*)?((e(\+|\-)[0-9]+)?)?|Infinity)$/).test(n) === true) { return parseFloat(n); } else { return NaN; }                           break; default: return NaN; }               },                start: function { rw.svg.insert('body'); /**                    * Load RailWAM module if                     *  RailWAM is set to load in the user's settings * the page is not the database page * the page or its namespace is specified in the user's settings */                   if (mwConfig.wgPageName.indexOf('/' + i18n.msg('database').plain.replace(/ /g, '_')) === -1 &&                         mwConfig.wgPageName.indexOf('/' + ('RailWAM Dashboard').replace(/ /g, '_')) === -1 &&                         (anonFlag === false || railWAM.showToAnons === true) &&                         (((railWAM.loadOnPage || railWAM.loadOnPage[pageIndex]) == mwConfig.wgPageName) || ((railWAM.loadOnNamespace || railWAM.loadOnNamespace[namespaceIndex]) == mwConfig.wgNamespaceNumber) || ((railWAM.loadOnPage || railWAM.loadOnPage[pageIndex]) == '__*__' && (railWAM.loadOnNamespace || railWAM.loadOnNamespace[namespaceIndex])) == '__*__')) { local.module.init; // Load database if this page is the RailWAM Database's blank special page } else if (mwConfig.wgPageName.indexOf('/' + i18n.msg('database').plain.replace(/ /g, '_')) !== -1) { local.database.init; } else if (mwConfig.wgPageName.indexOf('/' + ('RailWAM Dashboard').replace(/ /g, '_')) !== -1) { local.dashboard.init; } else if (railWAM.load === false) { // RailWAM was set to not load. console.log('RailWAM: RailWAM ' + i18n.msg('database').plain); } else if (((railWAM.loadOnPage && railWAM.loadOnPage[pageIndex]) != (mwConfig.wgPageName || '__*__')) && (railWAM.loadOnNamespace && railWAM.loadOnNamespace[namespaceIndex]) != (mwConfig.wgNamespaceNumber || '__*__')) { // This page or its namespace is not set to load RailWAM in the user's settings. console.log('RailWAM: RailWAM ' + i18n.msg('errorPage').plain); }               },            };            local.module = { /**                    * Initializes rail module. */                   init: function { if (railWAM.top5000Mode === true) { // Get score and rank data from WAM Index API rw.data.getLogged(                               {                                    log: railWAM.logPage,                                     success: local.module.getFullData(this),                                     error: local.module.getFullData(this),                                }                            ); } else if (railWAM.top5000Mode === false) { // Get score data only from Wiki Data API rw.data.getLogged(                               {                                    log: railWAM.logPage,                                     success: local.module.getMinData(this),                                     error: local.module.getMinData(this),                                }                            ); }                   },                    /**                     * Retrieves data from the WAM index and displays rail module. *                     * @param {Object} context - Context where function is executed (pass this) */                   getFullData: function(context) { function keepContext(logged) { rw.data.get(                               {                                    wikiId: mwConfig.wgCityId,                                     dateId: rw.config.maxDate,                                     days: 1,                                     logged: logged,                                     wikis: 1,                                    // Complete                                    callback: function(data) {                                        if ($.isEmptyObject(data[rw.config.maxDate]) === false) {                                            // No change - WAM has not been updated                                            if (wamDate - rw.config.maxDate > 86400) {                                                data[rw.config.maxDate - 86400] = data[rw.config.maxDate];                                            }                                            // Insert rail module context.insertModule(data, rw.config.maxDate); } else { // Get data from wiki data API context.getMinData(context)(logged); }                                   }                                }                            );                        }                        return keepContext;                    },                    /**                     * Retrieves data from wiki data and displays rail module.                     *                      * @param {Object} context - Context where function is executed (pass this)                     */                    getMinData: function(context) {                        function keepContext(logged) {                            rw.data.getLess( {                                   wikiId: mwConfig.wgCityId, logged: logged, callback: function(data) { if ($.isEmptyObject(data[wamDate]) === false) { // Insert rail module context.insertModule(data, wamDate); } else { local.module.error; }                                   },                                    // Error error: function { local.module.error; }                               }                            );                        }                        return keepContext;                    },                    /**                     * Adds the RailWAM module to the right rail.                     *                      * @param {Object} data - WAM data                     * @param {number} dateId - Date of data in seconds                     *                      * @returns {void}                     */                    insertModule: function(data, dateId) {                        data[dateId - 86400] = $.extend({}, {                                                           vertical_wam_rank: null, wam: null, wam_rank: null, },                                                       data[dateId - 86400]);                        // Ensure values are numerical                        $.each(data, function(id, obj) { $.each(obj,                                    function(key, val) {                                        if (key === 'wam' && (isNaN(local.parseNum(val)) === true || local.parseNum(val) > 100 || local.parseNum(val) < 0)) {                                            data[id][key] = 'N/A';                                        } else if (key === 'wam_rank' && (isNaN(local.parseNum(val)) === true || local.parseNum(val) > 5000 || local.parseNum(val) < 0)) {                                            data[id][key] = 'N/A';                                        }                                    }                                ); }                       );                        // SVG definition of WAM logo                        var wamLogoSvg = ' ',                            // HTML of database link                            databaseLink = '' + i18n.msg('wamPage').plain + '' + i18n.msg('wamDatabase').plain + '',                            // HTML of rank element if rank data is available                            rankElm = isNaN(data[dateId].wam_rank) === false ? '   ' + i18n.msg('rank').plain + ' ' + data[dateId].wam_rank + '   +/- ' + i18n.msg('unknown').plain + '   ' : '', module = '' + wamLogoSvg + i18n.msg('todayTitle').plain + '   ' + i18n.msg('score').plain + ' ' + data[dateId].wam + '   +/- ' + i18n.msg('unknown').plain + '   ' + rankElm + ' ' + i18n.msg('yesterdayNotLogged').plain +' ' + i18n.msg('faq').plain + '' + databaseLink + ' ' + i18n.msg('poweredBy').plain + ' RailWAM ', appendElms = ''; // Append RailWAM module after these modules $.each(railWAM.appendAfter, function(i, elm) {                           if (railWAM.appendAfter === i++) {                                appendElms += elm + ', ';                            } else {                                // Always append after ads                                appendElms += elm + ', #top-right-boxad-wrapper, #NATIVE_TABOOLA_RAIL';                            }                        }); // Bottommost specified element var appendAfter = $(appendElms).last; // Add module to right rail if (appendAfter.length > 0) { // Append after specified modules $(appendAfter).after(module); } else { // Prepend to right rail - no ads present $('#WikiaRail').prepend(module); }                       // Border CSS mw.util.addCSS('#railwam-rank-container { border-left: 1px solid ' + $('.WikiaRail .rail-module h2').css('border-bottom-color') + '; }'); // Make FAQ link clickable $('#railwam-faq').click(                           function{                                local.faq.display;                            }                        ); // Calculate and display changes in score and rank var scoreDiff = rw.math.diff(data[dateId].wam, data[dateId - 86400].wam), scorePercent = ((Math.abs(local.parseNum(data[dateId].wam) - local.parseNum(data[dateId - 86400].wam)) / local.parseNum(data[dateId - 86400].wam)) * 100).toFixed(1) + '%'; if (local.parseNum(data[dateId - 86400].wam) === 0) { if (local.parseNum(data[dateId].wam === 0)) { scorePercent = '0.0%'; } else { scorePercent = 'N/A%'; }                       }                        var scoreDiffElm = ' ' + scoreDiff + ' ' + scorePercent + ' '; if (typeof scoreDiff === 'string') { $('#railwam-score-difference').html(scoreDiffElm); }                       // Move arrow var scoreArrow = $('#railwam-score-difference .railwam-arrow'); scoreArrow.remove; $('#railwam-score-difference > div').before(scoreArrow); var rankDiff = rw.math.diff(data[dateId - 86400].wam_rank, data[dateId].wam_rank), rankPercent = ((Math.abs(local.parseNum(data[dateId].wam_rank) - local.parseNum(data[dateId - 86400].wam_rank)) / local.parseNum(data[dateId - 86400].wam_rank)) * 100).toFixed(1) + '%'; if (local.parseNum(data[dateId - 86400].wam_rank) === 0) { if (local.parseNum(data[dateId].wam_rank === 0)) { rankPercent = '0.0%'; } else { rankPercent = 'N/A%'; }                       }                        var rankDiffElm = ' ' + rankDiff + ' ' + rankPercent; if (typeof scoreDiff === 'string' || typeof rankDiff === 'string') { $('#railwam-not-logged').css('display', 'none'); $('#railwam-rank-difference').html(rankDiffElm); } else if (isNaN(local.parseNum(data[dateId].wam_rank)) === true || isNaN(local.parseNum(data[dateId - 86400].wam_rank)) === true) { $('#railwam-not-logged').css('display', 'block'); }                       // Move arrow var rankArrow = $('#railwam-rank-difference .railwam-arrow'); rankArrow.remove; $('#railwam-rank-difference > div').before(rankArrow); var showAlert = data[dateId].logged === false ? true : false; if (railWAM.autoLogForUsers.toString.indexOf(mwConfig.wgUserName) !== -1 && showAlert === true) { // Auto log WAM data rw.data.log(                               {                                    data: data,                                     log: railWAM.logPage,                                     summary: 'RailWAM: ' + i18n.msg('logSummary').plain,                                     types: ['wiki_id', 'wam', 'wam_rank', 'vertical_wam_rank'],                                    bot: botFlag,                                }                            ); } else if (railWAM.showLogAlert === true && showAlert === true) { data[dateId - 86400] = null; $.each(data,                                function(key, wamObj) {                                    if (wamObj !== null) {                                        $.each(wamObj, function(type, val) { if (val === 'N/A') { data[key][type] = null; }                                           }                                        );                                        if ($.isEmptyObject(data[key]) === true) {                                            data[key] = null;                                        }                                    }                                }                            ); // Show log alert if it is enabled in user's settings and data is not logged local.module.logAlert(data); }                       // Module ready mw.hook('rw.app.moduleAdded').fire; },                   /**                     * Shows alert with buttons to log WAM data. *                     * @param {number} data - WAM data *                     * @returns {void} */                   logAlert: function(data) { // Check if cookie to prevent alert is set if (document.cookie.replace(/(?:(?:^|.*;\s*)railwamShowAlert\s*\=\s*([^;]*).*$)|^.*$/, "$1") != "false") { // HTML of alert $('#railwam-rail-mod').before(' ' + i18n.msg('notLogged').plain + ' ' + i18n.msg('notLoggedWarning').plain + ' ' + i18n.msg('logBtn').plain + '' + i18n.msg('closeBtn').plain + '</a>  '); // Make log link clickable and show done message on click $('#railwam-log-link').click(function {                               rw.data.log( {                                       data: data, log: railWAM.logPage, summary: 'RailWAM: ' + i18n.msg('logSummary').plain, types: ['wiki_id', 'wam', 'wam_rank', 'vertical_wam_rank'], bot: botFlag, }                               );                                $('#railwam-notlogged-text').html(i18n.msg('scoreLogged').plain + ' ' + i18n.msg('doneBtn').plain + '</a>');                            }); // Allow user to set cookie to hide alert upon clicking close button $('#railwam-close-link').click(function {                               // Cookie form HTML                                $('#railwam-notlogged-text').html(i18n.msg('dontShow').plain + ' <input id="railwam-time-num" type="text" placeholder="#"><select id="railwam-time-type"> ' + i18n.msg('hours').plain + ' <option selected="selected" value="day">' + i18n.msg('days').plain + '  ' + i18n.msg('weeks').plain + '  ' + i18n.msg('years').plain + '  ' + i18n.msg('cookieWarning').plain + ' ' + i18n.msg('doneBtn').plain + '</a>');                            }); // Close alert $('#railwam-log-alert').on('click', '.railwam-done-link', function {                               local.module.hideAlert(local.parseNum($('#railwam-time-num').val), $('#railwam-time-type').val);                                $('#railwam-log-alert').remove;                            }); }                       // Alert ready mw.hook('rw.app.alertAdded').fire; },                   /**                     * Creates a cookie in user's browser to hide log alert. *                     * @param {number} num - Number inputted in cookie form by user (see logAlert function) * @param {string} type - Hours, days, months, or years *                     * @returns {void} */                   hideAlert: function(num, type) { if (typeof num === 'number' && typeof type === 'string') { // Calculate time in seconds based on type switch(type) { case 'hour': num *= 3600; break; case 'day': num *= 3600 * 24; break; case 'week': num *= 3600 * 24 * 7; break; case 'year': num *= 3600 * 24 * 365; }                           if (num > 0) { // Create cookie for time in seconds document.cookie = 'railwamShowAlert=false; domain=' + window.location.hostname + '; max-age=' + num; }                       }                        // Alert hidden mw.hook('rw.app.alertHidden').fire; },                   /**                     * Creates module with error message in right rail. *                     * @returns {void} */                   error: function { if ($('railwam-error-mod').length < 1) { var module = '<section class="rail-module" id="railwam-error-mod"> ' + i18n.msg('onErrorHeading').plain + ' ' + i18n.msg('onError', '' + i18n.msg('talkLinkText').plain + '</a>').plain + ' ', appendElms = ''; // Append RailWAM module after these modules $.each(railWAM.appendAfter, function(i, elm) {                               if (railWAM.appendAfter === i++) {                                    appendElms += elm + ', ';                                } else {                                    // Always append after ads                                    appendElms += elm + ', #top-right-boxad-wrapper, #NATIVE_TABOOLA_RAIL';                                }                            }); // Bottommost specified element var appendAfter = $(appendElms).last; // Add module to right rail if (appendAfter.length > 0) { // Append after specified modules $(appendAfter).after(module); } else { // Prepend to right rail - no ads present $('#WikiaRail').prepend(module); }                       }                        // Error message added mw.hook('rw.app.errorAdded').fire; }               };            local.database = { /**                    * Initializes WAM database. */                   init: function { rw.data.getLogged(                           {                                log: railWAM.logPage,                                 callback: function(logged) {                                    // Get date of wiki creation                                    var dateCreated,                                        yearMin,                                        monthMin,                                        dayMin,                                        dateId = rw.config.maxDate;                                    // Use date of main page creation as date of wiki creation                                    $.get(mwConfig.wgServer + '/api.php?action=query&format=json&prop=revisions&titles=Main+Page&rvprop=timestamp&rvlimit=1&rvdir=newer')                                        .done( function(history) { var pageId = Object.keys(history.query.pages)[0], // Isolate date and put numbers into an array dateProp = history.query.pages[pageId].revisions[0].timestamp.split('T')[0], dateArray = dateProp.split('-'); // Determine maximum and minimum dates for search yearMin = dateArray[0]; monthMin = local.parseNum(dateArray[1]) - 1; dayMin = dateArray[2]; dateCreated = Date.UTC(yearMin, monthMin, dayMin) / 1000 > rw.config.minDate ? Date.UTC(yearMin, monthMin, dayMin) / 1000 : rw.config.minDate; maxDate = local.database.formatDate(rw.config.maxDate); minDate = local.database.formatDate(dateCreated); }                                       );                                    // Change title of page                                    $('title').text('RailWAM: ' + i18n.msg('databaseAlt').plain);                                    $('.page-header__title').text('RailWAM: ' + i18n.msg('databaseAlt').plain);                                    // Add main HTML                                    $('#mw-content-text').html(i18n.msg('databaseWelcome').plain + mwConfig.wgSiteName + '. ' + i18n.msg('databaseWelcomeFaq', '' + i18n.msg('databaseFaqLinkText').plain + '</a>').plain + ' ' + i18n.msg('lastAvailable').plain + local.database.formatDate(rw.config.maxDate) + ' (UTC)  <input id="railwam-database-field" type="text" placeholder="# ' + i18n.msg('ofDays').plain + '"><select id="railwam-database-select" class="railwam-database-hidden"> ' + i18n.msg('withinLast').plain + ' 7 ' + i18n.msg('days').plain + '  ' + i18n.msg('withinLast').plain + ' 30 ' + i18n.msg('days').plain + '  ' + i18n.msg('withinLast').plain + ' 60 ' + i18n.msg('days').plain + '  ' + i18n.msg('customRange').plain + '  <input id="railwam-database-custom-input" class="railwam-database-hidden" type="text" placeholder="days"> ' + i18n.msg('search').plain + '   <ul id="railwam-database-radio"><li id="railwam-database-searchby">' + i18n.msg('searchBy').plain + '</li><li class="railwam-database-radio-container"> <input type="radio" name="railwam-database" value="list" id="railwam-database-list" checked><label for="railwam-database-list">' + i18n.msg('list').plain + '   </li><li class="railwam-database-radio-container"> <input type="radio" name="railwam-database" value="date" id="railwam-database-date"><label for="railwam-database-date">' + i18n.msg('date').plain + '   </li><li class="railwam-database-radio-container"> <input type="radio" name="railwam-database" value="score" id="railwam-database-score"><label for="railwam-database-score">' + i18n.msg('score').plain + '   </li><li class="railwam-database-radio-container"> <input type="radio" name="railwam-database" value="rank" id="railwam-database-rank"><label for="railwam-database-rank">' + i18n.msg('rank').plain + '   </li><li class="railwam-database-radio-container"> <input type="radio" name="railwam-database" value="vertrank" id="railwam-database-vertrank"><label for="railwam-database-vertrank">' + i18n.msg('vertRank').plain + '   </li></ul>  ' + i18n.msg('date').plain + ' ' + i18n.msg('score').plain + ' ' + i18n.msg('rank').plain + ' ' + i18n.msg('vertRank').plain + '  <svg class="railwam-database-spinner" width="25" viewBox="-15 -15 30 30" xmlns="http://www.w3.org/2000/svg"> <g> <circle fill="none" stroke-width="1" stroke-linecap="round" r="10"> </g>     '); // Make FAQ link clickable $('#railwam-database-faq').click(function {                                       local.faq.display;                                    }); // Radio input change $('input[name="railwam-database"]').change(function {                                       // Clear input field                                        $('#railwam-database-field').val('');                                        local.database.searchUnready;                                        // Change placeholders                                        switch ($('input[name="railwam-database"]:checked').val) {                                            case 'date':                                                $('#railwam-database-field').attr('placeholder', 'dd/mm/yyyy');                                                break;                                            case 'score':                                                $('#railwam-database-field').attr('placeholder', i18n.msg('score').plain);                                                break; case 'rank': $('#railwam-database-field').attr('placeholder', i18n.msg('rank').plain); break; case 'vertrank': $('#railwam-database-field').attr('placeholder', i18n.msg('vertRank').plain); break; case 'list': $('#railwam-database-field').attr('placeholder', '# ' + i18n.msg('ofDays').plain); break; }                                       // Don't show Within last... on date or last days types var dontShowWithin = ['date', 'list']; if ($.inArray($('input[name="railwam-database"]:checked').val, dontShowWithin) === -1 && $("#railwam-database-select").hasClass('railwam-database-hidden') === true) { // Add "Within last..." on non-date and non-last days types $('#railwam-database-select').animate({width:'toggle'}, 300); $('#railwam-database-select').removeClass('railwam-database-hidden'); $('#railwam-database-field').css('width', '70%'); if ($('#railwam-database-select').val === 'custom' && $('#railwam-database-custom-input').hasClass('railwam-database-hidden') === true) { $('#railwam-database-custom-input').animate({width: 'toggle'}, 200); $('#railwam-database-custom-input').removeClass('railwam-database-hidden'); }                                       } else if ($.inArray($('input[name="railwam-database"]:checked').val, dontShowWithin) !== -1  && $("#railwam-database-select").hasClass('railwam-database-hidden') === false) { // Remove "Within last..." on date and last days types $('#railwam-database-select').animate({width:'toggle'}, 300); $('#railwam-database-select').addClass('railwam-database-hidden'); $('#railwam-database-field').css({'width':'90%'}); if ($('#railwam-database-custom-input').hasClass('railwam-database-hidden') === false) { $('#railwam-database-custom-input').animate({width: 'toggle'}, 200); $('#railwam-database-custom-input').addClass('railwam-database-hidden'); }                                       }                                    });                                    // Change of Within last...                                    $('#railwam-database-select').change(function { if ($(this).val === 'custom' && $("#railwam-database-custom-input").hasClass('railwam-database-hidden') === true) { // Show custom input box $('#railwam-database-custom-input').animate({width:'toggle'}, 200); $('#railwam-database-custom-input').removeClass('railwam-database-hidden'); $('#railwam-database-field, #railwam-database-select').addClass('railwam-database-custom-shown'); $('#railwam-database-select option[value="custom"]').text(i18n.msg('withinLast').plain + '...'); } else if ($(this).val !== 'custom' && $("#railwam-database-custom-input").hasClass('railwam-database-hidden') === false) { // Hide custom input box $('#railwam-database-custom-input').animate({width:'toggle'}, 200); $('#railwam-database-custom-input').addClass('railwam-database-hidden'); $('#railwam-database-field, #railwam-database-select').addClass('railwam-database-custom-hidden'); $('#railwam-database-select option[value="custom"]').text(i18n.msg('customRange').plain); }                                   });                                    // Click search on enter                                    $(document).keydown(function(evt) { if (evt.key.trim === 'Enter') { $('#railwam-database-searchbtn').trigger('click'); }                                    });                                    // Backspace, Enter, Shift, Control, Delete, Arrow, and Slash keys                                    var acceptedSpecialChars = ['Backspace', 'Enter', 'Shift', 'Control', 'Delete', 'ArrowLeft', 'ArrowUp', 'ArrowRight', 'ArrowDown', '/'],                                        // Backspace and Delete                                        deleteChars = ['Backspace', 'Delate'],                                        // Arrows accepted when input has reached maximum length                                        acceptedMaxChars = deleteChars.concat('ArrowLeft', ['ArrowUp', 'ArrowRight', 'ArrowDown']);                                    $('#railwam-database-field').keydown(function(evt) { // Enter behavior already defined if (evt.key.trim === 'Enter') { return; }                                       if ($.inArray(evt.key.trim, acceptedSpecialChars) === -1) { // Score type allows period (.) if (($('input[name="railwam-database"]:checked').val !== 'score' || ($('input[name="railwam-database"]:checked').val === 'score' && evt.key.trim !== '.')) &&                                                evt.key.trim !== '/' ||                                                ($('input[name="railwam-database"]:checked').val === 'date' && $(this).val.split('/').length - 1 < 2)) { // Numbers only if (evt.key.trim.match(/[^0-9]/g)) { evt.preventDefault; local.database.error(i18n.msg('errorGreaterThanZero').plain, 'char'); }                                                // REMOVED: Enter slash after 2nd and 4th characters on date type }                                       }                                        // Different behaviors based on radio input value switch ($('input[name="railwam-database"]:checked').val) { // Date checked case 'date': // Maximum length: 10 if ($(this).val.length === 10 && $.inArray(evt.key.trim, acceptedMaxChars) === -1) { evt.preventDefault; local.database.error(i18n.msg('errorMaxChars').plain, 'maxLengthDate'); } else if ($(this).val.split('/').length === 3 &&                                                            (($(this).val.split('/')[local.database.cursorSect($(this).val, '/')].length > 1 &&                                                             ($.inArray(evt.key.trim, deleteChars) !== -1 || evt.key.trim === '/')) || ($.inArray(evt.key.trim, deleteChars) === -1 && evt.key.trim !== '/')) &&                                                            $(this).val.length <= 10) { local.database.searchReady(logged, dateId, dateCreated); } else { local.database.searchUnready; }                                               break; // Score checked case 'score': // Maximum length: 7 if ($(this).val.length === 7 && $.inArray(evt.key.trim, acceptedMaxChars) === -1) { evt.preventDefault; local.database.error(i18n.msg('errorMaxChars').plain, 'maxLengthScore'); } else if (($.inArray(evt.key.trim, deleteChars) === -1 && $(this).val.split('.').length - 1 === 0 || ($(this).val.length > 1 && $.inArray(evt.key.trim, deleteChars) !== -1 &&                                                            $(this).val.split('.').length - 1 <= 2)) &&                                                         (($(this).val.split('.')[0].length > 0 &&                                                             ($.inArray(evt.key.trim, deleteChars) !== -1 || evt.key.trim === '.')) || ($.inArray(evt.key.trim, deleteChars) === -1 && evt.key.trim !== '.')) &&                                                        evt.key.trim !== '/' && $(this).val.split('/').length - 1 === 0) { local.database.searchReady(logged, dateId, dateCreated); } else { local.database.searchUnready; }                                               break; // Rank or Vertical Rank checked case 'rank': case 'vertrank': // Maximum length: 4 if ($(this).val.length === 4 && $.inArray(evt.key.trim, acceptedMaxChars) === -1) { evt.preventDefault; local.database.error(i18n.msg('errorMaxChars').plain, 'maxLengthRank'); } else if (($.inArray(evt.key.trim, deleteChars) === -1 || ($(this).val.length > 1 &&                                                                $.inArray(evt.key.trim, deleteChars) !== -1)) &&                                                             evt.key.trim !== '/' &&                                                             $(this).val.split('/').length - 1 === 0) { local.database.searchReady(logged, dateId, dateCreated); } else { local.database.searchUnready; }                                               break; // Last ... days checked case 'list': // Minimum length: 1 if ((($(this).val.length === 0 &&                                                    $.inArray(evt.key.trim, deleteChars) !== -1) || ($(this).val.length === 1 && $.inArray(evt.key.trim, deleteChars) !== -1)) &&                                                evt.key.trim !== '/' &&                                                 $(this).val.split('/').length - 1 === 0) { local.database.searchUnready; } else { local.database.searchReady(logged, dateId, dateCreated); }                                               break; }                                   });                                }                            }                        );                    },                    /**                     * Checks if retrieved data meets user's search. *                     * @param {string} input - Search input * @param {Object} data - WAM data * @param {number} dateId - Date of data in seconds *                     * @returns {boolean} Show (true) or do not show (false) */                   checkEntry: function(input, data, dateId) { var wamVal; switch ($('input[name="railwam-database"]:checked').val) { case 'date': return true; case 'list': if (dateId > (rw.config.maxDate - ((local.parseNum(input)) * 86400)) && dateId <= rw.config.maxDate) { return true; } else { return false; }                               break; case 'score': wamVal = data[dateId].wam; break; case 'rank': wamVal = data[dateId].wam_rank; break; case 'vertrank': wamVal = data[dateId].vertical_wam_rank; break; }                       // Add period to number if none is present if (input.indexOf('.') === -1) { input += '.'; }                       // Get number of decimal places in value var placeholders = input.toString.split('.')[1].length; input = local.parseNum(input); var maxVal = Math.round((input + (1 / (Math.pow(10, placeholders)))) * Math.pow(10, placeholders)) / Math.pow(10, placeholders); if (wamVal >= input && wamVal < maxVal ) { return true; } else { return false; }                   },                    /**                     * Creates an HTML timer. *                     * @param {Object} time - Use the following properties: * d - days * h - hours * m - minutes * s - seconds *                     * @returns {string} HTML of timer */                   createTimer: function(time) { var days = time.d > 0 ? time.d + ' ' + i18n.msg('days').plain + ', ' : '', hours = time.h > 0 ? time.h + ' ' + i18n.msg('hours').plain + ', ' : '', min = time.m > 0 ? time.m + ' ' + i18n.msg('minutes').plain + ', ' : ''; return days + hours + min + time.s + ' ' + i18n.msg('seconds').plain; },                   /**                     * Returns the "section" of the cursor in relation to a character. *                     * @param {string} str - selected string * @param {string} char - character defining sections *                     * @returns {number} */                   cursorSect: function(str, char) { var cursorPos = str.selectionStart; return str .slice(0, cursorPos) .split(char).length - 1; },                   /**                     * Searches for and displays WAM data for a single date. *                     * @param {Object} logged - Logged WAM data * @param {string} input - dd/mm/yyyy date input * @param {function} callback - Executed after date is retrieved *                     * @returns {void} */                   dateSearch: function(logged, input, callback) { var dateSplit = input.split('/'); if (dateSplit[2].length === 2) { dateSplit[2] = '20' + dateSplit[2].toString; }                       var id = Date.UTC(dateSplit[2], (local.parseNum(dateSplit[1]) - 1), dateSplit[0]) / 1000; rw.data.get(                           {                                wikiId: mwConfig.wgCityId,                                 dateId: id,                                 days: 1,                                 logged: logged,                                wikis: 1,                                // Callback                                callback: function(data, dateId) {                                    callback(data, dateId);                                }                            }                        ); },                   /**                     * Displays an error upon invalid user input into database. *                     * @param {string} text - Error text to display to user. * @param {string} type - Type of error; used to prevent duplicate errors. *                     * @returns {void} */                   error: function(text, type) { if ($('#railwam-database-error-' + type).length === 0) { $('<div class="railwam-database-error" id="railwam-database-error-' + type + '">' + text + ' ') .prependTo($('#railwam-database-errors')) .slideDown(500) .delay(5000) .fadeOut(200,                                                function {                                                    $(this).remove;                                                }                            ); }                   },                    /**                     * Formats numeric date id into string. *                     * @param {number} dateId - Date of data in seconds */                   formatDate: function(dateId) { if (Number.isNaN(local.parseNum(dateId)) === false) { var dateObj = new Date(dateId * 1000), monthName = (function(monthNum) {                                               switch (monthNum) {                                                    case 0:                                                        return i18n.msg('jan').plain;                                                    case 1:                                                        return i18n.msg('feb').plain;                                                    case 2:                                                        return i18n.msg('mar').plain;                                                    case 3:                                                        return i18n.msg('apr').plain;                                                    case 4:                                                        return i18n.msg('may').plain;                                                    case 5: return i18n.msg('june').plain; case 6: return i18n.msg('july').plain; case 7: return i18n.msg('aug').plain; case 8: return i18n.msg('sept').plain; case 9: return i18n.msg('oct').plain; case 10: return i18n.msg('nov').plain; case 11: return i18n.msg('dec').plain; }                                               }) (dateObj.getUTCMonth),                            displayDate = monthName + ' ' + dateObj.getUTCDate + ', ' + dateObj.getUTCFullYear;                             return displayDate;                        } else {                            mw.log('RailWAM: "str.formatDate" was aborted. "dateId" must be a number. Illegal value: ' + dateId);                           return '';                        }                    },                    /**                     * Adds a new database entry.                     *                      * @param {Object} data - WAM data                     * @param {number} dateId - Date of data in seconds                     *                      * @returns {void}                     */                    newEntry: function(data, dateId) {                        data[dateId] = $.extend( {                                       wam: null, wam_rank: null, vertical_wam_rank: null },                                   data[dateId] );                       data[dateId - 86400] = $.extend( {                                       wam: null, wam_rank: null, vertical_wam_rank: null },                                   data[dateId - 86400] );                       var displayDate = local.database.formatDate(dateId),                            score = isNaN(local.parseNum(data[dateId].wam)) === false ? data[dateId].wam : i18n.msg('unknown').plain,                            scoreDiff = rw.math.diff(data[dateId].wam, data[dateId - 86400].wam) || '+/- ' + i18n.msg('unknown').plain,                            rank = isNaN(local.parseNum(data[dateId].wam_rank)) === false ? data[dateId].wam_rank : i18n.msg('unknown').plain,                            rankDiff = rw.math.diff(data[dateId - 86400].wam_rank, data[dateId].wam_rank) || '+/- ' + i18n.msg('unknown').plain,                            vertRank = isNaN(local.parseNum(data[dateId].vertical_wam_rank)) === false ? data[dateId].vertical_wam_rank : i18n.msg('unknown').plain,                            vertRankDiff = rw.math.diff(data[dateId - 86400].vertical_wam_rank, data[dateId].vertical_wam_rank) || '+/- ' + i18n.msg('unknown').plain; if (score !== i18n.msg('unknown').plain || rank !== i18n.msg('unknown').plain || vertRank !== i18n.msg('unknown').plain) { // HTML $('#railwam-database-entries').append('<div class="railwam-database-entrytable" id="railwam-entrytable-' + dateId + '" railwam-date-id="' + dateId + '"> ' + displayDate + ' ' + score + ' ' + scoreDiff + ' ' + rank + ' ' + rankDiff + '  ' + vertRank + ' ' + vertRankDiff + '   '); // Sort database entries based on date $('#railwam-database-entries').find('.railwam-database-entrytable').sort(function (a, b) {                               return $(b).attr('railwam-date-id') - $(a).attr('railwam-date-id');                            }).appendTo($('#railwam-database-entries')); }                   },                    /**                     * Makes database search button clickable. *                     * @param {Object} logged - Logged WAM data * @param {number} dateId - Date of data in seconds * @param {number} dateCreated - Date of wiki creation in seconds *                     * @returns {void} */                   searchReady: function(logged, dateId, dateCreated) { $('#railwam-database-searchbtn').css({'background': headerBgColor, 'cursor': 'pointer'}); $('#railwam-database-searchbtn') .off('click') .click(                                   function {                                        var selectDays = $('#railwam-database-select').val === 'custom' ? local.parseNum($('#railwam-database-custom-input').val) : local.parseNum($('#railwam-database-select').val),                                            input = $('#railwam-database-field').val.trim;                                        if (dateId - (selectDays * 86400) - dateCreated <= 0 || selectDays <= 0) {                                            local.database.error(i18n.msg('errorDateBetween').plain + ' ' + minDate + ' ' + i18n.msg('and').plain + ' ' + maxDate + '.', 'maxDate');                                            return;                                        }                                        $('#railwam-database-field').attr('readonly', true);                                        $('input[name="railwam-database"]:not(:checked)').attr('disabled', true); $('#railwam-database-select').attr('disabled', true); $('#railwam-database-custom-input').attr('readonly', true); $('#railwam-database-input-container').addClass('railwam-database-disabled'); local.database.searchUnready; if (local.database.validate(input, dateId, dateCreated) === true) { switch ($('input[name="railwam-database"]:checked').val) { case 'list': rw.data.get(                                                       {                                                            wikiId: mwConfig.wgCityId,                                                             dateId: dateId,                                                             days: local.parseNum(input),                                                             logged: logged,                                                             wikis: 1,                                                            // Complete                                                            callback: function(data) {                                                                $.each(data, function(id, dayData) { if (typeof dayData === 'object' && local.database.checkEntry(input, data, id) === true) { local.database.newEntry(data, id); }                                                                   }                                                                );                                                                local.database.timeLeft(0);                                                                $.extend(logged, data);                                                            },                                                            // Done                                                            success: function(data, dateId, requests) {                                                                local.database.timeLeft(requests * 10);                                                            },                                                            // Error                                                            error: function(data, dateId, requests) { local.database.timeLeft(requests * 10); }                                                       }                                                    );                                                    break;                                                case 'date':                                                    local.database.dateSearch(logged, input, function(data, dateId) { local.database.newEntry(data, dateId); local.database.timeLeft(0); }                                                   );                                                    break;                                                case 'score':                                                    rw.data.get( {                                                           wikiId: mwConfig.wgCityId, dateId: dateId, days: selectDays, logged: logged, wikis: 1, // Complete callback: function(data) { $.each(data,                                                                    function(id, dayData) {                                                                        if (typeof dayData === 'object' && typeof data[id - 86400] === 'object' && local.database.checkEntry(input, data, id) === true) {                                                                            local.database.newEntry(data, id);                                                                        }                                                                    }                                                                ); local.database.timeLeft(0); $.extend(logged, data); },                                                           // Done success: function(data, dateId, requests) { local.database.timeLeft(requests * 10); },                                                           // Error error: function(data, dateId, requests) { local.database.timeLeft(requests * 10); }                                                       }                                                    );                                                    break;                                                case 'rank':                                                case 'vertrank':                                                    rw.data.get( {                                                           wikiId: mwConfig.wgCityId, dateId: dateId, days: selectDays, logged: logged, wikis: 1, // Complete callback: function(data) { $.each(data,                                                                    function(id, dayData) {                                                                        if (typeof dayData === 'object' && local.database.checkEntry(input, data, id) === true) {                                                                            local.database.newEntry(data, id);                                                                        }                                                                    }                                                                ); local.database.timeLeft(0); $.extend(logged, data); },                                                           // Done success: function(data, dateId, requests) { local.database.timeLeft(requests * 10); },                                                           // Error error: function(data, dateId, requests) { local.database.timeLeft(requests * 10); }                                                       }                                                    );                                                    break;                                            }                                        }                                    }                                ); },                   /**                     * Makes database search button not clickable. *                     * @returns {void} */                   searchUnready: function { $('#railwam-database-searchbtn').css({'background': headerBgColor.replace('rgb', 'rgba').replace(')', ', 0.5)'), 'cursor':'auto'}); $('#railwam-database-searchbtn') .off('click'); },                   /**                     * Shows percentage indicator on database search and removes it when finished. *                     * @param {number} sec - Seconds remaining in search *                     * @returns {void} */                   timeLeft: function(sec) { if (sec === 0) { // Done $('#railwam-database-loading-text').empty; $('#railwam-database-loading').css('display', 'none'); // No matching entries if ($('.railwam-database-entrytable').length < 1) { $('#railwam-database-noentry').css('display', 'block'); $('#railwam-database-noentry-text').text(i18n.msg('noEntry').plain); } else { $('#railwam-database-noentry').css('display', 'none'); }                           $('#railwam-database-field').removeAttr('readonly'); $('input[name="railwam-database"]:not(:checked)').attr('disabled', false); $('#railwam-database-select').attr('disabled', false); $('#railwam-database-custom-input').attr('readonly', false); $('#railwam-database-input-container').removeClass('railwam-database-disabled'); } else { // Show loading text $('#railwam-database-loading-text').text(local.database.createTimer(rw.math.convertTime(sec))); if ($('#railwam-database-cancel').length < 1) { $('#railwam-database-loading').append(' ' + i18n.msg('cancel').plain + ' '); $('#railwam-database-cancel') .click(                                       function {                                            rw.data.cancel('get');                                            $('#railwam-database-loading-text').text(i18n.msg('duringCancel').plain);                                            $(this).remove;                                        }                                    ); }                           $('#railwam-database-loading').css('display', 'block'); $('#railwam-database-noentry').css('display', 'none'); }                   },                    /**                     * Validates user's database search input. *                     * @param {string} input - Search input * @param {number} dateId - Date of data in seconds * @param {number} dateCreated - Date of wiki creation in seconds *                     * @returns {void} */                   validate: function(input, dateId, dateCreated) { $('.railwam-database-entrytable').remove; switch ($('input[name="railwam-database"]:checked').val) { case 'list': if (dateId - (local.parseNum(input) * 86400) - dateCreated >= 0 && local.parseNum(input) > 0) { return true; } else { local.database.error(i18n.msg('errorDateBetween').plain + ' ' + minDate + ' ' + i18n.msg('and').plain + ' ' + maxDate + '.', 'maxDate'); $('#railwam-database-field').removeAttr('readonly'); $('input[name="railwam-database"]:not(:checked)').attr('disabled', false); $('#railwam-database-select').attr('disabled', false); $('#railwam-database-custom-input').attr('readonly', false); $('#railwam-database-input-container').removeClass('railwam-database-disabled'); return false; }                               break; case 'date': var dateSplit = input.split('/'); if (dateSplit[2].length === 2) { dateSplit[2] = '20' + dateSplit[2].toString; }                               var inputSec = Date.UTC(dateSplit[2], (dateSplit[1] - 1), dateSplit[0]) / 1000; if (inputSec <= dateId && inputSec >= dateCreated) { return true; } else { local.database.error(i18n.msg('errorDateBetween').plain + ' ' + minDate + ' ' + i18n.msg('and').plain + ' ' + maxDate + '.', 'maxDate'); $('#railwam-database-field').removeAttr('readonly'); $('input[name="railwam-database"]:not(:checked)').attr('disabled', false); $('#railwam-database-select').attr('disabled', false); $('#railwam-database-custom-input').attr('readonly', false); $('#railwam-database-input-container').removeClass('railwam-database-disabled'); return false; }                               break; case 'score': if (local.parseNum(input) >= 0 && local.parseNum(input) < 100) { if ($('#railwam-database-select').val === 'custom') { if (local.parseNum($('#railwam-database-custom-input').val) > 0) { return true; } else { return false; }                                   } else if (local.parseNum($('#railwam-database-select').val) > 0) { return true; } else { return false; }                               } else { local.database.error(i18n.msg('errorLessThanHundred').plain, 'maxScore'); $('#railwam-database-field').removeAttr('readonly'); $('input[name="railwam-database"]:not(:checked)').attr('disabled', false); $('#railwam-database-select').attr('disabled', false); $('#railwam-database-custom-input').attr('readonly', false); $('#railwam-database-input-container').removeClass('railwam-database-disabled'); return false; }                               break; case 'rank': case 'vertrank': if (local.parseNum(input) >= 1 && local.parseNum(input) <= 5000) { return true; } else { local.database.error(i18n.msg('errorRankBetween').plain, 'maxRank'); $('#railwam-database-field').removeAttr('readonly'); $('input[name="railwam-database"]:not(:checked)').attr('disabled', false); $('#railwam-database-select').attr('disabled', false); $('#railwam-database-custom-input').attr('readonly', false); $('#railwam-database-input-container').removeClass('railwam-database-disabled'); return false; }                               break; }                    },                };            local.dashboard = { init: function { // Change title of page $('title').text('RailWAM: ' + 'Dashboard'); $('.page-header__title').text('RailWAM: ' + 'Dashboard'); // Add main HTML $('#mw-content-text').html('  RailWAM Database Search for WAM score, rank, and vertical data with a single, easy-to-use interface. ' + i18n.msg('wamDatabase').plain + '</a>  <div style="width: 33%;height: 340px;background: #f5f5f5;box-sizing: border-box;padding-top: 50px;text-align: center;"> Search data</a>  '); },               };            local.faq = { /**                    * Displays a frequently asked questions module. *                     * @returns {void} */                   display: function { // Create object to store FAQ content var faqObj = { title:'RailWAM: ' + i18n.msg('faqTitle').plain, items: [{ name: i18n.msg('sectionWAM').plain, head1: i18n.msg('quesWhatIsWAM').plain, cnt1: i18n.msg('ansWhatIsWAM').plain, head2: i18n.msg('quesCalcWAM').plain, cnt2: i18n.msg('ansCalcWAM').plain, head3: i18n.msg('quesImproveWAM').plain, cnt3: i18n.msg('ansImproveWAM', '' + i18n.msg('communityLinkText').plain + '</a>').plain, head4: i18n.msg('quesScoreZero').plain, cnt4: i18n.msg('ansScoreZero').plain }, {                                name: 'RailWAM', head1: i18n.msg('quesWhatIsRailWAM').plain, cnt1: i18n.msg('ansWhatIsRailWAM', '' + i18n.msg('docLinkText').plain + '</a>').plain, head2: i18n.msg('quesInstallRailWAM').plain, cnt2: i18n.msg('ansInstallRailWAM', '' + i18n.msg('docLinkText').plain + '</a>').plain, head3: i18n.msg('quesCreators').plain, cnt3: i18n.msg('ansCreators', 'Blaster Niceshot</a>', 'Demotivator</a>').plain, }, {                               name: i18n.msg('databaseAlt').plain, head1: i18n.msg('quesWhatIsDatabase').plain, cnt1: ' ' + i18n.msg('ansWhatIsDatabaseIntro').plain + ' ' + i18n.msg('ansWhatIsDatabaseUseHeading').plain + ' ' + i18n.msg('ansWhatIsDatabaseInstructions').plain + ' ' + i18n.msg('ansWhatIsDatabaseMoreInfo').plain + ' ', head2: i18n.msg('quesSearchTime').plain, cnt2: ' ' + i18n.msg('searchTimeSummary').plain + ' ' + i18n.msg('detailedFormula').plain + ' ' + i18n.msg('searchTimeExp1').plain + ' T' + i18n.msg('requests').plain + ' = T' + i18n.msg('days').plain + ' + 1 ' + i18n.msg('searchTimeExp2').plain + ' t' + i18n.msg('seconds').plain + ' = (T' + i18n.msg('requests').plain + ' - 2) ⋅ 10  ' + i18n.msg('or').plain + ' t' + i18n.msg('seconds').plain + ' = (T' + i18n.msg('days').plain + ' - 1) ⋅ 10 ', head3: i18n.msg('quesList').plain, cnt3: i18n.msg('listTypeDesc').plain + ' ' + i18n.msg('whatToEnter').plain + ' ' + i18n.msg('list').plain + ' - ' + i18n.msg('listParamDesc').plain, head4: i18n.msg('quesDate').plain, cnt4: i18n.msg('dateTypeDesc').plain + ' ' + i18n.msg('whatToEnter').plain + ' ' + i18n.msg('date').plain + ' - ' + i18n.msg('dateParamDesc').plain, head5: i18n.msg('quesScore').plain, cnt5: i18n.msg('scoreTypeDesc').plain + ' ' + i18n.msg('whatToEnter').plain + ' ' + i18n.msg('score').plain + ' - ' + i18n.msg('scoreParamDesc').plain + ' ' + i18n.msg('matchingRules').plain + ' ' + i18n.msg('matchingIntro').plain + '<ol class="railwam-ol"><li>' + i18n.msg('matchingExcept1').plain + '</li><li>' + i18n.msg('matchingExcept2').plain + '</li></ol>' + i18n.msg('matchingSummary').plain, head6: i18n.msg('quesRank').plain, cnt6: i18n.msg('rankTypeDesc').plain + ' ' + i18n.msg('whatToEnter').plain + ' ' + i18n.msg('rank').plain + ', ' + i18n.msg('vertRank').plain + ' - ' + i18n.msg('rankParamDesc').plain, }]                       };                        if (windowWidth > 768) { // Desktop modal local.faq.createModal(faqObj); } else { // Mobile modal $.showCustomModal('RailWAM: ' + i18n.msg('faqTitle').plain, i18n.msg('faqWelcome', '' + i18n.msg('faqLinkText').plain + '</a>').plain + ' ', {                               id:'railwam-modal-body-mobile',                                width:windowWidth * 0.7,                            }); local.faq.addHeaders(faqObj, '#railwam-modal-body-mobile .modalContent', true); }                   },                    /**                     * Creates and displays a custom modal window. *                     * @param {Object} dataObj - Use the following properties: * title - modal title * items - contains menu and content items * items.name - section heading * items.head# - menu item # text * items.cnt# - content item # text *                     * @returns {void} */                   createModal: function(dataObj) { var modalBase = '   ' + i18n.msg('home').plain + '   RailWAM | ' + i18n.msg('documentation').plain + '</a> | ' + i18n.msg('reportBug').plain + '</a>    '; // Fade in modal $(modalBase).hide.appendTo('body').fadeIn(100); // Disable scroll $('body').css('overflow', 'hidden'); // Close button SVG $('#railwam-modal-body').append('<svg id="railwam-modal-close" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 39 43"><path id="railwam-x" fill="' + bodyTextColor + '" stroke-width="0" d="M 7.82,0.60 C 11.11,1.98 17.11,14.21 19.45,17.73 21.15,13.93 27.71,2.16 31.32,0.57 32.95,-0.14 35.91,-0.36 36.27,2.36 36.27,2.36 24.36,21.00 24.36,21.00 24.36,21.00 30.00,29.00 30.00,29.00 30.00,29.00 36.91,40.73 36.91,40.73 36.00,42.82 33.89,43.12 32.09,42.40 27.97,40.75 21.84,28.75 19.36,24.64 17.84,28.61 10.49,40.88 6.73,42.45 4.99,43.18 2.45,42.55 2.27,39.64 2.27,39.64 9.00,29.00 9.00,29.00 9.00,29.00 14.91,21.36 14.91,21.36 14.91,21.36 2.82,2.64 2.82,2.64 3.00,-0.27 6.09,-0.13 7.82,0.60 Z" /> '); // Make close button clickable $('#railwam-modal-close').click(function{                           $('#railwam-modal-overlay').fadeOut(100, function{ $(this).remove; $('body').css('overflow', bodyOverflow); });                       });                        // Set modal title $('#railwam-modal-content-container').append(' ' + dataObj.title + ' '); // Add sidebar items local.faq.addHeaders(dataObj, '#railwam-modal-sidebar', false); // Collapse if expanded height creates scrollbar if ($('#railwam-modal-sidebar').height !== $('#railwam-modal-sidebar')[0].scrollHeight) { $('.railwam-modal-sidebar-item').trigger('click'); }                       // Append nav links to top of content container $('#railwam-modal-content-container').append(' ' + i18n.msg('home').plain + '  /  '); // Append banner below nav links $('#railwam-modal-content-container').append(' ' + i18n.msg('faqWelcomeShort').plain + ' '); // Append content area below banner var contentHeight = $('#railwam-modal-body').height; $('#railwam-modal-content-container').append(' ' + i18n.msg('faqWelcome', '' + i18n.msg('faqLinkText').plain + '</a>').plain + ' '); /* Content area height = modal body height - banner, nav links, etc. heights */ $.each($('#railwam-modal-content-area').siblings, function(i, thisSibling){                           contentHeight -= $(thisSibling).height;                            contentHeight -= $(thisSibling).css('margin-top').replace('px', );                            contentHeight -= $(thisSibling).css('margin-bottom').replace('px', );                            contentHeight -= $(thisSibling).css('padding-top').replace('px', );                            contentHeight -= $(thisSibling).css('padding-bottom').replace('px', );                        }); contentHeight -= $('#railwam-modal-content-area').css('padding-top').replace('px', ''); contentHeight -= $('#railwam-modal-content-area').css('padding-bottom').replace('px', ''); $('#railwam-modal-content-area').height(contentHeight); // Make home nav link clickable $('#railwam-modal-navlink-home').click(function{                           local.faq.changePage(i18n.msg('faqWelcomeShort').plain, i18n.msg('faqWelcome', '<a href="//www.wikia.com/WAM/FAQ" target="_blank" rel="noopener noreferrer">' + i18n.msg('faqLinkText').plain + '</a>').plain);                        }); // Make home header clickable $('#railwam-modal-sidebar-home').click(function{                           local.faq.changePage(i18n.msg('faqWelcomeShort').plain, i18n.msg('faqWelcome', '<a href="//www.wikia.com/WAM/FAQ" target="_blank" rel="noopener noreferrer">' + i18n.msg('faqLinkText').plain + '</a>').plain);                        }); },                   /**                     * Adds headers and page links to FAQ modules. *                     * @param {Object} dataObj - Use the following properties: * title - modal title * items - contains menu and content items * items.name - section heading * items.head# - menu item # text * items.cnt# - content item # text * @param {string} appendTo - selector to append headers to                    * @param {boolean} isMobile - is the FAQ module mobile *                     * @returns {void} */                   addHeaders: function(dataObj, appendTo, isMobile) { var mobileFlag = isMobile === true ? '-mobile' : ''; // Add nav items $.each(dataObj.items, function(i, cur) {                           // Append heading                            $(appendTo).append('<ul id="railwam-modal-sidehead-' + i + mobileFlag + '" class="railwam-modal-sidehead' + mobileFlag + '"><span class="railwam-modal-sidebar-item' + mobileFlag + '">' + cur.name + '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 28" class="railwam-modal-dropdown-arrow"><use xlink:href="#railwam-modal-dropdown-arrow" fill="' + headerTextColor + '"/> <span class="railwam-modal-sidehead-container' + mobileFlag + '"> </ul>');                            // Collapsible behavior - open by default                            var degrees = 180;                            $('#railwam-modal-sidehead-' + i + mobileFlag + ' .railwam-modal-sidebar-item' + mobileFlag + ' .railwam-modal-dropdown-arrow').css('transform', 'rotate(180deg)');                            // Make header clickable $('#railwam-modal-sidehead-' + i + mobileFlag + ' .railwam-modal-sidebar-item' + mobileFlag).click(function {                                // Slide page list open                                var headerContent = $(this).siblings('.railwam-modal-sidehead-container' + mobileFlag);                                headerContent.slideToggle(100);                                // Rotate arrow                                degrees += 180;                                $('.railwam-modal-dropdown-arrow', $(this)).css('transform', 'rotate(' + degrees + 'deg)');                            }); // Add sidehead sub (page) items $.each(cur, function (prop, val) {                               // Property name must be head#                                if (prop.indexOf('head') !== -1) {                                    if (isMobile === false) {                                        // Append page item                                        $('#railwam-modal-sidehead-' + i + ' .railwam-modal-sidehead-container').append('<li class="railwam-modal-sidehead-sub">' + val + '</li>');                                        // Change page on page item click                                        $('.railwam-modal-sidehead-sub:contains("' + val + '")').click(function{ local.faq.changePage(val, cur['cnt' + prop.replace('head', '')]); });                                   } else {                                        // Append page item                                        $('#railwam-modal-sidehead-' + i + mobileFlag + ' .railwam-modal-sidehead-container' + mobileFlag).append(' <li class="railwam-modal-sidehead-sub' + mobileFlag + '">' + val + '</li><span class="railwam-modal-content' + mobileFlag + '">' + cur['cnt' + prop.replace('head', '')] + '  ');                                        var modalWrapColor = $('.modalWrapper').css('background-color');                                        $('.railwam-modal-sidebar-item-mobile').css('color', modalWrapColor);                                        $('.railwam-modal-dropdown-arrow').css('fill', modalWrapColor);                                        // Focus                                        $('.railwam-modal-sidebar-item-mobile').focus(function { $(this).css('background-color',                                               headerBgColor                                                    .replace('rgb(', 'rgba(')                                                        .replace(')', ', 0.4)')                                            ); });                                       // Focus out                                        $('.railwam-modal-sidebar-item-mobile').focusout(function { $(this).css('background-color', headerBgColor); });                                   }                                }                            });                        });                        if (isMobile === true) {                            $('.railwam-modal-sidebar-item-mobile').trigger('click');                        }                    },                    /**                     * Changes page of custom modal.                     *                      * @param {string} banner - Text to display in banner (e.g., the question)                     * @param {string} text - Content text                     *                      * @returns {void}                     */                    changePage: function(banner, text) {                        // Remove active class from no longer active page                        $('.railwam-modal-sidehead-sub-active').removeClass('railwam-modal-sidehead-sub-active'); if (banner != i18n.msg('faqWelcomeShort').plain) { // Page is active $('.railwam-modal-sidehead-sub:contains("' + banner + '")').addClass('railwam-modal-sidehead-sub-active'); } else { // Home is active $('.railwam-modal-sidebar-item:contains("' + i18n.msg('home').plain + '")').addClass('railwam-modal-sidehead-sub-active'); }                       // Set banner text $('#railwam-modal-content-banner').text(banner); // Set content text $('#railwam-modal-content-area').html(text); if ($('#railwam-modal-navlink-page').length > 0) { if (banner != i18n.msg('faqWelcomeShort').plain) { // Set page nav link text $('#railwam-modal-navlink-page').text(                                   $('.railwam-modal-sidebar-item', $('.railwam-modal-sidehead-sub:contains("' + banner + '")').closest('.railwam-modal-sidehead'))                                        .text                                ); } else { // Home page is selected; no page nav link $('#railwam-modal-navlink-page').remove; $('#railwam-modal-navlink-page-slash').remove; }                       } else { if (banner != i18n.msg('faqWelcomeShort').plain) { // Add page navigation link $('#railwam-modal-navlink-container').append(' ' + $('.railwam-modal-sidebar-item', $('.railwam-modal-sidehead-sub:contains("' + banner + '")').closest('.railwam-modal-sidehead')).text + ' / '); }                       }                    },                };            local.utils = { logOld: function { },               };            mw.hook('rw.api.ready').add(local.start); });   }); }) (this, this.jQuery, this.mediaWiki);
 * (function(window, $, mw) {