// ==UserScript== // @name Ikariam Enhanced UI // @description Enhancements for the user interface of Ikariam. // @namespace Tobbe // @author Tobbe // @version 3.2.2 // @license MIT License // // @name:de Ikariam Enhanced UI // @description:de Verbesserungen der Oberfläche von Ikariam. // // @run-at document-idle // // // @include /https?:\/\/s[0-9]*-[a-z]{2}\.ikariam\.gameforge\.com\/.*/ // // @require https://greasyfork.org/scripts/5574-ikariam-core/code/Ikariam%20Core.js?version=105280 // // // @resource de http://resources.ikascripts.de/IkariamEnhancedUI/v3.2.2/de.json // @resource gr http://resources.ikascripts.de/IkariamEnhancedUI/v3.2.2/gr.json // @resource fr http://resources.ikascripts.de/IkariamEnhancedUI/v3.2.2/fr.json // @resource it http://resources.ikascripts.de/IkariamEnhancedUI/v3.2.2/it.json // @resource lv http://resources.ikascripts.de/IkariamEnhancedUI/v3.2.2/lv.json // @resource ru http://resources.ikascripts.de/IkariamEnhancedUI/v3.2.2/ru.json // @resource tr http://resources.ikascripts.de/IkariamEnhancedUI/v3.2.2/tr.json // @resource core_de http://resources.ikascripts.de/IkariamCore/v2.3.2/core_de.json // @resource core_de_settings http://resources.ikascripts.de/IkariamCore/v2.3.2/core_de_settings.json // @resource core_fr http://resources.ikascripts.de/IkariamCore/v2.3.2/core_fr.json // @resource core_fr_settings http://resources.ikascripts.de/IkariamCore/v2.3.2/core_fr_settings.json // @resource core_gr http://resources.ikascripts.de/IkariamCore/v2.3.2/core_gr.json // @resource core_gr_settings http://resources.ikascripts.de/IkariamCore/v2.3.2/core_gr_settings.json // @resource core_it http://resources.ikascripts.de/IkariamCore/v2.3.2/core_it.json // @resource core_it_settings http://resources.ikascripts.de/IkariamCore/v2.3.2/core_it_settings.json // @resource core_lv http://resources.ikascripts.de/IkariamCore/v2.3.2/core_lv.json // @resource core_lv_settings http://resources.ikascripts.de/IkariamCore/v2.3.2/core_lv_settings.json // @resource core_ru http://resources.ikascripts.de/IkariamCore/v2.3.2/core_ru.json // @resource core_ru_settings http://resources.ikascripts.de/IkariamCore/v2.3.2/core_ru_settings.json // @resource core_tr http://resources.ikascripts.de/IkariamCore/v2.3.2/core_tr.json // @resource core_tr_settings http://resources.ikascripts.de/IkariamCore/v2.3.2/core_tr_settings.json // // @grant unsafeWindow // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_listValues // @grant GM_getResourceText // @grant GM_xmlhttpRequest // // @bug Opera & Chrome Zooming with the mouse is not possible with "Shift" as access key. // @bug Opera & Chrome No updating of the missing resources is possible due to a missing modification listener. // @bug All The selected island is not centered in world view. // @bug All If you are zooming to more than 100%, the view is not centered correctly after a page reload. // // @history 3.2.2 Release: 02.02.2016 // @history 3.2.2 Core: Update to Version 2.3.2 - Bug fix (permanent reload of crew conversion) // // @history 3.2.1 Release: 27.01.2016 // @history 3.2.1 Core: Update to Version 2.3.1 - Bug fixes // // @history 3.2 Release: 27.01.2016 // @history 3.2 Core: Update to Version 2.3 - Bug fixes // @history 3.2 Feature: Let the script also run on SSL encripted Ikariam page. // @history 3.2 Bugfix: In very rare cases it was possible that the script was to fast and thus did not work. // @history 3.2 Language: French translation added (incomplete). // // @history 3.1 Release: 14.10.2015 // @history 3.1 Core: Update to Version 2.2 - Bug fixes and user specific options // @history 3.1 Feature: Player specific signatures in messages. // @history 3.1 Change: Remove easy circular message functionality as it is implemented directly in Ikariam now. // @history 3.1 Language: Turkish translation added (incomplete). // // @history 3.0.3 Release: 20.03.2015 // @history 3.0.3 Bugfix: Town name in unit information incorrect. // // @history 3.0.2 Release: 08.03.2015 // @history 3.0.2 Bugfix: Wrong time display for last reset of highscore information. // @history 3.0.2 Bugfix: Start piracy raid icon was resized. // // @history 3.0.1 Release: 07.03.2015 // @history 3.0.1 Language: Updated Greek translation. // @history 3.0.1 Bugfix: Language key in message options. // @history 3.0.1 Bugfix: Alliance member data stored at same place for all alliance members. // // @history 3.0 Release: 05.03.2015 // @history 3.0 Language: Russian translation added (incomplete). // @history 3.0 Language: Italian translation added (incomplete). // @history 3.0 Language: Greek translation added (incomplete). // @history 3.0 Change: Implementation of Ikariam Core - rewrote the complete code. // @history 3.0 Change: Cleared the update history to use the Ikariam Core labels. // @history 3.0 Bugfix: Diverse graphic errors. // @history 3.0 Bugfix: Broken in Firefox and Chrome. // @history 3.0 Due to rename of script: Manually deleting old script necessary. // // @history 2.6 Release: 12.10.2014 // @history 2.6 Bugfix: Script options were broken. // // @history 2.6 Release: 19.08.2014 // @history 2.5 Bugfix: Game language is recognized again. // @history 2.5 Bugfix: Works now in Greasemonkey 2.0+ // @history 2.5 Change: Checks now for updates on Greasy Fork. // @history 2.5 Removed code parts for mobile version. // @history 2.5 Removed alliance page improvement, as fixed in Ikariam v0.5.13 // // @history 2.6 Release: 11.09.2013 // @history 2.4 Bugfix: New Ikariam domain -> script can now be used with this domain // // @history 2.3 Release: 12.04.2013 // @history 2.3 Feature: Formatting troop lists for posting in forums / personal messages. // @history 2.3 Feature: Filling level of warehouse as bar in town view. // @history 2.3 Feature: Link to mines / town hall when clicking on resources / citizens. // @history 2.3 Change: New versioning system. // @history 2.3 Bugfix: Some characters in links were not decoded correctly. // @history 2.3 Bugfix: Watching a foreign city causes a abortion of the script. // @history 2.3 Bugfix: The city dropdown sometimes was zoomed in world view. // @history 2.3 Bugfix: Removed obsolete CSS styles for Firefox. // @history 2.3 Adjustments in the language files. // @history 2.3 Violent Monkey brings Greasemonkey functions to Opera. // // @history 2.2.1 Release: 11.10.2012 // @history 2.2.1 Feature: Smaller icons in direct military tooltip. // @history 2.2.1 Bugfix: Problems with update check and version numbers >= 10. // @history 2.2.1 Bugfix: Problems with another script. // @history 2.2.1 Bugfix: Problems with a wrong style in island view. // // @history 2.2 Release: 10.10.2012 // @history 2.2 Feature: Message signature can be set. // @history 2.2 Feature: Button for faster sending of circular messages. // @history 2.2 Feature: Make links in messages clickable. // @history 2.2 Feature: Show town information of colonizing cities. // @history 2.2 Feature: Information about cargo / fleets is displayed directly in military view. // @history 2.2 Feature: Script options: Sections on the script tab can be folded. // @history 2.2 Bugfix: Tooltips with mouseover were not clickable anymore. // @history 2.2 Changes in code for better overview. // // @history 2.1.1 Release: 01.10.2012 // @history 2.1.1 Feature: Different styles for income in town view. // @history 2.1.1 Feature: Remaining resources after upgrade. // @history 2.1.1 Feature: Improved style for external alliance pages. // @history 2.1.1 Feature: Refresh the missing / remaining resources in construction view automatically. // // @history 2.1 Release: 23.09.2012 // @history 2.1 Feature: Show the missing resources in construction view. // @history 2.1 Feature: Show the hourly income directly in town view and add the daily production as popup. // @history 2.1 Feature: Don't center town information in the town advisor. // @history 2.1 Feature: Save the highscore data of alliance members and compare it with the actual value. // @history 2.1 Bugfix: There was an error with a missing language package and seperators. // @history 2.1 Bugfix: Some things in worldview were not resized correctly. // @history 2.1 Prevent more than one script execution. // @history 2.1 Prevent more than one script option panel (the script option panel now is usable for other scripts, too). // // @history 2.0.1 Release: 27.08.2012 // @history 2.0.1 Bugfix: Zooming was broken. // @history 2.0.1 Bugfix: Dropdown menus created by the script were broken. // @history 2.0.1 Bugfix: Tooltips in in Alliance / Military view were not shown correctly. // // @history 2.0 Release: 18.07.2012 // @history 2.0 Language: Latvian translation // @history 2.0 Feature: Cross-browser compatibility. // @history 2.0 Feature: Possibility to hide the update hint for a new script version. // @history 2.0 Bugfix: Resizing the owner state in world view was broken. // @history 2.0 Some changes in the code for easier copying of functions which should be used by more than one script. // // @history 1.7 Release: 12.06.2012 // @history 1.7 Feature: Resizing banners when zooming is possible in city view, too. // @history 1.7 Feature: The zoom buttons are available in world view, too. // @history 1.7 Feature: Zooming with the mouse scroll is possible again (now with key, standard is ctrl). // @history 1.7 Change: Changes in the option panel due to the new zooming function features. // @history 1.7 Bugfix: If resizing is enabled, zooming with the buttons will resize the banners, too. // @history 1.7 Bugfix: The chat will not cause to much executions of script functions. // @history 1.7 The language texts are integrated as resources, so that there is shorter code. // @history 1.7 Replace the GM_* functions by myGM.* to expand them easy and add new. // // @history 1.6 Release: 05.06.2012 // @history 1.6 Feature: Possibility to hide only the bird swarm animation. // @history 1.6 Feature: Easier upkeep reduction table. // @history 1.6 Feature: Enhanced zoom function using the Ikariam zoom function. // @history 1.6 Due to the use of Ikariam functions the code could be reduced. // @history 1.6 Code enhancements for shorter code. // // @history 1.5.1.1 Release: 25.05.2012 // @history 1.5.1.1 Bugfix: Not all occurrences of hidden were changed. // // @history 1.5.1 Release: 24.05.2012 // @history 1.5.1 Bugfix: Name of a class (hidden) is used by GF. // // @history 1.5 Release: 24.05.2012 // @history 1.5 Feature: Options panel to enable/disable funtions and set settings. // @history 1.5 Feature: Update interval can be set. // @history 1.5 Feature: Manually check for updates. // @history 1.5 Feature: Zoom function without resizing the whole view. // @history 1.5 Feature: Move loading circle to another position. // @history 1.5 Feature: Show tooltip in alliance / military view on mouseover. // @history 1.5 Change: Code better commented. More comments, so that it is easier to understand. // @history 1.5 Bugfix: Changed *.gif to *.png. // @history 1.5 Version numbers adjusted. // // @history 1.4.1 Release: 01.05.2012 // @history 1.4.1 Feature: Support for mobile interface. // @history 1.4.1 Bugfix: Fixed bug with scrollbar in finances view. // // @history 1.4 Release: 20.04.2012 // @history 1.4 Feature: Ready for 0.5.0, but also supports 0.4.5 furthermore. // @history 1.4 Feature: Implemented support for different languages. // @history 1.4 Feature: Enhanced script updater. // @history 1.4 Change: Cleaned up code. // @history 1.4 Change: Rename the script to "Enhanced UI". // @history 1.4 Change: Change the namespace to "Tobbe". // @history 1.4 Because of the change of namespace and name you have to delete the old script manually! // // @history 1.3.3 Release: 11.04.2011 // @history 1.3.3 Bugfix: Problem with negative numbers and 0.4.2.4 fixed. // // @history 1.3.2 Release: 15.01.2011 // @history 1.3.2 Feature: Own script updater. // @history 1.3.2 Change: Remove everything what refered to other scripts. // // @history 1.3.1 Release: 15.01.2011 // @history 1.3.1 Change: New script updater. // // @history 1.3 Release: 14.01.2011 // @history 1.3 Change: Remove the script updater (Because of the problem with Greasemonkey scripts). // // @history 1.2.1 Release: 28.12.2010 // @history 1.2.1 Change: New style of update panel. // @history 1.2.1 Bugfix: Bug with ',' as seperator fixed. // // @history 1.2 Release: 09.10.2010 // @history 1.2 Feature: Income in 24h added. // @history 1.2 Change: Cleaned up code. // // @history 1.1 Release: 13.04.2010 // @history 1.1 Feature: Update check implemented. // // @history 1.0 Release: 12.04.2010 // @history 1.0 Initial release. // @downloadURL none // ==/UserScript== /** * Instantiate a new set of enhancement functions. * {@link https://greasyfork.org/scripts/4369-enhanced-ui Script on Greasy Fork} * {@link https://github.com/IkaScripts/IkariamEnhancedUI Script on GitHub} * * @version 3.2.2 * @author Tobbe * * @global * * @class * @classdesc Enhancements for the user interface of Ikariam. * * @param {IkariamCore} $ * A instance of the Ikariam Core. */ function EnhancedUI(IC) { /** * Script toolbar. * * @type {element} */ var ge_toolbar = IC.myGM.addElement('div', IC.myGM.$('#GF_toolbar'), { 'id': 'toolbar' }, true, IC.myGM.$('#GF_toolbar ul')); IC.myGM.addStyle( '#GF_toolbar > ul { width: auto !important; text-align: center !important; pointer-events: none; } \ #GF_toolbar > ul > * { pointer-events: auto; } \ #GF_toolbar #mmoNewsticker { display: inline-block !important; position: relative !important; } \ #GF_toolbar #mmoNewsticker > ul { width: auto !important; } \ #' + IC.myGM.prefix + 'toolbar { float: right; } \ #' + IC.myGM.prefix + 'toolbar > div { display: inline-block; position: relative; float: right; margin: 0px 5px; }', 'scriptToolbar' ); IC.Options.addWrapper('diverseOptions', IC.Language.$('diverse.options.wrapperTitle')); IC.con.groupCollapsed('IkariamEnhancedUI initalization ...'); IC.con.timeStamp('IkariamEnhancedUI: toolbar and general styles created'); // General functions to enhance the view. (function() { IC.Options.addWrapper('enhancedView', IC.Language.$('view.options.wrapperTitle')); // Move the loading circle to the breadcrumb area. IC.Options.addCheckbox('moveLoadingCircle', 'enhancedView', 1, true, IC.Language.$('view.options.moveLoadingCircle'), { changeCallback: function(ib_newValue) { if(ib_newValue === true) { IC.myGM.addStyle( '#js_worldBread { margin-left: 16px !important; } \ #loadingPreview { transform: scale(0.5); -webkit-transform: scale(0.5); left: 35px !important; top: 141px !important; }', 'enhancedView_moveLoadingCircle' ); return; } IC.myGM.removeStyle('enhancedView_moveLoadingCircle'); } }); // Hide the flying bird swarm. IC.Options.addCheckbox('hideBirds', 'enhancedView', 1, true, IC.Language.$('view.options.hideBirds'), { changeCallback: function(ib_newValue) { if(ib_newValue === true) { IC.myGM.addStyle( '.bird_swarm { display: none; }', 'enhancedView_hideBirds' ); return; } IC.myGM.removeStyle('enhancedView_hideBirds'); } }); // Bind the town name and date to the top of the row in the town advisor. IC.Options.addCheckbox('noVerticalCenterInTownAdvisor', 'enhancedView', 1, true, IC.Language.$('view.options.noVerticalCenterInTownAdvisor'), { changeCallback: function(ib_newValue) { if(ib_newValue === true) { IC.myGM.addStyle( '#inboxCity td { vertical-align: top !important; }', 'enhancedView_noVerticalCenterInTownAdvisor' ); return; } IC.myGM.removeStyle('enhancedView_noVerticalCenterInTownAdvisor'); } }); })(); IC.con.timeStamp('IkariamEnhancedUI: view functions created'); // Functions for the island view. (function() { /** * Storage for the colonizing city info functions. * * @type {object} */ var _go_colonizingCityInfo = new function() { /** * Add the link to show the colonizing city information. */ var _lf_doShowColonizingCityInfo = function() { var la_colonizingCities = IC.myGM.$$('.level0'); la_colonizingCities.forEach(function(le_colonizingCity) { var ls_locationId = le_colonizingCity.id.replace(/\D/g, ''); var ls_cityId = IC.ika.getScreen().data.cities[ls_locationId].id; IC.myGM.$('#js_cityLocation' + ls_locationId + 'Link').href = '?view=cityDetails&destinationCityId=' + ls_cityId; }); }; /** * Remove the link to show the colonizing city information. */ var _lf_doHideColonizingCityInfo = function() { var la_colonizingCityLinks = IC.myGM.$$('.level0 .link_img'); la_colonizingCityLinks.forEach(function(le_colonizingCityLink) { le_colonizingCityLink.href = ''; }); }; /** * Update the settings to execute the callback or delete the handler. * * @param {boolean} ib_showColonizingCityInfo * If the user selected the checkbox to show the colonizing city info. */ this.updateSettings = function(ib_showColonizingCityInfo) { if(IC.Ikariam.view !== 'island') return; if(ib_showColonizingCityInfo === true) { IC.RefreshHandler.add('*', 'showColonizingCityInfo', _lf_doShowColonizingCityInfo); _lf_doShowColonizingCityInfo(); return; } IC.RefreshHandler.remove('*', 'showColonizingCityInfo'); _lf_doHideColonizingCityInfo(); }; }; // Retrieve information about colonies during colonization. IC.Options.addCheckbox('showColonizingCityInfo', 'diverseOptions', 1, true, IC.Language.$('island.options.showColonizingCityInfo'), { changeCallback: _go_colonizingCityInfo.updateSettings }); // Add a divider line. IC.Options.addLine('diverseOptions', 1); })(); IC.con.timeStamp('IkariamEnhancedUI: island functions created'); // Functions for the finance popup. (function(){ /** * Some general functions for the finance view enhancements. * * @type {object} */ var _go_generalFunctions = new function() { /** * Extract the current income in the finance popup. * * @return {int} * The current income. */ this.getIncome = function() { var le_incomeCell = IC.myGM.$$('.hidden')[IC.myGM.$$('.hidden').length - 1]; while(le_incomeCell.firstChild.firstChild) le_incomeCell = le_incomeCell.firstChild; return IC.Ikariam.getInt(le_incomeCell.innerHTML); }; /** * Create a new table row. * * @param {element} ie_parentTable * The table to add the row to. * @param {string[]} ia_classes * The class(es) of the table row. Set to null if no class should be set. * @param {object[]} ia_cells * The data for the table cells. Both properties of each cell are optional. If the cell object is empty, an empty cell is created. * Signature: [{ className: ['class1', 'class2', ...], text: 'cellContent' }] * @param {boolean} ib_isTableHeadRow * If the cells should be table header cells (th). * * @return {element} * The created row. */ this.createTableRow = function(ie_parentTable, ia_classes, ia_cells, ib_isTableHeadRow) { var re_newRow = IC.myGM.addElement('tr', ie_parentTable, { classes: ia_classes }); var ls_cellType = 'td'; if(!!ib_isTableHeadRow) ls_cellType = 'th'; for(var i = 0; i < ia_cells.length; i++) { var lo_options = { 'classes': ia_cells[i].className }; if(!!ia_cells[i].text === true) lo_options['innerHTML'] = ia_cells[i].text; IC.myGM.addElement(ls_cellType, re_newRow, lo_options); } return re_newRow; }; }; /** * Storage for the income on top functions. * * @type {object} */ var _go_incomeOnTop = new function() { /** * Callback to show the income on top. */ var _lf_doShowIncomeOnTop = function() { var le_summaryTable = IC.myGM.$('.table01'); var li_income = _go_generalFunctions.getIncome(); var la_incomeCells = [ { className: ['sigma'], text: IC.Language.$('finance.income.perHour') }, { className: ['value', 'res'] }, { className: ['value', 'res'] }, { className: ['value', 'res'], text: IC.Ikariam.formatToIkaNumber(li_income) } ]; _go_generalFunctions.createTableRow(le_summaryTable, ['result', 'alt'], la_incomeCells); la_incomeCells[0].text = IC.Language.$('finance.income.perDay'); la_incomeCells[3].text = IC.Ikariam.formatToIkaNumber(li_income * 24); _go_generalFunctions.createTableRow(le_summaryTable, ['result'], la_incomeCells); // Adjust the size of the Scrollbar. IC.ika.controller.adjustSizes(); }; /** * Update the settings to execute the callback or delete the handler. * * @param {boolean} ib_showIncomeOnTop * If the user selected the checkbox to show the income on top. */ this.updateSettings = function(ib_showIncomeOnTop) { if(ib_showIncomeOnTop === true) { IC.RefreshHandler.add('finances', 'showIncomeOnTop', _lf_doShowIncomeOnTop); return; } IC.RefreshHandler.remove('finances', 'showIncomeOnTop'); }; }; /** * Storage for the short upkeep reduction table functions. * * @type {object} */ var _go_shortUpkeepReductionTable = new function() { /** * Extract the data from the old tables. * * @param {element[]} ia_oldUpkeepReductionTables * The old upkeep tables to collapse. * * @return {object[]} * The data for the table rows. * Signature: * [{ * rows: [ * { reason : 'reason', basicUpkeep: int, supplyUpkeep: int, result: int } * ] * priorToReduction: int * income: int * }] */ var _lf_getData = function(ia_oldUpkeepReductionTables) { var ro_data = { rows: [], priorToReduction: IC.Ikariam.getInt(IC.myGM.$('td.hidden', ia_oldUpkeepReductionTables[2]).innerHTML), income: _go_generalFunctions.getIncome() }; // Get the data for the troops and ships redution rows. for(var i = 0; i < 3; i++) { var le_basicUpkeepCell = IC.myGM.$$('.alt.bottomLine td.hidden, .result td.hidden', ia_oldUpkeepReductionTables[0])[i]; var le_supplyUpkeepCell = IC.myGM.$$('.alt.bottomLine td.hidden, .result td.hidden', ia_oldUpkeepReductionTables[1])[i]; var li_basicUpkeep = IC.Ikariam.getInt(le_basicUpkeepCell.innerHTML); var li_supplyUpkeep = IC.Ikariam.getInt(le_supplyUpkeepCell.innerHTML); var lo_row = { reason: IC.Language.$('finance.upkeep.reason.' + i), basicUpkeep: li_basicUpkeep, supplyUpkeep: li_supplyUpkeep, result: li_basicUpkeep + li_supplyUpkeep }; ro_data.rows.push(lo_row); } return ro_data; }; /** * Prepare the table rows for easy adding to the new table. * * @param {element[]} ia_oldUpkeepReductionTables * The old upkeep tables to collapse. * * @return {object[]} * The data for the table rows. * Signature: * [{ * classes: 'class' || ['class1', 'class2', ...] * isHeadRow: true || false * cells: [ * { className: 'class' || ['class1', 'class2', ...], text: 'cellContent' (optional) } * ] * }] */ var _lf_prepareTableRows = function(ia_oldUpkeepReductionTables) { var lo_data = _lf_getData(ia_oldUpkeepReductionTables); var ra_tableRows = []; // Header ra_tableRows.push({ classes: [], isHeadRow: true, cells: [ { className: ['city'] }, { className: ['value', 'res'], text: IC.Language.$('finance.upkeep.basic') }, { className: ['value', 'res'], text: IC.Language.$('finance.upkeep.supply') }, { className: ['value', 'res'], text: IC.Language.$('finance.upkeep.result') } ] }); // Income without reduction ra_tableRows.push({ classes: ['alt', 'bottomLine'], isHeadRow: false, cells: [ { className: ['city'], text: IC.Language.$('finance.income.start') }, { className: ['value', 'res'] }, { className: ['value', 'res'] }, { className: ['value', 'res'], text: IC.Ikariam.formatToIkaNumber(lo_data.priorToReduction) } ] }); // Income reduction lo_data.rows.forEach(function(io_row, ii_index) { var trClass = []; if(ii_index % 2 === 1) trClass = ['alt', 'bottomLine']; ra_tableRows.push({ classes: trClass, isHeadRow: false, cells: [ { className: ['city'], text: io_row.reason }, { className: ['value', 'res'], text: IC.Ikariam.formatToIkaNumber(-io_row.basicUpkeep) }, { className: ['value', 'res'], text: IC.Ikariam.formatToIkaNumber(-io_row.supplyUpkeep) }, { className: ['hidden'], text: IC.Ikariam.formatToIkaNumber(-io_row.result) } ] }); }); // Result ra_tableRows.push({ classes: ['result'], isHeadRow: false, cells: [ { className: ['sigma'], text: 'Summe' }, { className: ['value', 'res'] }, { className: ['value', 'res'] }, { className: ['hidden'], text: IC.Ikariam.formatToIkaNumber(lo_data.income) } ] }); return ra_tableRows; }; /** * Create the new upkeep reduction table. * * @param {element[]} ia_oldUpkeepReductionTables * The old upkeep tables. */ var _lf_createNewTable = function(ia_oldUpkeepReductionTables) { var le_shortTable = IC.myGM.addElement('table', ia_oldUpkeepReductionTables[0].parentNode, { 'id': 'balance', 'classes': ['table01', 'border', 'left'] }, null, ia_oldUpkeepReductionTables[0]); var la_tableRows = _lf_prepareTableRows(ia_oldUpkeepReductionTables); la_tableRows.forEach(function(io_rowData) { _go_generalFunctions.createTableRow(le_shortTable, io_rowData.classes, io_rowData.cells, io_rowData.isHeadRow); }); IC.myGM.addElement('hr', ia_oldUpkeepReductionTables[0].parentNode, {}, null, ia_oldUpkeepReductionTables[0]); }; /** * Toggle the status of an old upkeep table (collapsed / non-collapsed). */ var _lf_toggleUpkeepReductionTable = function() { IC.myGM.toggleShowHideButton(this); var la_rows = IC.myGM.$$('tr:not(:first-child)', this.parentNode.parentNode.parentNode); la_rows.forEach(function(ie_row) { ie_row.classList.toggle('invisible'); }); // Adjust the size of the Scrollbar. IC.ika.controller.adjustSizes(); }; /** * Minimize the old upkeep tables and make them collapsable. * * @param {element[]} ia_oldUpkeepReductionTables * The old upkeep tables to collapse. */ var _lf_minimizeOldTables = function(ia_oldUpkeepReductionTables) { for(var i = 0; i < ia_oldUpkeepReductionTables.length; i++) { var la_rows = IC.myGM.$$('tr', ia_oldUpkeepReductionTables[i]); la_rows.forEach(function(ie_row, ii_index) { if(ii_index !== 0) ie_row.classList.add('invisible'); }); var le_buttonParent = IC.myGM.$('th', la_rows[0]); IC.myGM.addElement('div', le_buttonParent, { 'class': 'maximizeImg', 'style': [['cssFloat', 'left']], 'title': IC.Language.$('general.expand'), 'click': _lf_toggleUpkeepReductionTable }, null, le_buttonParent.firstChild); } }; /** * Callback to show the short upkeep reduction table. */ var _lf_doShowShortTable = function() { var la_oldUpkeepReductionTables = IC.myGM.$$('.upkeepReductionTable'); _lf_createNewTable(la_oldUpkeepReductionTables); _lf_minimizeOldTables(la_oldUpkeepReductionTables); // Adjust the size of the Scrollbar. IC.ika.controller.adjustSizes(); }; /** * Update the settings to execute the callback or delete the handler. * * @param {boolean} ib_showShortTable * If the user selected the checkbox to show the short upkeep reduction table. */ this.updateSettings = function(ib_showShortTable) { if(ib_showShortTable === true) { IC.RefreshHandler.add('finances', 'shortUpkeepReductionTable', function() { _lf_doShowShortTable(); }); return; } IC.RefreshHandler.remove('finances', 'shortUpkeepReductionTable'); }; }; // Show the income also on top in finance popup. IC.Options.addCheckbox('showIncomeOnTop', 'diverseOptions', 1, true, IC.Language.$('finance.options.showIncomeOnTop'), { changeCallback: _go_incomeOnTop.updateSettings }); // Short overview upkeep reduction table in finance popup. IC.Options.addCheckbox('shortUpkeepReductionTable', 'diverseOptions', 1, true, IC.Language.$('finance.options.shortUpkeepReductionTable'), { changeCallback: _go_shortUpkeepReductionTable.updateSettings }); // Add a divider line. IC.Options.addLine('diverseOptions', 1); })(); IC.con.timeStamp('IkariamEnhancedUI: finance functions created'); // Functions for missing resources. (function() { /** * Storage for the missing ressources functions. * * @type {object} */ var _go_showMissingResources = new function() { /** * Update the information in the missing resources wrappers. * * @param {boolean} ib_isUpdateView * If the update is in the update view. */ var _lf_updateInformation = function(ib_isUpdateView) { var la_currentResources = [ IC.ika.getModel().currentResources.resource, // Wood. IC.ika.getModel().currentResources[1], // Wine. IC.ika.getModel().currentResources[2], // Marble. IC.ika.getModel().currentResources[3], // Crystal. IC.ika.getModel().currentResources[4] // Sulfur. ]; var lb_showPositiveNumbers = IC.Options.getOption('missingResources', 'showPositive') === true && ib_isUpdateView === true; var lb_showMissingColoured = IC.Options.getOption('missingResources', 'showColoured'); var ls_resourcesPattern = '%resources%'; if(ib_isUpdateView !== true) ls_resourcesPattern = ' (' + ls_resourcesPattern + ')'; for(var i = 0; i < IC.Ikariam.resourceNames.length; i++) { var la_missingWrappers = IC.myGM.$$('.' + IC.myGM.prefix + 'missingResources' + IC.Ikariam.resourceNames[i]); if(!!la_missingWrappers) { for(var k = 0; k < la_missingWrappers.length; k++) { var le_neededWrapper = la_missingWrappers[k].previousSibling; var li_missing = la_currentResources[i] - IC.Ikariam.getInt(le_neededWrapper.nodeValue); if(li_missing < 0 || lb_showPositiveNumbers === true) { var ls_formattedMissingValue = IC.Ikariam.formatToIkaNumber(li_missing, lb_showMissingColoured, true); la_missingWrappers[k].innerHTML = ls_resourcesPattern.replace(/\%resources\%/, ls_formattedMissingValue); } else { la_missingWrappers[k].innerHTML = ''; } } } } }; /** * Add the missing resources wrappers. * * @param {boolean} ib_isUpdateView * If the wrappers are added to the update view. */ var _lf_addMissingWrappers = function(ib_isUpdateView) { var ls_wrapperSelector = '#buildingGround .resources'; if(ib_isUpdateView === true) ls_wrapperSelector = '#sidebar .resources'; var la_wrappers = IC.myGM.$$(ls_wrapperSelector); for(var i = 0; i < la_wrappers.length; i++) { for(var k = 0; k < IC.Ikariam.resourceNames.length; k++) { var le_resourceNode = IC.myGM.$('.' + IC.Ikariam.resourceNames[k], la_wrappers[i]); if(!!le_resourceNode) { IC.myGM.addElement('span', le_resourceNode, { 'classes': ['missingResources', 'missingResources' + IC.Ikariam.resourceNames[k]] }, true); } } } _lf_updateInformation(ib_isUpdateView); }; /** * Update the missing resources in building ground popup. */ var _lf_doUpdateInBuildingView = function() { if(!IC.myGM.$('#buildingGround_c')) { IC.Observer.remove('missingResourcesBuilding'); return; } _lf_updateInformation(false); }; /** * Update the missing resources in update view. */ var _lf_doUpdateInUpdateView = function() { if(!IC.myGM.$('#buildingUpgrade')) { IC.Observer.remove('missingResourcesUpdate'); return; } _lf_updateInformation(true); }; /** * Show the missing resources in building ground popup. */ var _lf_doShowInBuildingGround = function() { _lf_addMissingWrappers(false); IC.Observer.add('missingResourcesBuilding', IC.myGM.$('#cityResources'), { childList: true, subtree: true }, _lf_doUpdateInBuildingView, _lf_doUpdateInBuildingView); }; /** * Show the missing resources in update view. */ var _lf_doShowInUpdateView = function() { if(!IC.myGM.$('#buildingUpgrade') || IC.myGM.$$('.' + IC.myGM.prefix + 'missingResources').length > 0) return; _lf_addMissingWrappers(true); IC.Observer.add('missingResourcesUpgrade', IC.myGM.$('#cityResources'), { childList: true, subtree: true }, _lf_doUpdateInUpdateView, _lf_doUpdateInUpdateView); }; /** * Update the settings to execute the callback or delete the handler. * * @param {boolean} ib_showMissingResources * If the user selected the checkbox to show the missing resources info. */ this.updateSettings = function(ib_showMissingResources) { if(ib_showMissingResources === true) { IC.RefreshHandler.add('buildingGround', 'showMissingResources', _lf_doShowInBuildingGround); IC.RefreshHandler.add('%', 'showMissingResources', _lf_doShowInUpdateView); IC.myGM.addStyle( '#sidebar #buildingUpgrade ul.resources li { width: 120px; } \ #sidebar #buildingUpgrade ul.resources li.time { width: 60px !important; } \ #sidebar .' + IC.myGM.prefix + 'missingResources { float: right; }', 'showMissingResources' ); return; } IC.RefreshHandler.remove('buildingGround', 'showMissingResources'); IC.RefreshHandler.remove('%', 'showMissingResources'); IC.myGM.removeStyle('showMissingResources'); }; }; IC.Options.addWrapper('missingResources', IC.Language.$('missingResources.options.wrapperTitle')); // Show missing resources in upgrade / building view. IC.Options.addCheckbox('show', 'missingResources', 1, true, IC.Language.$('missingResources.options.show'), { changeCallback: _go_showMissingResources.updateSettings }); // Disable coloring of the missing resources. IC.Options.addCheckbox('showPositive', 'missingResources', 2, true, IC.Language.$('missingResources.options.showPositive'), {}); // Show only missing ressources, not also remaining. IC.Options.addCheckbox('showColoured', 'missingResources', 2, true, IC.Language.$('missingResources.options.showColoured'), {}); })(); IC.con.timeStamp('IkariamEnhancedUI: missing resource functions created'); // Functions for tooltips. (function() { /** * Storage for the autoshow tootips functions. * * @type {object} */ var _go_autoshowTooltips = new function() { /** * General function for autowhow. * * @param {string} onclickWrapperClass * The class of the wrapper which has the onclik attribute set. */ var _lf_autoshowTooltipsGeneral = function(onclickWrapperClass) { IC.myGM.$$('.' + onclickWrapperClass).forEach(function(onclickWrapper) { var onclickFunction = onclickWrapper.onclick; onclickWrapper.onclick = 'return false;'; var newHandler = IC.myGM.$('.magnify_icon', onclickWrapper); if(!newHandler) newHandler = onclickWrapper; newHandler.addEventListener('mouseover', function(e) { IC.ika.controller.captureMousePosition(e); onclickFunction(e); }, true); }); IC.myGM.$('.templateView .mainContent').addEventListener('click', function() { IC.win.$(document).trigger("closeExclusiveInfo"); }, true); }; /** * Autmatically show tooltips in alliance member lists. */ var _lf_doAutoshowTooltipsAlliance = function() { _lf_autoshowTooltipsGeneral('cityInfo'); }; /** * Autmatically show tooltips in military advisor. */ var _lf_doAutoshowTooltipsMilitaryAdvisor = function() { if(IC.Options.getOption('moduleOptions', 'showDirectMilitaryTooltips') === true) return; _lf_autoshowTooltipsGeneral('spyMilitary'); }; /** * Update the settings to execute the callback or delete the handler. * * @param {boolean} autoshowTooltips * If the user selected the checkbox to autoshow tooltips. */ this.updateSettings = function(autoshowTooltips) { var alliancePopupIds = ['diplomacyAllyMemberlist', 'embassy']; if(autoshowTooltips === true) { IC.RefreshHandler.add('militaryAdvisor', 'autoshowTooltips', _lf_doAutoshowTooltipsMilitaryAdvisor); IC.RefreshHandler.add(alliancePopupIds, 'autoshowTooltips', _lf_doAutoshowTooltipsAlliance); return; } IC.RefreshHandler.remove('militaryAdvisor', 'autoshowTooltips'); IC.RefreshHandler.remove(alliancePopupIds, 'autoshowTooltips'); }; }; /** * Storage for the direct military tooltip functions. * * @type {object} */ var _go_directMilitaryTooltips = new function() { /** * Storage for the class ids and their corresponding translations. Each class is a property of the object with the translation stored in it. * * @type {object} */ var _lo_idTranslation = {}; /** * Fill the id translation object. */ var _lf_fillIdTranslation = function() { if(_lo_idTranslation.length === 0) return; var la_troops = ['swordsman', 'phalanx', 'archer', 'marksman', 'mortar', 'slinger', 'catapult', 'ram', 'steamgiant', 'bombardier', 'cook', 'medic', 'gyrocopter', 'spearman', 'spartan']; var la_ships = ['balliasta', 'catapult', 'flamethrower', 'mortar', 'ram', 'steamboat', 'rocketship', 'submarine', 'paddlespeedship', 'balloncarrier', 'tender', 'transport', 'premium_transport']; var la_resources = IC.Ikariam.resourceNames; la_resources.push('gold'); la_troops.forEach(function(is_troopName) { _lo_idTranslation[is_troopName] = IC.Language.$('diverse.name.unit.' + is_troopName); }); la_ships.forEach(function(is_shipName) { _lo_idTranslation['ship_' + is_shipName] = IC.Language.$('diverse.name.ship.' + is_shipName.replace('premium_', '')); }); la_resources.forEach(function(is_resourceName) { _lo_idTranslation[is_resourceName] = IC.Language.$('diverse.name.resource.' + is_resourceName); }); }; /** * Hide the number of ships for the own peaceful missions (trade / transport). */ var _lf_hideShipNumberOwnPeacefulMissions = function() { var la_ownEventTableRows = IC.myGM.$$('#js_MilitaryMovementsFleetMovementsTable .military_event_table tr.own'); la_ownEventTableRows.forEach(function(ie_tableRow) { var le_missionDiv = IC.myGM.$('td:nth-child(1) div.mission_icon', ie_tableRow); var lb_peacefulMission = le_missionDiv.classList.contains('transport') || le_missionDiv.classList.contains('trade'); if(lb_peacefulMission === true) { IC.myGM.$('td:nth-child(4) div', ie_tableRow).classList.add('invisible'); } }); }; /** * Show the military tooltips directly. */ var _lf_doShowDirectMilitaryTooltips = function() { _lf_fillIdTranslation(); _lf_hideShipNumberOwnPeacefulMissions(); IC.myGM.$$('.spyMilitary').forEach(function(ie_movementWrapper) { ie_movementWrapper.onclick = 'return false;'; }); var le_movementsTable = IC.myGM.$('#js_MilitaryMovementsFleetMovementsTable'); IC.myGM.forEach(_lo_idTranslation, function(is_classId, is_translation) { IC.myGM.$$('.icon40.' + is_classId, le_movementsTable).forEach(function(ie_detailIcon) { ie_detailIcon.title = is_translation; }); }); }; /** * Update the settings to execute the callback or delete the handler. * * @param {boolean} ib_showDirectMilitaryTooltips * If the user selected the checkbox to show the military tooltips directly. */ this.updateSettings = function(ib_showDirectMilitaryTooltips) { if(ib_showDirectMilitaryTooltips === true) { IC.RefreshHandler.add('militaryAdvisor', 'showDirectMilitaryTooltips', _lf_doShowDirectMilitaryTooltips); IC.myGM.addStyle( '#js_MilitaryMovementsFleetMovementsTable .military_event_table .magnify_icon { background-image: none; cursor: default; width: 240px; } \ #js_MilitaryMovementsFleetMovementsTable .military_event_table .magnify_icon .infoTip { display: inline; position: relative; padding: 0px; border: none; } \ #js_MilitaryMovementsFleetMovementsTable .military_event_table .magnify_icon .infoTip h5 { display: none; } \ #js_MilitaryMovementsFleetMovementsTable .military_event_table .icon40 { background-size: 25px 25px; background-color: transparent; padding: 26px 3px 0px 3px; width: 30px; } \ #js_MilitaryMovementsFleetMovementsTable .military_event_table .icon40.resource_icon { background-size: 20px 16px; }', 'showDirectMilitaryTooltips' ); return; } IC.RefreshHandler.remove('militaryAdvisor', 'showDirectMilitaryTooltips'); IC.myGM.removeStyle('showDirectMilitaryTooltips'); }; }; // Show alliance / military tooltips directly. IC.Options.addCheckbox('autoshowTooltips', 'diverseOptions', 1, true, IC.Language.$('tooltips.options.autoshow'), { changeCallback: _go_autoshowTooltips.updateSettings }); // Show military tooltips directly. IC.Options.addCheckbox('showDirectMilitaryTooltips', 'diverseOptions', 1, false, IC.Language.$('tooltips.options.showDirectInMilitaryAdvisor'), { changeCallback: _go_directMilitaryTooltips.updateSettings }); // Add a divider line. IC.Options.addLine('diverseOptions', 1); })(); IC.con.timeStamp('IkariamEnhancedUI: tooltip functions created'); // Zoom function. (function() { /** * Storage for the zoom functions. * * @type {object} */ var _go_zoomView = new function() { /** * Storage for the minimum zoom factor. * * @type {int} */ var _li_minZoom = 55; /** * Storage for the maximum zoom factor. * * @type {int} */ var _li_maxZoom = 150; /** * Storage for the zoom step size. * * @type {int} */ var _li_zoomStep = 5; /** * Storage for the actual mousewheel callback. * * @type {function} */ var _lf_mousewheelCallbackStorage = IC.ika.getController().mouseScrollHandle; /** * Getter for the minimum zoom factor. * * @return {int} * The minimum zoom factor. */ this.__defineGetter__('minZoom', function() { return _li_minZoom; }); /** * Getter for the maximum zoom factor. * * @return {int} * The maximum zoom factor. */ this.__defineGetter__('maxZoom', function() { return _li_maxZoom; }); /** * Getter for the zoom step size. * * @return {int} * The zoom step size. */ this.__defineGetter__('zoomStep', function() { return _li_zoomStep; }); /** * Initialize the zoom bounds (min and max zoom). */ var _lf_initBounds = function() { var li_minZoom = Math.round(IC.ika.worldview_scale_min * 100); if(li_minZoom % 5 != 0) li_minZoom = li_minZoom + (5 - (li_minZoom % 5)); _li_minZoom = li_minZoom; IC.ika.worldview_scale_min = _li_minZoom / 100; IC.ika.worldview_scale_max = _li_maxZoom / 100; }; /** * Zoom the world view, as there is no function provided by Ikariam. * * @param {decimal} in_zoomFactor * The zoom factor as decimal number (1 =^= 100%) */ var _lf_zoomWorldView = function(in_zoomFactor) { var li_translateXY = (100 - 100 / in_zoomFactor) / 2; var ls_heightWidth = (100 / in_zoomFactor) + '% !important'; var ls_transformString = 'scale(' + in_zoomFactor + ') translate(' + li_translateXY + '%, ' + li_translateXY + '%)'; IC.myGM.addStyle( '#scrollcover { transform: ' + ls_transformString + '; -webkit-transform: ' + ls_transformString + '; height: ' + ls_heightWidth + '; width: ' + ls_heightWidth + '; }', 'zoomWorld', true ); var le_map = IC.myGM.$('#map1'); le_map.style.top = '0px'; le_map.style.left = '0px'; }; /** * Rescale the badges and symbols. * * @param {decimal} in_zoomFactorNumber * The zoom factor as decimal number (1 =^= 100%) */ var _lf_scaleChildren = function(in_zoomFactorNumber) { var ls_transformString = 'transform: scale(' + 1 / in_zoomFactorNumber + '); -webkit-transform: scale(' + 1 / in_zoomFactorNumber + ');'; var ls_style = ''; if(IC.Ikariam.view == 'world') { var ls_ownerState = ''; if(in_zoomFactorNumber < 1) ls_ownerState = ', .ownerState'; ls_style = '.islandTile .wonder, .islandTile .tradegood, .islandTile .cities, .islandTile .piracyInRange' + ls_ownerState + ' { ' + ls_transformString + ' } \ .islandTile .cities { bottom: 10px !important; }'; } if(IC.Ikariam.view == 'island') { var ls_movePiracy = 'transform: translate(0px, -' + (1 - in_zoomFactorNumber) * 20 + 'px) scale(' + 1 / in_zoomFactorNumber + ');'; ls_style = '.cityLocation .scroll_img, .cityLocationScroll .scroll_img { ' + ls_transformString + ' } \ .cityLocation .piracyRaid { ' + ls_movePiracy + ' }'; } if(IC.Ikariam.view == 'town') ls_style = '.timetofinish { ' + ls_transformString + ' }'; IC.myGM.addStyle(ls_style, 'scaleChildren', true); }; /** * Update the zoom in and zoom out button and the percentage in the middle. * * @param {int} ii_zoomFactor * The zoom factor as percentage. */ var _lf_updateZoomButtons = function(ii_zoomFactor) { var le_zoomFactorDiv = IC.myGM.$('#' + IC.myGM.prefix + 'zoomFactor'); var le_zoomIn = IC.myGM.$('#' + IC.myGM.prefix + 'zoomIn'); var le_zoomOut = IC.myGM.$('#' + IC.myGM.prefix + 'zoomOut'); if(!!le_zoomFactorDiv) { le_zoomFactorDiv.innerHTML = ii_zoomFactor + '%'; } if(!!le_zoomIn) { le_zoomIn.style.visibility = ''; if(ii_zoomFactor >= _li_maxZoom) le_zoomIn.style.visibility = 'hidden'; } if(!!le_zoomOut) { le_zoomOut.style.visibility = ''; if(ii_zoomFactor <= _li_minZoom) le_zoomOut.style.visibility = 'hidden'; } }; /** * Calculate the zoom factor as decimal number and execute the zoom function. If it is requestet, call also the rescale function for child elements. * * @param {int} ii_zoomFactor * The zoom factor as percentage. */ var _lf_zoomView = function(ii_zoomFactor) { var ln_zoomFactorNumber = ii_zoomFactor / 100.0; var li_scale = 0; if(IC.Ikariam.view == 'island') li_scale = IC.ika.worldview_scale_island; if(IC.Ikariam.view == 'town') li_scale = IC.ika.worldview_scale_city; if(IC.Ikariam.view == 'world') { _lf_zoomWorldView(ln_zoomFactorNumber); } else { var li_stepNumber = Math.round((ln_zoomFactorNumber - li_scale) / .05); var le_worldview = IC.myGM.$('#worldview'); var li_posX = le_worldview.offsetLeft + le_worldview.offsetWidth / 2; var li_posY = le_worldview.offsetTop + le_worldview.offsetHeight / 2; IC.ika.controller.scaleWorldMap(li_stepNumber, li_posX, li_posY); } if(IC.Options.getOption('zoom', IC.Ikariam.view + 'ScaleChildren') === true) _lf_scaleChildren(ln_zoomFactorNumber); }; /** * Ensure that the requested zoom factor is in the bounds and update the view. * * @param {int} ii_zoomFactor * The zoom factor as percentage. */ var _lf_zoom = function(ii_zoomFactor) { if(ii_zoomFactor > _li_maxZoom) ii_zoomFactor = _li_maxZoom; if(ii_zoomFactor < _li_minZoom) ii_zoomFactor = _li_minZoom; IC.Options.setOption('zoom', IC.Ikariam.view + 'Factor', ii_zoomFactor); _lf_updateZoomButtons(ii_zoomFactor); _lf_zoomView(ii_zoomFactor); }; /** * Zoom one step in. */ var _lf_zoomIn = function() { var li_factor = IC.Ikariam.getInt(IC.Options.getOption('zoom', IC.Ikariam.view + 'Factor', 100)) + _li_zoomStep; _lf_zoom(li_factor); }; /** * Zoom one step out. */ var _lf_zoomOut = function() { var li_factor = IC.Options.getOption('zoom', IC.Ikariam.view + 'Factor', 100) - _li_zoomStep; _lf_zoom(li_factor); }; /** * Add the zoom buttons. */ var _lf_addZoomButtons = function() { var le_zoomWrapper = IC.myGM.addElement('div', ge_toolbar, { 'id': 'zoomWrapper' }); IC.myGM.addElement('div', le_zoomWrapper, { 'id': 'zoomIn', 'class': 'maximizeImg', 'title': IC.Language.$('zoom.zoomIn'), 'click': _lf_zoomIn }); IC.myGM.addElement('div', le_zoomWrapper, { 'id': 'zoomFactor', 'title': IC.Language.$('zoom.factor') }); IC.myGM.addElement('div', le_zoomWrapper, { 'id': 'zoomOut', 'class': 'minimizeImg', 'title': IC.Language.$('zoom.zoomOut'), 'click': _lf_zoomOut }); IC.myGM.addStyle( '#' + IC.myGM.prefix + 'zoomWrapper { width: 72px; margin: 0px -5px !important; transform: scale(0.75); scale(0.75); -webkit-transform: scale(0.75); } \ #' + IC.myGM.prefix + 'zoomWrapper > div { display: inline-block; position: relative; } \ #' + IC.myGM.prefix + 'zoomFactor { top: -4px; width: 35px; text-align: center; }', 'zoomButtons' ); }; /** * Set the zoom to 100% if in world view or if it was bigger than 100% and remove the zoom buttons and all styles for the zoom. */ var _lf_resetZoom = function() { if((IC.Ikariam.view == 'island' && IC.ika.worldview_scale_island > 1) || (IC.Ikariam.view == 'town' && IC.ika.worldview_scale_city > 1) || IC.Ikariam.view == 'world') _lf_zoomView(100); IC.ika.worldview_scale_max = 1; IC.myGM.removeElement(IC.myGM.$('#' + IC.myGM.prefix + 'zoomWrapper')); IC.myGM.removeStyle('zoomButtons'); IC.myGM.removeStyle('zoomWorld'); IC.myGM.removeStyle('scaleChildren'); }; /** * Check, if the key are pressed which are required to zoom with the mouse. * * @param {object} io_event * The "event object" with information about the mouse scroll and pressed keys. * * @return {boolean} * If the correct keys were pressed. */ var _lf_keysOK = function(io_event) { var lb_ctrlOK = !!io_event.ctrlKey; if(IC.Options.getOption('zoom', 'ctrlAsAccessKey') === false) lb_ctrlOK = true; var lb_altOK = !!io_event.altKey; if(IC.Options.getOption('zoom', 'altAsAccessKey') === false) lb_altOK = true; var lb_shiftOK = !!io_event.shiftKey; if(IC.Options.getOption('zoom', 'shiftAsAccessKey') === false) lb_shiftOK = true; return lb_ctrlOK && lb_altOK && lb_shiftOK; }; /** * Calculate the delta the mousewheel was turned. * * @param {object} io_event * The "event object" with information about the mouse scroll and pressed keys. * * @return {int} * The delta the mousewheel was moved. */ var _lf_calculateDelta = function(io_event) { var ri_stepNumber = 0; // Get the number of steps to scroll. if(io_event.wheelDelta) ri_stepNumber = io_event.wheelDelta / 120; if (io_event.detail) ri_stepNumber = -io_event.detail / 3; if (io_event.wheelDeltaY !== undefined) ri_stepNumber = io_event.wheelDeltaY / 120; // If the number is between -1 and 0, set it to -1. if(ri_stepNumber < 0) ri_stepNumber = ri_stepNumber > -1 ? -1 : Math.round(ri_stepNumber); // If the number is between 0 and 1, set it to 1. else ri_stepNumber = ri_stepNumber < 1 ? 1 : Math.round(ri_stepNumber); return ri_stepNumber; }; /** * Handler for mousescroll to zoom. * * @param {object} io_event * The "event object" with information about the mouse scroll and pressed keys. * * @return false * If the prevent default method is not available to prevent the default action. */ var _lf_mouseScroll = function(io_event) { if(_lf_keysOK(io_event) === true) { // If the scrolling is horizontally return. if(io_event.axis !== undefined && io_event.axis === io_event.HORIZONTAL_AXIS) return; var li_factor = IC.Ikariam.getInt(IC.Options.getOption('zoom', IC.Ikariam.view + 'Factor')) + _li_zoomStep * _lf_calculateDelta(io_event); _lf_zoom(li_factor); // Prevent the default event. if(io_event.preventDefault) io_event.preventDefault(); else return false; } }; /** * Change the mousewheel listener to a new callback. * * @param {function} if_newCallback * The new callback for the mousewheel listener. */ var _lf_changeMouseWheelListener = function(if_newCallback) { if(_lf_mousewheelCallbackStorage == if_newCallback) return; var ls_scrollDivId = '#worldmap'; if(IC.Ikariam.view == 'world') ls_scrollDivId = '#map1'; if(_lf_mousewheelCallbackStorage == IC.ika.getController().mouseScrollHandle) { // Remove the ikariam mouse wheel listener and add the own. (with the use of Ikariam-jQuery) IC.win.$(ls_scrollDivId).unbind('mousewheel'); var scrollDiv = IC.myGM.$(ls_scrollDivId); scrollDiv.addEventListener('DOMMouseScroll', if_newCallback, false); scrollDiv.addEventListener('mousewheel', if_newCallback, false); } else { var scrollDiv = IC.myGM.$(ls_scrollDivId); scrollDiv.removeEventListener('DOMMouseScroll', _lf_mousewheelCallbackStorage, false); scrollDiv.removeEventListener('mousewheel', _lf_mousewheelCallbackStorage, false); IC.win.$(ls_scrollDivId).on('mousewheel', if_newCallback); } _lf_mousewheelCallbackStorage = if_newCallback; }; /** * Update the settings to execute the callback or delete the handler. * * @param {boolean} ib_zoomView * If the user selected the checkbox to zoom. */ this.updateSettings = function(ib_zoomView) { _lf_initBounds(); _go_zoomOptions.renewFactorSelects(); if(ib_zoomView === true) { _lf_addZoomButtons(); _lf_changeMouseWheelListener(_lf_mouseScroll); _lf_zoom(IC.Options.getOption('zoom', IC.Ikariam.view + 'Factor')); return; } _lf_resetZoom(); _lf_changeMouseWheelListener(IC.ika.getController().mouseScrollHandle); }; }; /** * Storage for the option creation functions. * * @type {object} */ var _go_zoomOptions = new function() { /** * If the zoom wrapper is already created. */ var _lb_zoomWrapperCreated = false; /** * Add the select fields for the zoom factors. */ var _lf_addFactorSelects = function(ib_replace) { var la_options = []; for(var i = _go_zoomView.minZoom; i <= _go_zoomView.maxZoom; i = i + _go_zoomView.zoomStep) { la_options.push({ value: i, label: i + '%' }); } IC.Ikariam.viewNames.forEach(function(is_view, ii_index) { IC.Options.addSelect(is_view + 'Factor', 'zoom', 'factors', 100, IC.Language.$('zoom.options.factor.' + is_view), la_options, { replace: !!ib_replace }); }); }; /** * Add the checkboxes fields for rescaling the badges and icons. */ var _lf_addScaleChildrenCheckboxes = function() { IC.Options.addHTML('scaleChildrenDescription', 'zoom', 'scale', { html: '

