Twister84 / Ogame ShortCut

// ==UserScript==
// @name         Ogame ShortCut
// @namespace    https://openuserjs.org/users/Twister84
// @version      0.4
// @copyright    2018, Twister84 (https://openuserjs.org/users/Twister84)
// @license      MIT
// @match        https://*.ogame.gameforge.com/game/index.php*
// @grant        none
// ==/UserScript==

// ==OpenUserJS==
// @author Twister84
// ==/OpenUserJS==

(function() {
    'use strict';

    var blockWidth = 100,
        href = window.location.href,
        storeItemKey = 'ogame-key-page-map',
        sotreLangKey = 'ogame-lang',
        menuTable = $('#menuTable'),
        buttonLabelMap = {},
        store = window.localStorage || null,
        storedPageMap = store ? store.getItem(storeItemKey) || null: null,
        currentLang = (store ? store.getItem(sotreLangKey) : 'null') || 'en',
        paramIndex = href.indexOf('?'),
        baseUrl = href.substring(0, paramIndex),
        hasEventListener = document.addEventListener !== undefined,
        eventHandler = hasEventListener ? document.addEventListener : document.attachEvent,
        getBaseSelector = page => '.menubutton[href*="?page=' + page + '"]',
        footerEl = $('#siteFooter'),
        footerElHeight = footerEl ? footerEl.height() : 20;

    var isFKey = (keyCode) => {return keyCode >= 112 && keyCode <= 123;};
    var isNumeric =  (keyCode) => {return keyCode >= 48 && keyCode <= 57;};

    //FLEET SECTION
    var battleshipListIdentifier = 'battleships',
        civilshipListIdentifier = 'civilships',
        itemIdentifier = 'buildingimg',
        isFleetPage = href.indexOf('page=fleet') !== -1,
        isChatPage = href.indexOf('page=chat') !== -1 || href.indexOf('page=messages')!==-1,
        battleshipElements = isFleetPage ?  $('#'+battleshipListIdentifier+' .'+itemIdentifier): null,
        battleshipAmount =battleshipElements ? new Array(battleshipElements.length).fill(500): null,
        civilshipElements = isFleetPage ? $('#'+civilshipListIdentifier+' .'+itemIdentifier): null,
        civilshipAmount =civilshipElements ? new Array(civilshipElements.length).fill(500): null;

    if(isFleetPage){
        // Force templates loading
        $('span.dropdown.currentlySelected.combatunits a').click().click();
    }

    var manageShipSelector = event => {
        var key = event.key.toUpperCase();
        var templates = $('ul.dropdown.dropdownList.initialized li [data-value!=-]');

        if(event.ctrlKey && key.length === 1){
            if(!isNaN(key)){
                try{
                    var index = parseInt(key) - 1;
                    templates[index].click();
                    return true;

                    //                 var baseElements = battleshipElements,
                    //                     amountElement = battleshipAmount;

                    //                 if(event.altKey){
                    //                     baseElements = civilshipElements;
                    //                     amountElement = civilshipAmount;
                    //                 }

                    //                 var element = baseElements[index];
                    //                 if(amountElement[index]){
                    //                     var input = $(element).parent().find('input');
                    //                     input.val(amountElement[index]);
                    //                     input.change();
                    //                     return true;
                    //                 }else{
                    //                     $(element).find('a').click();
                    //                     return true;
                    //                 }
                }catch(e){
                    return false;
                }
                return false;
            }
        }
    };


    //IMAGES
    var keyboardImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMS4xYyqcSwAAArNJREFUSEvFl+trE0EUxUOriCX1WQ2UgohSa2pAiKJYbbRKyKPJJjaxPqAgaGvTb/WBSCEf/bPj+a0zcTIOZlfS9MLJnrmvc2d2sySZfr8/0+12ZwHcXfv+ScUymcxMBlIqlU5NE7H4iQlzDKFgCI1GY2Nzc1M0HE+KVMKdTufswFgobqHBVur1+gsNeTMUB6mOutlsPjO6fwlXKpVzEjw04RGTf8HPTyWsBu9No23rK5fLl7S7b7GCY8r5Ymhsbh+Qdsf3TB8afzd0aPIdsnO3xoQG8i+5/lTCQPfts+k1NAn21CMbyjcpAw2dd/2xcJqnGmj6KzzdtVrtbihuoYEWjC47PuPG/ks4KYxmfCJ+bERYxzGvB6UmtLWjl0BFWz4U7wDld32o5hVQ3rbRHWj9hjX9VHdxKMwHR2Hyjt00xNxQWPfrtvEPNNVTH0ouAe1qfRS1dcWfAMUfu9AO1yzU/5Fpj/D9obAK7+BU0q5zH87Lb48m22q1LheLxdMqnINzSgCOjzy4BpqHR1F0Adh+ynlrNB7+U5g15nIJ5dXgCK6a1+INeKNR/6ldXYNjfj2wwhrsQSzMw5VUmObK3YErd0NYg6vpnngOjvn1IChcrVYLOGlgEyeNxMKsMZfrqG8o5wCuBnXx53Bdv2q9CMf8emCFdTJ/7rEVHnfUyltGBK7rlvIrhvc11BIc8+tBUDh0jycNabxLJMwag2vanlmONeUe+fWmR7Ids8ZcntT8emCFx36d+OrwMMHb7fZVFdwC3GcXemksuzFdF6lRr+vA9gsKK2EVJ2abKHEF8Dr1wYtEOXnqfLAJEEXVAtAwukYFxX7QXz1/vzIRdn/IHbdJNBsL82GOJqdpPggHQs+H4vvayb74pwD2gHJ2fajmo8GO1jm0RoSniZMV5g8UZLrozv4Cgh1+2Uoy6TQAAAAASUVORK5CYII=';
    var clearImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMjHxIGmVAAACKklEQVRoQ+2XzWsaURTF3WeRRck+NKWkodBdyKqYktBknU2gtMRdNoEW+gfYRbb9F6SBkkjtPq5CyKp0tlWMiOjGjh84TjI6o472vMcVxIz5gPfUtvcHlzcc571zzwwz8wwxDMP83+Tz+Wee573r9/t7t1Umk3lBU2aPVCr1yPd9F43eCc7rNhqNpzR1tigWi0+oz/sSpqmzxXCQXq+3i2FxtNLp9GuMA2Y/CAhsMplMPqffBdMJYprmkjAfV81m8w1GCe7Ieww3zimVShGMknHnDMq27RWyVod4MGHcgcHE6Ha7frVaXaMW1NDpdNZp/UmzRy2oYThILpfbNAxjWVfF4/FVshLoC2JZ1mOSdTFPVgIOEshwEHyVE3jwY7rKcZyvZCXQF2SS4M31llpQAz5kc67rnuKKtcjAwXFeQ13R+th7emf4lixQC2qB0ZkwqlQqCZKUgvVjYv16vf6TJD1wkHvCQR7KuCDYML7EAxrB222bJAkaCgsd87ZIkmDz+CpIn3qQdrt9JHQ0d06SBJvNE6GLeSRJyuXy9yCdgzwUDsJBNMFBOIgmOAgH0QQH+VuCmKZ5UKvVvqE+kSQpFAofhI7GoiRJstnsxyB96kFU8c8Ewf+ZL2J927Z/kKQHnUEMw5j3ff+3WN913WOS9TAI0mq1fmGIqirciUPUJY4llmVtkKUeBkF04nneZ7LTh+M4+7hyTfJUBpq/Rl3g7bdDVgzDMKOEQn8AQ50Pjsfq5NwAAAAASUVORK5CYII=';

    var localeMap = {
        it: {
            image: 'data:image/gif;base64,R0lGODlhEAALANUAAPdMTACFAOLi4t7e3uYAAPITE/lVVfT09PU9PewAAPIuLli6WQBXAPENDf7+/ly9XPMAAEOvQlS2VQB9AHvKewBlAFS5VPUlJfMZGU+2TwB2APMyMuAAAACJAMLCwvcxMUm0SfQfH/YrK3nIeXTGdOXl5QBvAACRAPQ2Nli8WM3NzfYsLMjIyEuzS/g3NzqqOmjCaPpcXPM1NfZERGC/Ydvb2/X19d0AAP39/fv7+/z8/Pb29vr6+vn5+fj4+Pf39yH5BAAAAAAALAAAAAAQAAsAAAaLwFOnEwiUBILBoAZpJhIBCmU0cuBwOl0uZjAAEh0K7bG4ank912cFIARGZAk2h/Z9RJeZm5SyZM49Pj94IQh7fi10gT87FyEYhhMkGSARdYw2jwUoBBMwlRGLOzYHGAUFGxwaMBERL4KjBwcFDQ0KHCZjCxKCmAcyGwoKNxoVFQwMKiwsHs0cHDfRQQA7',
            'menu.item.text': 'Shortcut Config.',
            'settings.dialog.title': 'Configurazione shortcut',
            'settings.dialog.choosekey.title': 'Scegli un tasto',
            'settings.dialog.choosekey.text': 'Premi qualsiasi tasto per associarlo al link per',
        },
        en: {
            image: 'data:image/gif;base64,R0lGODlhEAALAMQAAP5RTlBlsQAUbZC20/mRjc3V6vg0NZhLaf39+xgrjrrP7b+ZtaGt1vyur+pgVfmFfGGDwYqZz/5jYnubxP/r6jxSrIUbN3GEx9vh9Kxhf+G+32RztcLE3dnd7f7+/////yH5BAAAAAAALAAAAAAQAAsAAAWBYKRMUNllWRcEFXRMTONhDOMRhBdF3IMMEEWj8Yl8JJLPpUH4MBIQRkTz+BwBR0qhckl0PNYwABv+eAoZAnLMNrjdAMu3/HGHEfhtJFCgJO11CwkBAhUMHw8EG3UGCBUIBA4RAgMeDxwXFx5jCCscCA4bEwcBCaYFFhYFAqwJAwkhADs=',
            'menu.item.text': 'Shortcut Settings',
            'settings.dialog.title': 'Shorcut Settings',
            'settings.dialog.choosekey.title': 'Choose a key',
            'settings.dialog.choosekey.text': 'Press any key to configure the link for',
        }
    };

    var localize = (placeholder) => {return localeMap[currentLang][placeholder] ? localeMap[currentLang][placeholder] : placeholder};
    var getButtonText = (page) =>{return buttonLabelMap[page];};

    // shortcut configuration map
    var pageMap = storedPageMap ? JSON.parse(storedPageMap) : {overview:"F1",resources:"F2",station:"F3",traderOverview:"F4",research:"F5",shipyard:"F6",defense:"F7",fleet1:"F8",galaxy:"F9",alliance:"F10"};

    var saveStore = function(){
        if(store){
            store.setItem(storeItemKey, JSON.stringify(pageMap));
            store.setItem(sotreLangKey, currentLang);
        }
    };

    if(!storedPageMap){
        saveStore();
    }

    var generateSpecialKeysRadioGroup = function(index, ctrl, alt){
        return '<label style="margin-right:5px"><input type="radio" name="specialkeyradio-'+index+'" value="NONE"' + (!ctrl && !alt ? ' checked': '')+'>NONE</label>'+
            '<label style="margin-right:5px"><input type="radio" name="specialkeyradio-'+index+'" value="CTRL"' + (ctrl ? ' checked': '')+'>CTRL</label>'+
            '<label style="margin-right:5px"><input type="radio" name="specialkeyradio-'+index+'" value="ALT"' + (alt ? ' checked': '')+'>ALT</label>';
    };

    var createKeyboardElement = function(index, page, key, onClickHandler){
        var img = $('<img index="'+index+'" page="'+page+'" key="'+key+'" width="30" height="30" style="cursor:pointer; float:right" src="'+keyboardImage+'" />');
        img.click(function(e){
            var rowIndex = (e.target.getAttribute('index'));
            var rowPage = (e.target.getAttribute('page'));
            var rowKey = (e.target.getAttribute('key'));
            var radioValue = $("input[name='specialkeyradio-"+rowIndex+"']:checked").val();

            if(onClickHandler){
                onClickHandler(rowPage, radioValue);
            }

        });
        return img;
    };

    var createClearElement = function(index, page){
        var img = $('<img index="'+index+'" page="'+page+'" width="30" height="30" style="cursor:pointer; float:right" src="'+clearImage+'" />');
        img.click(function(e){
            var rowIndex = (e.target.getAttribute('index'));
            var rowPage = (e.target.getAttribute('page'));
            // SET NONE RADIO
            $("input[name='specialkeyradio-"+rowIndex+"'][value=NONE]").prop("checked", true);
            pageMap[rowPage] = '';
            saveStore();

            showShortcutSettingsMenu(true);
            updateShortcutElement(rowPage);
        });
        return img;
    };

    var generateKeySelector = event => {
        var key = event.key.toUpperCase();
        key = event.ctrlKey ? key = 'CTRL+' + key: event.altKey ? 'ALT+' + key : key;
        var page = Object.keys(pageMap)[Object.values(pageMap).indexOf(key)];
        return page ? getBaseSelector(page) : null;
    };

    var firstColW = 150,
        secondColW = 270,
        thirdColW = 120;

    var showShortcutSettingsMenu = (edit) => {
        removeWindowListener();
        var box = edit ? $('#shortcut-settings-box') : $('<div id="shortcut-settings-box"></div>');
        if(edit){
            box.empty();
        }

        Object.keys(pageMap).map((page, index) => {
            var key = pageMap[page];
            try{
                var btn = $(getBaseSelector(page));

                var hasCtrl = key.indexOf('CTRL') !== -1;
                var hasAlt = key.indexOf('ALT') !== -1;
                var rawkey = key.replace('CTRL+', '').replace('ALT+', '');

                var htmlContent = '<div id="'+page+'-shortcut">'+
                    '<div style="line-height:30px;width:'+firstColW+'px;display:inline-block">'+getButtonText(page)+'</div>'+
                    '<div style="line-height:30px;width:'+secondColW+'px;display:inline-block;">'+generateSpecialKeysRadioGroup(index, hasCtrl, hasAlt)+'</div>'+
                    '<div id="key-'+index+'" key="'+rawkey+'" page="'+page+'" style="line-height:30px;width:'+thirdColW+'px;display:inline-block;text-align:right;">'+(rawkey ? rawkey : '')+'</div>'+
                    '</div>';

                var element = $(htmlContent).css({
                    fontSize: '14px',
                    padding: '5px',
                    backgroundColor: index%2==0 ? '#222': 'black'
                });

                var shortcutImg = createKeyboardElement(index, page, key, function(nPage, radioValue){
                    var keyDialog = $('<div>'+localize('settings.dialog.choosekey.text')+' <b>'+getButtonText(nPage)+'</b>...</div>');
                    window.onkeydown = (function(event) {
                        event.stopPropagation();
                        event.preventDefault();
                        var eventKey = event.key.toUpperCase();
                        var newKey = radioValue !== 'NONE' ? radioValue+'+'+eventKey: eventKey;
                        pageMap[nPage] = newKey;
                        saveStore();
                        keyDialog.dialog('close');
                        showShortcutSettingsMenu(true);
                        updateShortcutElement(nPage);
                    });

                    keyDialog.dialog({
                        closeOnEscape: false,
                        resizable: false,
                        height: 65,
                        width: 350,
                        modal: true,
                        closable: false,
                        title: localize('settings.dialog.choosekey.title'),
                        close: function(){
                            keyDialog.remove();
                            removeWindowListener();
                        }
                    })
                });

                var clearImg = createClearElement(index, page);

                element.append(clearImg);
                element.append(shortcutImg);


                box.append(element);
            }catch(e){}
        });


        if(!edit){
            box.dialog({
                resizable: false,
                height: "auto",
                width: 650,
                modal: true,
                title: localize('settings.dialog.title'),
                close: function(){
                    box.remove();
                    addWindowListener();
                }
            });

            Object.keys(pageMap).map((pageIn, index) => {
                try{
                    $('input[name="specialkeyradio-'+index+'"]').change(function() {
                        var category = $(this).filter(':checked').val();
                        var baseKey = $('div #key-'+index).attr('key');
                        var page = $('div #key-'+index).attr('page');
                        var key = category !== 'NONE' ? category+'+'+baseKey: baseKey;
                        pageMap[page] = key;
                        saveStore();
                        updateShortcutElement(page);
                    });
                }catch(e){}
            });
        }
    };


    var settingButton = $(getBaseSelector('overview')).clone();
    settingButton.attr('href', 'javascript:void(0)');
    settingButton.removeClass('selected');
    settingButton.click(()=>{showShortcutSettingsMenu();});
    settingButton.html(localize('menu.item.text'));
    menuTable.append($('<li></lii>').append(settingButton));

    var updateShortcutElement = function(page){
        try{
            $('div #shortcut-'+page).html(pageMap[page] ? ('['+pageMap[page]+']') : '');
        }catch(e){}
    };

    Object.keys(pageMap).map(page => {
        var key = pageMap[page];
        try{
            var btn = $(getBaseSelector(page)),
                coords = btn.position();

            buttonLabelMap[page] = btn.text().trim();
            var element = $('<div id="shortcut-'+page+'">'+(key ? ('['+key+']'): '')+'</div>').css({
                cursor: 'default',
                position: "absolute",
                textAlign: 'right',
                height: btn.height()+'px',
                lineHeight: btn.height()+'px',
                width: blockWidth+'px',
                top: coords.top + "px",
                left: '-'+blockWidth+'px'
            });

            btn.before(element);
        }catch(e){}
    });

    var _windowListener = (event) => {
        var isF = isFKey(event.keyCode || event.which);
        var isConfigured = false;
        if(isChatPage && !isF){
            return true;
        }

        var keySelector = generateKeySelector(event);
        if(keySelector){
            try{
                $(keySelector)[0].click();
                isConfigured = true;
            }catch(e){}
        }else if(isFleetPage){
            isConfigured = manageShipSelector(event);
        }

        //Returning false overrides default browser event
        if(isConfigured && (isF || event.key === 'ESCAPE' || event.altKey || event.ctrlKey)){
            event.stopPropagation();
            event.preventDefault();
            return false;
        }
        return true;
    };

    var removeWindowListener = () => { window.onkeydown = null;};
    var addWindowListener = () => { window.onkeydown = _windowListener;};

    addWindowListener();
})();