' + IC.Language.$('zoom.options.scaleChildren.label') + '

' }); IC.Ikariam.viewNames.forEach(function(is_view) { IC.Options.addCheckbox(is_view + 'ScaleChildren', 'zoom', 'scale', true, IC.Language.$('zoom.options.scaleChildren.' + is_view), {}); }); }; /** * Add the checkboxes for the access keys. */ var _lf_addAccessKeyCheckboxes = function() { IC.Options.addHTML('accessKeyDescription', 'zoom', 'accessKeys', { html: '

' + IC.Language.$('zoom.options.accessKeyLabel') + '

' }); var la_accessKeys = ['ctrl', 'alt', 'shift']; la_accessKeys.forEach(function(is_accessKey) { var lb_defaultEnabled = (is_accessKey == 'ctrl'); IC.Options.addCheckbox(is_accessKey + 'AsAccessKey', 'zoom', 'accessKeys', lb_defaultEnabled, IC.Language.$('general.' + is_accessKey), {}); }); }; /** * Create the zoom options wrapper and add the option elements. */ this.create = function() { _lf_addFactorSelects(); _lf_addScaleChildrenCheckboxes(); _lf_addAccessKeyCheckboxes(); _lb_zoomWrapperCreated = true; }; /** * Recreate the select fields for the zoom factor (and keep the old zoom factor). */ this.renewFactorSelects = function() { if(_lb_zoomWrapperCreated === false) return; _lf_addFactorSelects(true); }; }; IC.Options.addWrapper('zoom', IC.Language.$('zoom.options.wrapperTitle')); // Show missing resources in upgrade / building view. IC.Options.addCheckbox('view', 'zoom', 'general', true, IC.Language.$('zoom.options.zoomView'), { changeCallback: _go_zoomView.updateSettings }); // Add the zoom function settings. _go_zoomOptions.create(); })(); IC.con.timeStamp('IkariamEnhancedUI: zoom functions created'); // Ressource information. (function() { /** * Storage for the style functions for the capacity bar and the direct income. * * @type {object} */ var _go_styleFunctions = new function() { /** * Get the style for the #js_GlobalMenu_ elements. * * @param {string} is_incomeStyle * How the income is styled. * * @return {string} * The style string. */ var _lf_getGlobalMenuStyle = function(is_incomeStyle) { if(is_incomeStyle != 'alignLeft') return '#js_GlobalMenu_wood, #js_GlobalMenu_wine, #js_GlobalMenu_marble, #js_GlobalMenu_crystal, #js_GlobalMenu_sulfur { padding-right: 4px; } '; return ''; }; /** * Gets the style for the separation of the resource values. * * @param {string} is_incomeStyle * How the income is styled. * * @return {string} * The style string. */ var _lf_getSeparationStyle = function(is_incomeStyle) { if(is_incomeStyle == 'withSeparation') return '#resources_wood, #resources_wine, #resources_marble, #resources_glass { border-right: 1px dotted #542C0F; } '; return ''; }; /** * Get styles which are independent of the activation of the cpacity bar or direct income. * * @param {string} is_incomeStyle * How the income is styled. * * @return {string} * The style string. */ var _lf_getGeneralStyles = function(is_incomeStyle) { var ls_globalMenuStyle = _lf_getGlobalMenuStyle(is_incomeStyle); var ls_separationStyle = _lf_getSeparationStyle(is_incomeStyle); return ls_globalMenuStyle + ls_separationStyle; }; /** * Get the style for the capacity bar "wrapper". * * @param {string} is_capacityBarOrientation * The orientation of the capacity bar. * @param {string} is_incomeStyle * How the income is styled. * * @return {string} * The style string. */ var _lf_getCapacityBarStyle = function(is_capacityBarOrientation, is_incomeStyle) { var ls_height = 'height: 4px; '; var ls_width = 'width: 79px;'; var ls_right = 'right: 4px; '; var ls_marginLeft = ''; if(is_capacityBarOrientation == 'horizontal') ls_width = 'width: 50px; '; if(is_capacityBarOrientation == 'vertical') { ls_height = 'height: 21px; '; ls_width = 'width: 4px; '; ls_right = ''; if(is_incomeStyle == 'alignLeft') ls_marginLeft = 'margin-left: -7px; '; } return '.' + IC.myGM.prefix + 'capacityInformation { position: absolute; bottom: 4px; ' + ls_height + ls_width + ls_right + ls_marginLeft + '} '; }; /** * Get the style for the capacity bar with a border. * * @param {string} is_capacityBarOrientation * The orientation of the capacity bar. * * @return {string} * The style string. */ var _lf_getCapacityBarWithBorderStyle = function(is_capacityBarOrientation) { var ls_height = 'height: 3px; '; var ls_width = 'width: 78px; '; var ls_right = 'right: 3px; '; if(is_capacityBarOrientation == 'horizontal') ls_width = 'width: 50px; '; if(is_capacityBarOrientation == 'vertical') { ls_height = 'height: 20px; '; ls_width = 'width: 3px; '; ls_right = ''; } return '.' + IC.myGM.prefix + 'capacityInformation.' + IC.myGM.prefix + 'border { border: 1px inset #906646; bottom: 3px; ' + ls_height + ls_width + ls_right + '} '; }; /** * Get the style for the capacity bar. * * @param {string} is_capacityBarOrientation * The orientation of the capacity bar. * @param {string} is_incomeStyle * How the income is styled. * * @return {string} * The style string. */ var _lf_getCapacityStyle = function(is_capacityBarOrientation, is_incomeStyle) { var ls_prefix = IC.myGM.prefix; var ls_barStyle = '.' + ls_prefix + 'bar { height: 100%; width: 100%; bottom: 0px; position: absolute; } \ .' + ls_prefix + 'bar.' + ls_prefix + 'red { background-color: #AA0000; } \ .' + ls_prefix + 'bar.' + ls_prefix + 'yellow { background-color: #FFD700; } \ .' + ls_prefix + 'bar.' + ls_prefix + 'green { background-color: #669900; }'; var ls_capacityStyle = _lf_getCapacityBarStyle(is_capacityBarOrientation, is_incomeStyle); var ls_capacityBorderStyle = _lf_getCapacityBarWithBorderStyle(is_capacityBarOrientation); return ls_barStyle + ls_capacityStyle + ls_capacityBorderStyle; }; /** * Get the style for the direct hourly income in the town view. * * @param {boolean} ib_capacityBarActive * If the capacity bar is shown. * @param {string} is_capacityBarOrientation * The orientation of the capacity bar. * @param {string} is_incomeStyle * How the income is styled. * * @return {string} * The style string. */ var _lf_getHourlyIncomeStyle = function(ib_capacityBarActive, is_capacityBarOrientation, is_incomeStyle) { var ls_display = 'display: block; '; var ls_fontSize = 'font-size: 11px; '; var ls_paddingRight = 'padding-right: 4px; '; if(ib_capacityBarActive === true && is_capacityBarOrientation !== 'horizontalFull') ls_fontSize = 'font-size: 9px; '; if(is_incomeStyle == 'alignLeft') ls_paddingRight = ''; return '.' + IC.myGM.prefix + 'hourlyIncomeResource { ' + ls_display + ls_fontSize + ls_paddingRight + '} '; }; /** * Get some resource styles which are only set if the capacity bar is active. * * @param {boolean} ib_directIncomeActive * If the direct income is shown. * @param {string} is_capacityBarOrientation * The orientation of the capacity bar. * @param {string} is_incomeStyle * How the income is styled. * * @return {string} * The style string. */ var _lf_getResourceStyleCapacityActive = function(ib_directIncomeActive, is_capacityBarOrientation, is_incomeStyle) { var ls_height = ''; var ls_top = ''; var ls_paddingLeft = ''; var ls_fontSize = ''; if(is_capacityBarOrientation == 'horizontalFull') { ls_height = 'height: 32px !important; '; ls_top = 'top: -2px !important; '; } if(is_capacityBarOrientation == 'vertical' && is_incomeStyle == 'alignLeft') ls_paddingLeft = 'padding-left: 38px !important; '; if(is_capacityBarOrientation == 'vertical' || (ib_directIncomeActive === true && is_capacityBarOrientation != 'horizontalFull')) ls_fontSize = 'font-size: 11px; '; return ls_height + ls_top + ls_paddingLeft + ls_fontSize; }; /** * Get the line height for the sored resources. * * @param {boolean} ib_capacityBarActive * If the capacity bar is shown. * @param {boolean} ib_directIncomeActive * If the direct income is shown. * @param {string} is_capacityBarOrientation * The orientation of the capacity bar. * * @return {string} * The style string. */ var _lf_getResourceStyleLineHeigth = function(ib_capacityBarActive, ib_directIncomeActive, is_capacityBarOrientation) { if(ib_directIncomeActive === true) { if(ib_capacityBarActive === true && is_capacityBarOrientation == 'horizontal') return 'line-height: 9px !important; '; return 'line-height: 11px !important; '; } if(is_capacityBarOrientation == 'horizontal') return 'line-height: 12px !important; '; if(is_capacityBarOrientation == 'vertical') return 'line-height: 24px !important; '; return ''; }; /** * Get the style for the resource fields. * * @param {boolean} ib_capacityBarActive * If the capacity bar is shown. * @param {boolean} ib_directIncomeActive * If the direct income is shown. * @param {string} is_capacityBarOrientation * The orientation of the capacity bar. * @param {string} is_incomeStyle * How the income is styled. * * @return {string} * The style string. */ var _lf_getResourceStyle = function(ib_capacityBarActive, ib_directIncomeActive, is_capacityBarOrientation, is_incomeStyle) { var ls_align = 'text-align: right; '; var ls_capacityActive = ''; var ls_lineHeight = _lf_getResourceStyleLineHeigth(ib_capacityBarActive, ib_directIncomeActive, is_capacityBarOrientation); if(is_incomeStyle == 'alignLeft') ls_align = ''; if(ib_capacityBarActive === true) ls_capacityActive = _lf_getResourceStyleCapacityActive(ib_directIncomeActive, is_capacityBarOrientation, is_incomeStyle); return '#resources_wood, #resources_wine, #resources_marble, #resources_glass, #resources_sulfur { ' + ls_align + ls_lineHeight + ls_capacityActive + ' } '; }; /** * Set the styles for the direct income and the capacity bar. */ this.setStyles = function() { var lb_capacityBarActive = IC.Options.getOption('resourceInformation', 'showCapacityBar'); var lb_directIncomeActive = IC.Options.getOption('resourceInformation', 'showDirectIncome'); // If not both of the checkboxes have been defined yet, do nothing! if(lb_capacityBarActive === null || lb_directIncomeActive === null) return; if(lb_capacityBarActive === false && lb_directIncomeActive === false) { IC.myGM.removeStyle('resourceInformation'); return; } var ls_capacityBarOrientation = IC.Options.getOption('resourceInformation', 'capacityBarOrientation'); var ls_incomeStyle = IC.Options.getOption('resourceInformation', 'incomeStyle'); var ls_incomeStyleString = _lf_getGeneralStyles(ls_incomeStyle) + _lf_getResourceStyle(lb_capacityBarActive, lb_directIncomeActive, ls_capacityBarOrientation, ls_incomeStyle); if(lb_capacityBarActive === true) ls_incomeStyleString += _lf_getCapacityStyle(ls_capacityBarOrientation, ls_incomeStyle); if(lb_directIncomeActive === true) ls_incomeStyleString += _lf_getHourlyIncomeStyle(lb_capacityBarActive, ls_capacityBarOrientation, ls_incomeStyle); IC.myGM.addStyle(ls_incomeStyleString, 'resourceInformation', true); }; }; /** * Storage for the functions for the capacity bar. * * @type {object} */ var _go_capacityInformation = new function() { /** * Update the capacity information bars. */ var _lf_updateFields = function() { if(IC.ika.model.isOwnCity === false) return; var la_capacityInformation = []; var la_resourceIdentifiers = ['resource', 1, 2, 3, 4]; la_resourceIdentifiers.forEach(function(im_identifier, ii_index) { la_capacityInformation.push({ warehouse: IC.Ikariam.getInt(IC.ika.getModel().maxResources[im_identifier]), branchOffice: IC.Ikariam.getInt(IC.ika.getModel().branchOfficeResources[im_identifier]), current: IC.Ikariam.getInt(IC.ika.getModel().currentResources[im_identifier]) }); }); var ls_prefix = '#' + IC.myGM.prefix; var ls_styleToChange = 'width'; if(IC.Options.getOption('resourceInformation', 'capacityBarOrientation') == 'vertical') ls_styleToChange = 'height'; la_capacityInformation.forEach(function(io_capacity, ii_index) { var ls_resource = IC.Ikariam.resourceNames[ii_index]; var li_warehousePercentage = 100; var li_resourcePercentage = io_capacity.current / io_capacity.warehouse * 100; if(IC.Options.getOption('resourceInformation', 'capacityBarShowBranchOfficeResources') === true) { var li_maximumCapacity = io_capacity.warehouse + io_capacity.branchOffice; li_warehousePercentage = io_capacity.warehouse / li_maximumCapacity * 100; li_resourcePercentage = io_capacity.current / li_maximumCapacity * 100; } IC.myGM.$(ls_prefix + 'maxCapacity' + ls_resource).style[ls_styleToChange] = '100%'; IC.myGM.$(ls_prefix + 'warehouseCapacity' + ls_resource).style[ls_styleToChange] = li_warehousePercentage + '%'; IC.myGM.$(ls_prefix + 'currentResource' + ls_resource).style[ls_styleToChange] = li_resourcePercentage + '%'; }); }; /** * Add the capacity information bars. */ var _lf_addFields = function() { var la_classes = ['capacityInformation']; if(IC.Options.getOption('resourceInformation', 'capacityBarHasBorder') === true) la_classes.push('border'); IC.Ikariam.resourceNames.forEach(function(is_resource) { var le_wrapper = IC.myGM.addElement('div', IC.myGM.$('#resources_' + is_resource), { 'id': 'capacityInfo' + is_resource, 'classes': la_classes }, true); IC.myGM.addElement('div', le_wrapper, { 'id': 'maxCapacity' + is_resource, 'classes': ['bar', 'yellow'] }, true); IC.myGM.addElement('div', le_wrapper, { 'id': 'warehouseCapacity' + is_resource, 'classes': ['bar', 'green'] }, true); IC.myGM.addElement('div', le_wrapper, { 'id': 'currentResource' + is_resource, 'classes': ['bar', 'red'] }, true); }); _lf_updateFields(); }; /** * Remove the capacity information bars. */ var _lf_removeFields = function() { IC.myGM.removeElement(IC.myGM.$$('.' + IC.myGM.prefix + 'capacityInformation')); }; /** * Update the settings to execute the callback or delete the handler. * * @param {boolean} ib_showCapacityBar * If the user selected the checkbox to show the capacity information. */ this.updateSettings = function(ib_showCapacityBar) { _go_styleFunctions.setStyles(); if(ib_showCapacityBar === true) { _lf_addFields(); IC.Observer.add('updateCapacityBar', IC.myGM.$('#cityResources'), { childList: true, subtree: true }, _lf_updateFields, _lf_updateFields); return; } IC.Observer.remove('updateCapacityBar'); _lf_removeFields(); }; }; /** * Storage for the functions for the direct income. * * @type {object} */ var _go_directIncome = new function() { /** * Storage for the tradegood of the last town selected. * * @type {int} */ var _li_lastTradegood = null; /** * Delete the data of the tradegood of the last town selected. * * @param {string} is_hourlyPrefix * The prefix for the hourly income wrapper selector. * @param {string} is_dailyPrefix * The prefix for the daily income wrapper selector. */ var _lf_deleteLastTradegoodData = function(is_hourlyPrefix, is_dailyPrefix) { IC.myGM.$(is_hourlyPrefix + IC.Ikariam.resourceNames[_li_lastTradegood]).innerHTML = ''; IC.myGM.$(is_dailyPrefix + IC.Ikariam.resourceNames[_li_lastTradegood]).innerHTML = ''; if(_li_lastTradegood !== 1) { IC.myGM.$(is_hourlyPrefix + IC.Ikariam.resourceNames[_li_lastTradegood]).classList.add('invisible'); IC.myGM.$(is_dailyPrefix + 'Wrapper' + IC.Ikariam.resourceNames[_li_lastTradegood]).classList.add('invisible'); } }; /** * Update the direct icome fields. * * @param {boolean} ib_firstRun * If this is the first run after adding the fields. */ var _lf_updateFields = function(ib_firstRun) { if(IC.ika.model.isOwnCity === false) return; var ls_hourlyPrefix = '#' + IC.myGM.prefix + 'hourlyIncomeResource'; var ls_dailyPrefix = '#' + IC.myGM.prefix + 'dailyIncomeResource'; if(_li_lastTradegood !== null) _lf_deleteLastTradegoodData(ls_hourlyPrefix, ls_dailyPrefix); var li_producedTradegood = IC.Ikariam.getInt(IC.ika.getModel().producedTradegood); var li_tradegoodProduction = IC.ika.getModel().tradegoodProduction * 3600 + 0.001; var li_woodProduction = IC.ika.getModel().resourceProduction * 3600 + 0.001; var li_wineSpending = IC.ika.getModel().wineSpendings; var li_producesWine = IC.ika.getModel().cityProducesWine; var ls_tradegoodName = IC.Ikariam.resourceNames[li_producedTradegood]; IC.myGM.$(ls_hourlyPrefix + IC.Ikariam.resourceNames[0]).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(li_woodProduction), true, true); IC.myGM.$(ls_dailyPrefix + IC.Ikariam.resourceNames[0]).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(li_woodProduction * 24), false); IC.myGM.$(ls_hourlyPrefix + IC.Ikariam.resourceNames[1]).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(-1 * li_wineSpending), true, true); IC.myGM.$(ls_dailyPrefix + IC.Ikariam.resourceNames[1]).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(-1 * li_wineSpending * 24), false); if(li_producesWine === true) li_tradegoodProduction = li_tradegoodProduction - li_wineSpending; IC.myGM.$(ls_hourlyPrefix + ls_tradegoodName).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(li_tradegoodProduction), true, true); IC.myGM.$(ls_dailyPrefix + ls_tradegoodName).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(li_tradegoodProduction * 24), false); IC.myGM.$(ls_hourlyPrefix + ls_tradegoodName).classList.remove('invisible'); IC.myGM.$(ls_dailyPrefix + 'Wrapper' + ls_tradegoodName).classList.remove('invisible'); _li_lastTradegood = li_producedTradegood; }; /** * Add the direct income fields. */ var _lf_addFields = function() { IC.Ikariam.resourceNames.forEach(function(is_resource, ii_index) { var la_hourlyClasses = [IC.myGM.prefix + 'hourlyIncomeResource']; var la_dailyClasses = ['smallFont', IC.myGM.prefix + 'dailyIncomeResourceWrapper']; if(ii_index >= 2) { la_hourlyClasses.push('invisible'); la_dailyClasses.push('invisible'); } IC.myGM.addElement('span', IC.myGM.$('#resources_' + is_resource), { 'id': 'hourlyIncomeResource' + is_resource, 'classes': la_hourlyClasses }); var le_dailyIncomeParent = IC.myGM.$('#resources_' + is_resource + ' .tooltip'); var le_dailyIncomeWrapper = IC.myGM.addElement('p', le_dailyIncomeParent, { 'id': 'dailyIncomeResourceWrapper' + is_resource, 'classes': la_dailyClasses, 'innerHTML': IC.Language.$('resourceInformation.dailyProduction', [IC.Language.$('diverse.name.resource.' + is_resource)]) + ' ' }, null, IC.myGM.$('p:nth-child(2)', le_dailyIncomeParent)); IC.myGM.addElement('span', le_dailyIncomeWrapper, { 'id': 'dailyIncomeResource' + is_resource }); }); _lf_updateFields(true); }; /** * Remove the direct income fields. */ var _lf_removeFields = function() { IC.myGM.removeElement(IC.myGM.$$('.' + IC.myGM.prefix + 'hourlyIncomeResource' + ', .' + IC.myGM.prefix + 'dailyIncomeResourceWrapper')); }; /** * Update the settings to execute the callback or delete the handler. * * @param {boolean} ib_showDirectIncome * If the user selected the checkbox to show the income directly in town view. */ this.updateSettings = function(ib_showDirectIncome) { _go_styleFunctions.setStyles(); if(ib_showDirectIncome === true) { _lf_addFields(); IC.RefreshHandler.add('*', 'directIncome', _lf_updateFields); return; } IC.RefreshHandler.remove('*', 'directIncome'); _lf_removeFields(); }; }; /** * Storage for the functions for the resource quicklinks enhancements. * * @type {object} */ var _go_resourceQuicklinkEnhancements = new function() { /** * Open the town hall of the selected town. */ var _lf_openTownHall = function() { var ls_selectedCity = IC.ika.getModel().relatedCityData.selectedCity; var ls_cityId = IC.ika.getModel().relatedCityData[ls_selectedCity].id; if(IC.Ikariam.view == 'town') { IC.win.ajaxHandlerCall('?view=townHall&cityId=' + ls_cityId + '&position=0'); return; } IC.win.ajaxHandlerCall('?view=city&dialog=townHall&cityId=' + ls_cityId + '&position=0'); }; /** * Update the css to hover only the resources which are clickable. */ var _lf_updateCSS = function() { var ls_activeResource = IC.Ikariam.resourceNames[IC.ika.getModel().producedTradegood]; IC.myGM.addStyle( '#resources_population:hover, #resources_wood:hover, #resources_' + ls_activeResource + ':hover { text-shadow: 2px 2px 2px #666; cursor: pointer; color: #333; }', 'resourceQuicklinkEnhancements', true ); }; /** * Update the settings to execute the callback or delete the handler. * * @param {boolean} ib_enhanceResourceQuicklinks * If the user selected the checkbox to enhance the resource quicklinks. */ this.updateSettings = function(ib_enhanceResourceQuicklinks) { if(ib_enhanceResourceQuicklinks === true) { IC.myGM.$('#resources_population').addEventListener('click', _lf_openTownHall, true); IC.RefreshHandler.add('*', 'resourceQuicklinkEnhancements', _lf_updateCSS); return; } IC.RefreshHandler.remove('*', 'resourceQuicklinkEnhancements'); IC.myGM.$('#resources_population').removeEventListener('click', _lf_openTownHall, true); IC.myGM.removeStyle('resourceQuicklinkEnhancements'); }; }; IC.Options.addWrapper('resourceInformation', IC.Language.$('resourceInformation.options.wrapperTitle')); // Option to show the income directly in town view. IC.Options.addCheckbox('showDirectIncome', 'resourceInformation', 1, true, IC.Language.$('resourceInformation.options.directIncome.show'), { changeCallback: _go_directIncome.updateSettings }); // Option to enhance the resource quicklinks and add one to population. IC.Options.addCheckbox('resourceQuicklinkEnhancements', 'resourceInformation', 1, true, IC.Language.$('resourceInformation.options.resourceQuicklinkEnhancements'), { changeCallback: _go_resourceQuicklinkEnhancements.updateSettings }); // Option to show the capacity information. IC.Options.addCheckbox('showCapacityBar', 'resourceInformation', 2, true, IC.Language.$('resourceInformation.options.capacityBar.show'), { changeCallback: _go_capacityInformation.updateSettings }); // Option to show the capacity bar with border. IC.Options.addCheckbox('capacityBarHasBorder', 'resourceInformation', 2, true, IC.Language.$('resourceInformation.options.capacityBar.hasBorder'), {}); // Option to show also branch office ressources. IC.Options.addCheckbox('capacityBarShowBranchOfficeResources', 'resourceInformation', 2, true, IC.Language.$('resourceInformation.options.capacityBar.showBranchOfficeResources'), {}); // Style of the resources in warehouse / daily income. IC.Options.addSelect('incomeStyle', 'resourceInformation', 3, 'alignRight', IC.Language.$('resourceInformation.options.directIncome.style.label'), [ { value: 'alignRight', label: IC.Language.$('resourceInformation.options.directIncome.style.alignRight') }, { value: 'alignLeft', label: IC.Language.$('resourceInformation.options.directIncome.style.alignLeft') }, { value: 'withSeparation', label: IC.Language.$('resourceInformation.options.directIncome.style.withSeparation') } ], {}); // Style of the capacity bar. IC.Options.addSelect('capacityBarOrientation', 'resourceInformation', 3, 'vertical', IC.Language.$('resourceInformation.options.capacityBar.orientation.label'), [ { value: 'vertical', label: IC.Language.$('resourceInformation.options.capacityBar.orientation.vertical') }, { value: 'horizontal', label: IC.Language.$('resourceInformation.options.capacityBar.orientation.horizontal') }, { value: 'horizontalFull', label: IC.Language.$('resourceInformation.options.capacityBar.orientation.horizontalFull') } ], {}); })(); IC.con.timeStamp('IkariamEnhancedUI: resource information functions created'); // Member information in highscore view. (function() { /** * Storage for the member information functions. * * @type {object} */ var _go_memberInformation = new function() { /** * Storage for the member data. * * @type {object} */ var _lo_data = null; /** * Key for the storage of the member information. * * @type {string} */ var _ls_dataKey = ''; /** * Key for the storage of the last reset date. * * @type {string} */ var _ls_timeKey = ''; /** * Show the data. */ var _lf_clickShow = function() { IC.myGM.setValue('memberInfo_infoLinkClicked', true); IC.myGM.$('#tab_highscore input[name="searchUser"]').value = ''; IC.myGM.$('#searchOnlyFriends').checked = false; IC.myGM.$('#searchOnlyAllies').checked = true; IC.myGM.$('#tab_highscore input[type="submit"]').click(); }; /** * Reset the stored data. */ var _lf_clickReset = function() { IC.myGM.setValue(_ls_dataKey, _lo_data); IC.myGM.setValue(_ls_timeKey, (new Date).getTime()); _lf_clickShow(); }; /** * Add the button to show the data. */ var _lf_addShowButton = function() { var le_button = IC.myGM.addButton(IC.myGM.$('#tab_highscore .centerButton'), IC.Language.$('highscore.memberInformation.show'), _lf_clickShow, true); le_button.id = IC.myGM.prefix + 'showInfo'; }; /** * Add the button to reset the stored data. */ var _lf_addResetButton = function() { var le_button = IC.myGM.addButton(IC.myGM.$('#tab_highscore .content p'), IC.Language.$('highscore.memberInformation.reset'), _lf_clickReset, true); le_button.id = IC.myGM.prefix + 'resetInfo'; }; /** * Get the own data and show the differences to the last stored data. * * @param {object} io_oldMemberInfo * The last stored data. * * @return {object} * The own data. */ var _lf_getOwnDataShowDifference = function(io_oldMemberInfo) { var le_ownRow = IC.myGM.$('table.highscore tr.own'); var ro_ownData = { 'place': IC.Ikariam.getInt(IC.myGM.$('.place', le_ownRow).innerHTML), 'score': IC.Ikariam.getInt(IC.myGM.$('.score', le_ownRow).innerHTML) }; var ls_placeDifference = '-'; var ls_scoreDifference = '-'; if(!!io_oldMemberInfo === true && !!io_oldMemberInfo['own'] === true) { ls_placeDifference = IC.Ikariam.formatToIkaNumber(io_oldMemberInfo['own']['place'] - ro_ownData['place'], true, true); ls_scoreDifference = IC.Ikariam.formatToIkaNumber(ro_ownData['score'] - io_oldMemberInfo['own']['score'], true, true); } IC.myGM.addElement('span', IC.myGM.$('.place', le_ownRow), { 'innerHTML': ls_placeDifference }); IC.myGM.addElement('span', IC.myGM.$('.score', le_ownRow), { 'innerHTML': ls_scoreDifference }); return ro_ownData; }; /** * Get the data and show the differences to the last stored data. * * @return {object} * The member data. */ var _lf_getDataShowDifference = function() { var ro_memberInfo = {}; var lo_oldMemberInfo = IC.myGM.getValue(_ls_dataKey, null); var la_allyMemberRows = IC.myGM.$$('table.highscore tr.ownally'); la_allyMemberRows.forEach(function(ie_allyMemberRow) { var ls_actionLink = IC.myGM.$('.action a', ie_allyMemberRow).href; var ls_memberId = ls_actionLink.match(/receiverId=([0-9]*)/i)[1]; ro_memberInfo[ls_memberId] = { 'place': IC.Ikariam.getInt(IC.myGM.$('.place', ie_allyMemberRow).innerHTML), 'score': IC.Ikariam.getInt(IC.myGM.$('.score', ie_allyMemberRow).innerHTML) }; var ls_placeDifference = '-'; var ls_scoreDifference = '-'; if(!!lo_oldMemberInfo === true && !!lo_oldMemberInfo[ls_memberId] === true) { ls_placeDifference = IC.Ikariam.formatToIkaNumber(lo_oldMemberInfo[ls_memberId]['place'] - ro_memberInfo[ls_memberId]['place'], true, true); ls_scoreDifference = IC.Ikariam.formatToIkaNumber(ro_memberInfo[ls_memberId]['score'] - lo_oldMemberInfo[ls_memberId]['score'], true, true); } IC.myGM.addElement('span', IC.myGM.$('.place', ie_allyMemberRow), { 'innerHTML': ls_placeDifference }); IC.myGM.addElement('span', IC.myGM.$('.score', ie_allyMemberRow), { 'innerHTML': ls_scoreDifference }); }); ro_memberInfo['own'] = _lf_getOwnDataShowDifference(lo_oldMemberInfo); return ro_memberInfo; }; /** * Add the span with the time of the last reset. */ var _lf_addLastResetTime = function() { var li_lastResetTime = IC.myGM.getValue(_ls_timeKey, 0); var li_differenceInSec = ((new Date()).getTime() - li_lastResetTime) / 1000; var ls_lastReset = IC.Language.$('highscore.memberInformation.noReset'); if(li_lastResetTime > 0) { var li_days = Math.floor(li_differenceInSec / 86400); var li_hours = Math.floor(li_differenceInSec / 3600) % 24; var li_minutes = Math.floor(li_differenceInSec / 60) % 60; ls_lastReset = li_days + 'd ' + li_hours + 'h ' + li_minutes + 'min'; } IC.myGM.addElement('br', IC.myGM.$('#tab_highscore .content p')); IC.myGM.addElement('span', IC.myGM.$('#tab_highscore .content p'), { 'classes': ['bold', 'brown'], 'innerHTML': IC.Language.$('highscore.memberInformation.lastReset', [ls_lastReset]) }); }; /** * Prepare the highscore popup to show the data and show the data if requested. */ var _lf_doPreparePopup = function() { _ls_dataKey = IC.Ikariam.serverCode + '_' + IC.ika.getModel().avatarAllyId + '_memberInfo_data_' + IC.myGM.getSelectValue('js_highscoreType', true, true); _ls_timeKey = IC.Ikariam.serverCode + '_' + IC.ika.getModel().avatarAllyId + '_memberInfo_time_' + IC.myGM.getSelectValue('js_highscoreType', true, true); _lf_addShowButton(); if(IC.myGM.getValue('memberInfo_infoLinkClicked', false) === true) { IC.myGM.deleteValue('memberInfo_infoLinkClicked'); _lo_data = _lf_getDataShowDifference(); _lf_addResetButton(); _lf_addLastResetTime(); } }; /** * Update the settings to execute the callback or delete the handler. * * @param {boolean} ib_showMemberInformation * If the user selected the checkbox to show the member information. */ this.updateSettings = function(ib_showMemberInformation) { if(ib_showMemberInformation === true) { IC.RefreshHandler.add('highscore', 'memberInformation', _lf_doPreparePopup); IC.myGM.addStyle( '#' + IC.myGM.prefix + "resetInfo { float: right; margin-top: -6px; margin-right: 6px; } \ .highscore .score span { float: right; text-align: right; width: 70px; } \ .highscore .place span { float: right; text-align: right; width: 30px; } \ .highscore th:nth-child(4) { width: 30% !important; } \ .highscore th:nth-child(5) { width: 10% !important; } \ #tab_highscore .centerButton { margin: 10px 0px; }", 'memberInformation', true ); return; } IC.RefreshHandler.remove('highscore', 'memberInformation'); IC.myGM.removeStyle('memberInformation'); }; }; // Show the member information. IC.Options.addCheckbox('showMemberInformation', 'diverseOptions', 1, false, IC.Language.$('highscore.options.showMemberInformation'), { changeCallback: _go_memberInformation.updateSettings }); })(); IC.con.timeStamp('IkariamEnhancedUI: highscore functions created'); // Message enhancements. (function() { /** * Storage for the url replacement functions. * * @type {object} */ var _go_replaceURL = new function() { /** * Show a warning when a replaced link is clicked. */ var _lf_showNotification = function() { var ls_urlToOpen = this.innerHTML.IC.decodeHTML(); var lo_notificationText = { header: IC.Language.$('message.replacedUrl.notification.header'), body: IC.Language.$('message.replacedUrl.notification.text', ['"' + ls_urlToOpen + '"']), confirm: IC.Language.$('general.yes'), abort: IC.Language.$('general.no') }; var lo_notificationCallback = { confirm: function() { IC.win.open(ls_urlToOpen); }, abort: function() { /* Only set to show the abort button */ } }; IC.myGM.notification(lo_notificationText, lo_notificationCallback); }; /** * Replace the links. */ var _lf_doReplace = function() { var la_messageBodys = IC.myGM.$$('.msgText'); la_messageBodys.forEach(function(ie_messageBody) { var ls_text = ie_messageBody.innerHTML; ie_messageBody.innerHTML = ls_text.replace(/(?:^|\s)(http(s?)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,4}(\/[^<\s]*)?)/g, ' $1 '); }); var la_replacedURLs = IC.myGM.$$('.' + IC.myGM.prefix + 'replacedUrl'); la_replacedURLs.forEach(function(ie_replacedURL) { ie_replacedURL.addEventListener('click', _lf_showNotification, true); }); }; /** * Update the settings to execute the callback or delete the handler. * * @param {boolean} ib_replaceURL * If the user selected the checkbox to replace the url. */ this.updateSettings = function(ib_replaceURL) { var la_postboxes = ['diplomacyAdvisor', 'diplomacyAdvisorOutBox', 'diplomacyAdvisorArchive', 'diplomacyAdvisorArchiveOutBox']; if(ib_replaceURL === true) { IC.RefreshHandler.add(la_postboxes, 'replaceURL', _lf_doReplace); IC.myGM.addStyle( '.' + IC.myGM.prefix + 'replacedUrl { font-weight: bold; font-style: italic; } \ .' + IC.myGM.prefix + 'replacedUrl:hover { text-decoration: underline; cursor: pointer; }', 'replaceURL', true ); return; } IC.RefreshHandler.remove(la_postboxes, 'replaceURL'); IC.myGM.removeStyle('replaceURL'); }; }; /** * Storage for the message signature functions. * * @type {object} */ var _go_messageSignature = new function() { /** * Add the signature to a new message. */ var _lf_addSignature = function() { var ls_signature = ''; switch(IC.Options.getOption('messages', 'useMessageSignature')) { case IC.Options.SpecificityLevel.GLOBAL: ls_signature = IC.Options.getOption('messages', 'globalSignature'); break; case IC.Options.SpecificityLevel.SERVER: ls_signature = IC.Options.getOption('messages', 'serverSignature'); break; case IC.Options.SpecificityLevel.PLAYER: ls_signature = IC.Options.getOption('messages', 'playerSignature'); break; } if(ls_signature === '') return; var le_textarea = IC.myGM.$('#js_msgTextConfirm'); var ls_text = le_textarea.value; if(IC.Options.getOption('messages', 'signaturePlacementTop')) ls_text = '\n\n' + ls_signature + ls_text; else ls_text = ls_text + '\n\n' + ls_signature; le_textarea.value = ls_text; le_textarea.setSelectionRange(0,0); le_textarea.focus(); }; /** * Update the settings to execute the callback or delete the handler. * * @param {boolean} ib_addMessageSignature * If the user selected the checkbox to add signatures to messages. */ this.updateSettings = function(is_useMessageSignature) { if(is_useMessageSignature === IC.Options.SpecificityLevel.GLOBAL || is_useMessageSignature === IC.Options.SpecificityLevel.SERVER || is_useMessageSignature === IC.Options.SpecificityLevel.PLAYER) { IC.RefreshHandler.add('sendIKMessage', 'addMessageSignature', _lf_addSignature); return; } IC.RefreshHandler.remove('sendIKMessage', 'addMessageSignature'); }; }; IC.Options.addWrapper('messages', IC.Language.$('message.options.wrapperTitle')); // Replace urls. IC.Options.addCheckbox('replaceURL', 'messages', 1, true, IC.Language.$('message.options.replaceURL'), { changeCallback: _go_replaceURL.updateSettings }); // Player specific signatures. var la_options = [ { value: 'none', label: IC.Language.$('message.options.signature.use.none') }, { value: IC.Options.SpecificityLevel.GLOBAL, label: IC.Language.$('message.options.signature.use.global') }, { value: IC.Options.SpecificityLevel.SERVER, label: IC.Language.$('message.options.signature.use.server') }, { value: IC.Options.SpecificityLevel.PLAYER, label: IC.Language.$('message.options.signature.use.player') } ]; IC.Options.addSelect('useMessageSignature', 'messages', 2, IC.Options.SpecificityLevel.GLOBAL, IC.Language.$('message.options.signature.use.description'), la_options, { changeCallback: _go_messageSignature.updateSettings, 'specificity': IC.Options.SpecificityLevel.PLAYER }); // Place the signature on top. IC.Options.addCheckbox('signaturePlacementTop', 'messages', 2, true, IC.Language.$('message.options.signature.placementTop'), {}); // Define a global signature. IC.Options.addTextArea('globalSignature', 'messages', 3, '', IC.Language.$('message.options.signature.global'), {}); // Define a server specific signature. IC.Options.addTextArea('serverSignature', 'messages', 4, '', IC.Language.$('message.options.signature.server'), { 'specificity': IC.Options.SpecificityLevel.SERVER }); // Define a server specific signature. IC.Options.addTextArea('playerSignature', 'messages', 4, '', IC.Language.$('message.options.signature.player'), { 'specificity': IC.Options.SpecificityLevel.PLAYER }); })(); IC.con.timeStamp('IkariamEnhancedUI: message functions created'); // Troop information. (function() { /** * Provider for data storages. * * @type {object} */ var _go_storageProvider = new function() { /** * Constructor for troop list. */ var _lf_troopList = function() { /** * Storage for troop information. * * @type {lf_troop[]} */ var la_troopList = []; /** * Troop information storage. * * @param {string} is_name * The name of the troop. * @param {int} ii_number * The number of the troop. */ var lf_troop = function(is_name, ii_number) { var ls_name = is_name; var li_number = ii_number; this.toString = function() { return '\n' + ls_name + ': ' + li_number; }; }; /** * If the troop list contains no entries. * * @return {boolean} * If the troop list is empty. */ this.__defineGetter__('isEmpty', function() { return la_troopList.length < 1; }); /** * Add a new troop to the troop list. * * @param {string} is_name * The name of the troop. * @param {int} ii_number * The number of the troop. */ this.addTroop = function(is_name, ii_number) { la_troopList.push(new lf_troop(is_name, ii_number)); }; /** * Transform the troop list to a string. * * @return {string} * The string representation of the troop list. */ this.toString = function() { return la_troopList.join(''); }; }; /** * Constructor for troop list of foreign player. * * @param {string} is_playerName * The name of the player who owns the troops. */ var _lf_foreignTroopList = function(is_playerName) { /** * The name of the player who owns the troops. * * @type {string} */ var ls_playerName = is_playerName; /** * Storage for troop information. * * @type {_lf_troopList[]} */ var lo_troopList = new _lf_troopList(); /** * If the troop list contains no entries. * * @return {boolean} * If the troop list is empty. */ this.__defineGetter__('isEmpty', function() { return lo_troopList.isEmpty; }); /** * Add a new troop to the troop list. * * @param {string} is_name * The name of the troop. * @param {int} ii_number * The number of the troop. */ this.addTroop = function(is_name, ii_number) { lo_troopList.addTroop(is_name, ii_number); }; /** * Transform the troop list to a string. * * @return {string} * The string representation of the troop list. */ this.toString = function() { return '\n* ' + ls_playerName + ' *' + lo_troopList; }; }; /** * Storage for multiple troop lists. * * @param {string} is_type * The type of the troops (units / ships) * @param {string} is_status * The status of the troops (own / friends / enemies) */ var _lf_troopListStorage = function(is_type, is_status) { /** * The type of the troops (units / ships). * * @type {string} */ var ls_type = is_type; /** * The status of the troops (own / friends / enemies). * * @type {string} */ var ls_status = is_status; /** * The troop lists. * * @type {(_lf_troopList||_lf_foreignTroopList)[]} */ var la_troopLists = []; /** * The status of the troop lists (own / friends / enemies). * * @return {boolean} * The status of the lists. */ this.__defineGetter__('status', function() { return ls_status; }); /** * Add a new troop list to the storage. * * @param {_lf_troopList||_lf_foreignTroopList} io_troopList * The troop list to add. */ this.addTroopList = function(io_troopList) { la_troopLists.push(io_troopList); }; /** * Transform the troop list storage to a string. * * @return {string} * The string representation of the troop list storage. */ this.toString = function() { return '\n--- ' + IC.Language.$('troopInformation.' + ls_type + '.' + ls_status) + ' ---' + la_troopLists.join('\n'); }; }; /** * Storage for data of all troops of one type. * * @param {string} is_type * The type of the troops (units / ships) */ var _lf_troopData = function(is_type) { /** * The type of the troops (units / ships). * * @type {string} */ var ls_type = is_type; /** * The troop list storages. * * @type {_lf_troopListStorage[]} */ var la_listStorages = []; /** * If the troop list contains no entries. * * @return {boolean} * If the troop list is empty. */ this.__defineGetter__('isEmpty', function() { return la_listStorages.length < 1; }); /** * Add a new troop list to the storage. * * @param {string} is_status * The status of the troop list. * @param {_lf_troopList||_lf_foreignTroopList} io_troopList * The troop list to add. */ this.addTroopList = function(is_status, io_troopList) { for(var i = 0; i < la_listStorages.length; i++) { if(la_listStorages[i].status === is_status) { la_listStorages[i].addTroopList(io_troopList); return; } } var lo_listStorage = new _lf_troopListStorage(ls_type, is_status); lo_listStorage.addTroopList(io_troopList); la_listStorages.push(lo_listStorage); }; /** * Transform the troop data to a string. * * @param {string} is_townInformation * The information about the town for which the troop data is displayed. * * @return {string} * The string representation of the troop data. */ this.getString = function(is_townInformation) { return '===== ' + IC.Language.$('troopInformation.' + ls_type + '.label', [is_townInformation]) + ' =====' + la_listStorages.join('\n\n'); }; }; /** * Get a new troop list representation for own troops. * * @return {_lf_troopList} * The troop list. */ this.ownTroopList = function() { return new _lf_troopList(); }; /** * Get a new troop list representation for foreign troops. * * @param {string} is_playerName * The name of the player who owns the troops. * * @return {_lf_foreignTroopList} * The troop list. */ this.foreignTroopList = function(is_playerName) { return new _lf_foreignTroopList(is_playerName); }; /** * Get a new troop data storage representation for all troops of one type. * * @param {string} is_type * The type of the troops (units / ships). * * @return {_lf_troopData} * The troop data storage. */ this.troopData = function(is_type) { return new _lf_troopData(is_type); }; }; /** * Storage for the dta extraction functions. * * @type {object} */ var _go_dataExtractor = new function() { /** * Extract own troops from a wrapper. * * @param {element} ie_wrapper * The wrapper to extract the troops from. * * @return {_go_storageProvider.ownTroopList[]} * The extracted troops. */ var _lf_extractOwnTroops = function(ie_wrapper) { var la_nameCells = IC.myGM.$$('.table01 .title_img_row th', ie_wrapper); var la_numberCells = IC.myGM.$$('.table01 .count td', ie_wrapper); var ro_troops = _go_storageProvider.ownTroopList(); for(var i = 0; i < la_nameCells.length; i++) { var li_number = IC.Ikariam.getInt(la_numberCells[i].innerHTML); if(li_number > 0) ro_troops.addTroop(la_nameCells[i].title, li_number); } return ro_troops; }; /** * Extract foreign troops from a wrapper. * * @param {element} ie_wrapper * The wrapper to extract the troops from. * * @return {_go_storageProvider.foreignTroopList[]} * The extracted troops. */ var _lf_extractForeignTroops = function(ie_wrapper) { var la_nameCells = IC.myGM.$$('.table01 .title_img_row th:not(:first-child)', ie_wrapper); var la_numberRows = IC.myGM.$$('.table01 tr:not(.title_img_row)', ie_wrapper); var li_distance = la_numberRows.length / 2; var ra_troops = []; for(var i = 0; i < li_distance; i++) { var la_numberCells = IC.myGM.$$('td:not(:first-child)', la_numberRows[i]).concat(IC.myGM.$$('td:not(:first-child)', la_numberRows[i + li_distance])); var ls_playerName = IC.myGM.$('td a', la_numberRows[i]).innerHTML; var lo_playerTroops = _go_storageProvider.foreignTroopList(ls_playerName); for(var i = 0; i < la_nameCells.length; i++) { var li_number = IC.Ikariam.getInt(la_numberCells[i].innerHTML); if(li_number > 0) lo_playerTroops.addTroop(la_nameCells[i].title, li_number); } if(lo_playerTroops.isEmpty === false) ra_troops.push(lo_playerTroops); } return ra_troops; }; /** * Extract all troop of one type. * * @param {string} is_type * The type of the troops to extract (units / ships). * @param {string} is_wrapperTabId * The id of the tab which contains the wrappers. * * @return {_go_storageProvider.troopData} * The extracted data. */ var _lf_extractTroops = function(is_type, is_wrapperTabId) { var ro_return = _go_storageProvider.troopData(is_type); var la_wrappers = IC.myGM.$$('#' + is_wrapperTabId + ' .contentBox01h'); var lo_ownTroops = _lf_extractOwnTroops(la_wrappers[0]); if(lo_ownTroops.isEmpty === false) ro_return.addTroopList('own', lo_ownTroops); var la_foreignStatus = ['friends', 'enemies']; for(var i = 0; i < la_foreignStatus.length; i++) { var la_foreignTroops = _lf_extractForeignTroops(la_wrappers[i + 1]); for(var j = 0; j < la_foreignTroops.length; j++) { ro_return.addTroopList(la_foreignStatus[i], la_foreignTroops[j]); } } return ro_return; }; /** * Extract all troop from the popup. * * @return {object} * All extracted troops. * Signature: { units: <_go_storageProvider.troopData>, ships: <_go_storageProvider.troopData> } */ this.extract = function() { return { units: _lf_extractTroops('units', 'tabUnits'), ships: _lf_extractTroops('ships', 'tabShips') }; }; }; /** * Storage for the troop information functions. * * @type {object} */ var _go_troopInformation = new function() { /** * Show the troop information popup. * * @param {object} io_data * All extracted troop. * Signature: { units: <_go_storageProvider.troopData>, ships: <_go_storageProvider.troopData> } */ var _ls_showPopup = function(io_data) { var la_output = []; var ls_townInformation = (function() { var lo_allTowns = IC.ika.getModel().relatedCityData; var lo_selectedTown = lo_allTowns[lo_allTowns.selectedCity]; return lo_selectedTown.name + ' ' + lo_selectedTown.coords; })(); if(!!io_data === true) { if(!!io_data.units.isEmpty === false) la_output.push(io_data.units.getString(ls_townInformation)); if(!!io_data.ships.isEmpty === false) la_output.push(io_data.ships.getString(ls_townInformation)); } var ls_output = la_output.join('\n\n-------------------------------------------------------------------------------------\n\n'); if(ls_output.length === 0) ls_output = IC.Language.$('troopInformation.noTroops', [ls_townInformation]); var lo_text = { header: IC.Language.$('troopInformation.header', [ls_townInformation]), body: ls_output }; IC.myGM.notification(lo_text, null, { textarea: true, readonly: true, autoselect: true }); }; /** * Extract the data and show the popup. */ var _lf_showInformation = function() { _ls_showPopup(_go_dataExtractor.extract()); }; /** * Show the troop information link. */ var _lf_doShowTroopInformationLink = function() { var le_button = IC.myGM.addButton(IC.myGM.$('#cityMilitary_c .buildingDescription'), IC.Language.$('troopInformation.button'), _lf_showInformation, true); var la_cssRules = [['position', 'absolute'], ['top', '5px'], ['right', '20px']]; for(var i = 0; i < la_cssRules.length; i++) { le_button.style[la_cssRules[i][0]] = la_cssRules[i][1]; } }; /** * Update the settings to execute the callback or delete the handler. * * @param {boolean} ib_enableTroopInformation * If the user selected the checkbox to show the troop information. */ this.updateSettings = function(ib_enableTroopInformation) { if(ib_enableTroopInformation === true) { IC.RefreshHandler.add('cityMilitary', 'troopInformation', _lf_doShowTroopInformationLink); return; } IC.RefreshHandler.remove('cityMilitary', 'troopInformation'); }; }; IC.Options.addCheckbox('showTroopInformation', 'diverseOptions', 1, true, IC.Language.$('troopInformation.options.show'), { changeCallback: _go_troopInformation.updateSettings }); })(); IC.con.timeStamp('IkariamEnhancedUI: troop information functions created'); IC.con.groupEnd(); } /** * Main function of the script.
* Inits the Ikariam Core and calls the script functions.
* Must be called with
setTimeout(main, 0)
for correct setting of some core variables. */ function main() { // Get the Ikariam core. var IC = new IkariamCore('3.2.2', 4369, 'Ikariam Enhanced UI', 'Tobbe', false); if(IC.myGM.alreadyExecuted === true) return; IC.Language.setDefaultLanguage('en'); IC.Language.addLanguageText('en', {"view": {"options": {"wrapperTitle":"View","moveLoadingCircle":"Move loading circle to position bar","hideBirds":"Hide the bird swarm","noVerticalCenterInTownAdvisor":"Don't center town information in the town advisor"}},"island": {"options": {"showColonizingCityInfo":"Show information about colonizing cities"}},"finance": {"options": {"showIncomeOnTop":"Show income on top in balance view","shortUpkeepReductionTable":"Show a short version of the upkeep reduction"},"income": {"perHour":"Income per hour","perDay":"Income per day","start":"Income without reduction"},"upkeep": {"reason": {"0":"Troops","1":"Ships","2":"Troops & Ships"},"basic":"Basic Costs","supply":"Supply Costs","result":"Total Costs"}},"missingResources": {"options": {"wrapperTitle":"Missing Resources","show":"Show missing resources in construction view","showPositive":"Show also the remaining resources after an upgrade","showColoured":"Show the remaining resources coloured"}},"tooltips": {"options": {"autoshow":"Show tooltips in alliance mebers view and military advisor automatically","showDirectInMilitaryAdvisor":"Show information about cargo / fleets in military view without tooltips"}},"zoom": {"options": {"wrapperTitle":"Zoom function","zoomView":"Activate zoom in world view, island view, town view","factor": {"world":"Zoom worldmap:","island":"Zoom island view:","town":"Zoom town view:"},"scaleChildren": {"label":"Let banners and symbols in normal size when zooming when zooming in this view:","world":"Worldmap","island":"Island view","town":"Town view"},"accessKeyLabel":"This keys must be pressed to zoom with the mouse:"},"zoomIn":"Zoom in","factor":"Zoom factor","zoomOut":"Zoom out"},"resourceInformation": {"options": {"wrapperTitle":"Resource Information","resourceQuicklinkEnhancements":"Link resource number to town hall / mines","directIncome": {"show":"Show the hourly income directly in town view","style": {"label":"Style of the hourly income in town view:","alignRight":"Right align","alignLeft":"Left align","withSeparation":"Right align with separation"}},"capacityBar": {"show":"Show info bar for warehouse capacity","hasBorder":"Has border","showBranchOfficeResources":"Show resources in trading post","orientation": {"label":"Orientation of the bar","vertical":"Vertical","horizontal":"Horizontal","horizontalFull":"Horizontal, full length"}}},"dailyProduction":"Daily production %$1:"},"highscore": {"options": {"showMemberInformation":"Enable the possibility to save highscore data of alliance members"},"memberInformation": {"show":"Alliance info","reset":"Reset","lastReset":"Time since the last reset: %$1","noReset":"No reset so far."}},"message": {"options": {"wrapperTitle":"Messages","replaceURL":"Make links in messages clickable","signature": {"use": {"description":"Use this signature:","none":"No signature","global":"Global signature","server":"Server signature","player":"Player signature"},"placementTop":"Insert signature above cited messages","global":"Global signature, which would be used on every world:","server":"Server signature, which only would be used on this world:","player":"Player signature, which only would be used for this player:"}},"replacedUrl": {"notification": {"header":"Attention!","text":"You're going to open the link %$1. This happens on your own risk. Proceed?"}}},"troopInformation": {"options": {"show":"Show troop info"},"units": {"label":"Units in %$1","own":"Own units","friends":"Allied units","enemies":"Enemy units"},"ships": {"label":"Ships in %$1","own":"Own ships","friends":"Allied ships","enemies":"Enemy ships"},"button":"Troop information","header":"Troops in %$1","noTroops":"There are no troops in %$1"},"diverse": {"options": {"wrapperTitle":"Diverse"},"name": {"resource": {"gold":"Gold","wood":"Building Material","wine":"Wine","marble":"Marble","glass":"Crystal Glass","sulfur":"Sulphur"},"unit": {"swordsman":"Swordsman","phalanx":"Hoplite","archer":"Archer","marksman":"Sulphur Carabineer","mortar":"Mortar","slinger":"Slinger","catapult":"Catapult","ram":"Battering Ram","steamgiant":"Steam Giant","bombardier":"Balloon-Bombardier","cook":"Cook","medic":"Doctor","girocopter":"Gyrocopter","spearman":"Spearman","spartan":"Spartan"},"ship": {"ballista":"Ballista Ship","catapult":"Catapult Ship","flamethrower":"Fire Ship","mortar":"Mortar Ship","ram":"Ram Ship","steamboat":"Steam Ram","rocketship":"Rocket Ship","submarine":"Diving Boat","paddlespeedship":"Paddle Speedboat","ballooncarrier":"Balloon Carrier","tender":"Tender","transport":"Merchant Ship"}}}}); var la_language = ['de', 'gr', 'fr', 'it', 'lv', 'ru', 'tr']; for(var i = 0; i < la_language.length; i++) { IC.Language.registerLanguageResource(la_language[i], la_language[i], 'http://resources.ikascripts.de/IkariamEnhancedUI/v3.2.2/' + la_language[i] + '.json'); } // Instantiate the ui script. new EnhancedUI(IC); } // Call the main function of the script. setTimeout(main, 0);