Ikariam Enhanced UI

Enhancements for the user interface of Ikariam.

当前为 2015-03-05 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Ikariam Enhanced UI
  3. // @description Enhancements for the user interface of Ikariam.
  4. // @namespace Tobbe
  5. // @author Tobbe
  6. // @version 3.0
  7. // @license MIT License
  8. //
  9. // @name:de Ikariam Enhanced UI
  10. // @description:de Verbesserungen der Oberfläche von Ikariam.
  11. //
  12. //
  13. // @include http://s*.ikariam.gameforge.com/*
  14. //
  15. // @exclude http://support.*.ikariam.gameforge.com/*
  16. //
  17. // @require https://greasyfork.org/scripts/5574-ikariam-core/code/Ikariam%20Core.js?version=39332
  18. //
  19. //
  20. // @resource de http://resources.ikascripts.de/IkariamEnhancedUI/v3.0/de.json
  21. // @resource gr http://resources.ikascripts.de/IkariamEnhancedUI/v3.0/gr.json
  22. // @resource it http://resources.ikascripts.de/IkariamEnhancedUI/v3.0/it.json
  23. // @resource lv http://resources.ikascripts.de/IkariamEnhancedUI/v3.0/lv.json
  24. // @resource ru http://resources.ikascripts.de/IkariamEnhancedUI/v3.0/ru.json
  25. // @resource core_de http://resources.ikascripts.de/IkariamCore/v2.0/core_de.json
  26. // @resource core_de_settings http://resources.ikascripts.de/IkariamCore/v2.0/core_de_settings.json
  27. // @resource core_gr http://resources.ikascripts.de/IkariamCore/v2.0/core_gr.json
  28. // @resource core_gr_settings http://resources.ikascripts.de/IkariamCore/v2.0/core_gr_settings.json
  29. // @resource core_it http://resources.ikascripts.de/IkariamCore/v2.0/core_it.json
  30. // @resource core_it_settings http://resources.ikascripts.de/IkariamCore/v2.0/core_it_settings.json
  31. // @resource core_lv http://resources.ikascripts.de/IkariamCore/v2.0/core_lv.json
  32. // @resource core_lv_settings http://resources.ikascripts.de/IkariamCore/v2.0/core_lv_settings.json
  33. // @resource core_ru http://resources.ikascripts.de/IkariamCore/v2.0/core_ru.json
  34. // @resource core_ru_settings http://resources.ikascripts.de/IkariamCore/v2.0/core_ru_settings.json
  35. //
  36. // @grant unsafeWindow
  37. // @grant GM_setValue
  38. // @grant GM_getValue
  39. // @grant GM_deleteValue
  40. // @grant GM_listValues
  41. // @grant GM_getResourceText
  42. // @grant GM_xmlhttpRequest
  43. //
  44. // @bug Opera & Chrome Zooming with the mouse is not possible with "Shift" as access key.
  45. // @bug Opera & Chrome No updating of the missing resources is possible due to a missing modification listener.
  46. // @bug All The selected island is not centered in world view.
  47. // @bug All If you are zooming to more than 100%, the view is not centered correctly after a page reload.
  48. //
  49. // @history 3.0 Release: 05.03.2015
  50. // @history 3.0 Language: Russian translation added (incomplete).
  51. // @history 3.0 Language: Italian translation added (incomplete).
  52. // @history 3.0 Language: Greek translation added (incomplete).
  53. // @history 3.0 Change: Implementation of Ikariam Core - rewrote the complete code.
  54. // @history 3.0 Change: Cleared the update history to use the Ikariam Core labels.
  55. // @history 3.0 Bugfix: Diverse graphic errors.
  56. // @history 3.0 Bugfix: Broken in Firefox and Chrome.
  57. //
  58. // @history 2.6 Release: 12.10.2014
  59. // @history 2.6 Bugfix: Script options were broken.
  60. //
  61. // @history 2.6 Release: 19.08.2014
  62. // @history 2.5 Bugfix: Game language is recognized again.
  63. // @history 2.5 Bugfix: Works now in Greasemonkey 2.0+
  64. // @history 2.5 Change: Checks now for updates on Greasy Fork.
  65. // @history 2.5 Removed code parts for mobile version.
  66. // @history 2.5 Removed alliance page improvement, as fixed in Ikariam v0.5.13
  67. //
  68. // @history 2.6 Release: 11.09.2013
  69. // @history 2.4 Bugfix: New Ikariam domain -> script can now be used with this domain
  70. //
  71. // @history 2.3 Release: 12.04.2013
  72. // @history 2.3 Feature: Formatting troop lists for posting in forums / personal messages.
  73. // @history 2.3 Feature: Filling level of warehouse as bar in town view.
  74. // @history 2.3 Feature: Link to mines / town hall when clicking on resources / citizens.
  75. // @history 2.3 Change: New versioning system.
  76. // @history 2.3 Bugfix: Some characters in links were not decoded correctly.
  77. // @history 2.3 Bugfix: Watching a foreign city causes a abortion of the script.
  78. // @history 2.3 Bugfix: The city dropdown sometimes was zoomed in world view.
  79. // @history 2.3 Bugfix: Removed obsolete CSS styles for Firefox.
  80. // @history 2.3 Adjustments in the language files.
  81. // @history 2.3 Violent Monkey brings Greasemonkey functions to Opera.
  82. //
  83. // @history 2.2.1 Release: 11.10.2012
  84. // @history 2.2.1 Feature: Smaller icons in direct military tooltip.
  85. // @history 2.2.1 Bugfix: Problems with update check and version numbers >= 10.
  86. // @history 2.2.1 Bugfix: Problems with another script.
  87. // @history 2.2.1 Bugfix: Problems with a wrong style in island view.
  88. //
  89. // @history 2.2 Release: 10.10.2012
  90. // @history 2.2 Feature: Message signature can be set.
  91. // @history 2.2 Feature: Button for faster sending of circular messages.
  92. // @history 2.2 Feature: Make links in messages clickable.
  93. // @history 2.2 Feature: Show town information of colonizing cities.
  94. // @history 2.2 Feature: Information about cargo / fleets is displayed directly in military view.
  95. // @history 2.2 Feature: Script options: Sections on the script tab can be folded.
  96. // @history 2.2 Bugfix: Tooltips with mouseover were not clickable anymore.
  97. // @history 2.2 Changes in code for better overview.
  98. //
  99. // @history 2.1.1 Release: 01.10.2012
  100. // @history 2.1.1 Feature: Different styles for income in town view.
  101. // @history 2.1.1 Feature: Remaining resources after upgrade.
  102. // @history 2.1.1 Feature: Improved style for external alliance pages.
  103. // @history 2.1.1 Feature: Refresh the missing / remaining resources in construction view automatically.
  104. //
  105. // @history 2.1 Release: 23.09.2012
  106. // @history 2.1 Feature: Show the missing resources in construction view.
  107. // @history 2.1 Feature: Show the hourly income directly in town view and add the daily production as popup.
  108. // @history 2.1 Feature: Don't center town information in the town advisor.
  109. // @history 2.1 Feature: Save the highscore data of alliance members and compare it with the actual value.
  110. // @history 2.1 Bugfix: There was an error with a missing language package and seperators.
  111. // @history 2.1 Bugfix: Some things in worldview were not resized correctly.
  112. // @history 2.1 Prevent more than one script execution.
  113. // @history 2.1 Prevent more than one script option panel (the script option panel now is usable for other scripts, too).
  114. //
  115. // @history 2.0.1 Release: 27.08.2012
  116. // @history 2.0.1 Bugfix: Zooming was broken.
  117. // @history 2.0.1 Bugfix: Dropdown menus created by the script were broken.
  118. // @history 2.0.1 Bugfix: Tooltips in in Alliance / Military view were not shown correctly.
  119. //
  120. // @history 2.0 Release: 18.07.2012
  121. // @history 2.0 Language: Latvian translation
  122. // @history 2.0 Feature: Cross-browser compatibility.
  123. // @history 2.0 Feature: Possibility to hide the update hint for a new script version.
  124. // @history 2.0 Bugfix: Resizing the owner state in world view was broken.
  125. // @history 2.0 Some changes in the code for easier copying of functions which should be used by more than one script.
  126. //
  127. // @history 1.7 Release: 12.06.2012
  128. // @history 1.7 Feature: Resizing banners when zooming is possible in city view, too.
  129. // @history 1.7 Feature: The zoom buttons are available in world view, too.
  130. // @history 1.7 Feature: Zooming with the mouse scroll is possible again (now with key, standard is ctrl).
  131. // @history 1.7 Change: Changes in the option panel due to the new zooming function features.
  132. // @history 1.7 Bugfix: If resizing is enabled, zooming with the buttons will resize the banners, too.
  133. // @history 1.7 Bugfix: The chat will not cause to much executions of script functions.
  134. // @history 1.7 The language texts are integrated as resources, so that there is shorter code.
  135. // @history 1.7 Replace the GM_* functions by myGM.* to expand them easy and add new.
  136. //
  137. // @history 1.6 Release: 05.06.2012
  138. // @history 1.6 Feature: Possibility to hide only the bird swarm animation.
  139. // @history 1.6 Feature: Easier upkeep reduction table.
  140. // @history 1.6 Feature: Enhanced zoom function using the Ikariam zoom function.
  141. // @history 1.6 Due to the use of Ikariam functions the code could be reduced.
  142. // @history 1.6 Code enhancements for shorter code.
  143. //
  144. // @history 1.5.1.1 Release: 25.05.2012
  145. // @history 1.5.1.1 Bugfix: Not all occurrences of hidden were changed.
  146. //
  147. // @history 1.5.1 Release: 24.05.2012
  148. // @history 1.5.1 Bugfix: Name of a class (hidden) is used by GF.
  149. //
  150. // @history 1.5 Release: 24.05.2012
  151. // @history 1.5 Feature: Options panel to enable/disable funtions and set settings.
  152. // @history 1.5 Feature: Update interval can be set.
  153. // @history 1.5 Feature: Manually check for updates.
  154. // @history 1.5 Feature: Zoom function without resizing the whole view.
  155. // @history 1.5 Feature: Move loading circle to another position.
  156. // @history 1.5 Feature: Show tooltip in alliance / military view on mouseover.
  157. // @history 1.5 Change: Code better commented. More comments, so that it is easier to understand.
  158. // @history 1.5 Bugfix: Changed *.gif to *.png.
  159. // @history 1.5 Version numbers adjusted.
  160. //
  161. // @history 1.4.1 Release: 01.05.2012
  162. // @history 1.4.1 Feature: Support for mobile interface.
  163. // @history 1.4.1 Bugfix: Fixed bug with scrollbar in finances view.
  164. //
  165. // @history 1.4 Release: 20.04.2012
  166. // @history 1.4 Feature: Ready for 0.5.0, but also supports 0.4.5 furthermore.
  167. // @history 1.4 Feature: Implemented support for different languages.
  168. // @history 1.4 Feature: Enhanced script updater.
  169. // @history 1.4 Change: Cleaned up code.
  170. // @history 1.4 Change: Rename the script to "Enhanced UI".
  171. // @history 1.4 Change: Change the namespace to "Tobbe".
  172. // @history 1.4 Because of the change of namespace and name you have to delete the old script manually!
  173. //
  174. // @history 1.3.3 Release: 11.04.2011
  175. // @history 1.3.3 Bugfix: Problem with negative numbers and 0.4.2.4 fixed.
  176. //
  177. // @history 1.3.2 Release: 15.01.2011
  178. // @history 1.3.2 Feature: Own script updater.
  179. // @history 1.3.2 Change: Remove everything what refered to other scripts.
  180. //
  181. // @history 1.3.1 Release: 15.01.2011
  182. // @history 1.3.1 Change: New script updater.
  183. //
  184. // @history 1.3 Release: 14.01.2011
  185. // @history 1.3 Change: Remove the script updater (Because of the problem with Greasemonkey scripts).
  186. //
  187. // @history 1.2.1 Release: 28.12.2010
  188. // @history 1.2.1 Change: New style of update panel.
  189. // @history 1.2.1 Bugfix: Bug with ',' as seperator fixed.
  190. //
  191. // @history 1.2 Release: 09.10.2010
  192. // @history 1.2 Feature: Income in 24h added.
  193. // @history 1.2 Change: Cleaned up code.
  194. //
  195. // @history 1.1 Release: 13.04.2010
  196. // @history 1.1 Feature: Update check implemented.
  197. //
  198. // @history 1.0 Release: 12.04.2010
  199. // @history 1.0 Initial release.
  200. // ==/UserScript==
  201.  
  202. /**
  203. * Instantiate a new set of enhancement functions.
  204. * {@link https://greasyfork.org/scripts/4369-enhanced-ui Script on Greasy Fork}
  205. * {@link https://github.com/tobias-engelmann/IkariamEnhancedUI Script on GitHub}
  206. *
  207. * @version 2.6.0.0.167
  208. * @author Tobbe <contact@ikascripts.de>
  209. *
  210. * @global
  211. *
  212. * @class
  213. * @classdesc Enhancements for the user interface of Ikariam.
  214. *
  215. * @param {IkariamCore} $
  216. * A instance of the Ikariam Core.
  217. */
  218. function EnhancedUI(IC) {
  219. /**
  220. * Script toolbar.
  221. *
  222. * @type {element}
  223. */
  224. var ge_toolbar = IC.myGM.addElement('div', IC.myGM.$('#GF_toolbar'), { 'id': 'toolbar' }, true, IC.myGM.$('#GF_toolbar ul'));
  225. IC.myGM.addStyle(
  226. '#GF_toolbar > ul { width: auto !important; text-align: center !important; pointer-events: none; } \
  227. #GF_toolbar > ul > * { pointer-events: auto; } \
  228. #GF_toolbar #mmoNewsticker { display: inline-block !important; position: relative !important; } \
  229. #GF_toolbar #mmoNewsticker > ul { width: auto !important; } \
  230. #' + IC.myGM.prefix + 'toolbar { float: right; } \
  231. #' + IC.myGM.prefix + 'toolbar > div { display: inline-block; position: relative; float: right; margin: 0px 5px; }',
  232. 'scriptToolbar'
  233. );
  234. IC.Options.addWrapper('diverseOptions', IC.Language.$('diverse.options.wrapperTitle'));
  235. IC.con.groupCollapsed('IkariamEnhancedUI initalization ...');
  236. IC.con.timeStamp('IkariamEnhancedUI: toolbar and general styles created');
  237. // General functions to enhance the view.
  238. (function() {
  239. IC.Options.addWrapper('enhancedView', IC.Language.$('view.options.wrapperTitle'));
  240. // Move the loading circle to the breadcrumb area.
  241. IC.Options.addCheckbox('moveLoadingCircle', 'enhancedView', 1, true, IC.Language.$('view.options.moveLoadingCircle'), {
  242. changeCallback: function(ib_newValue) {
  243. if(ib_newValue === true) {
  244. IC.myGM.addStyle(
  245. '#js_worldBread { margin-left: 16px !important; } \
  246. #loadingPreview { transform: scale(0.5); -webkit-transform: scale(0.5); left: 35px !important; top: 141px !important; }',
  247. 'enhancedView_moveLoadingCircle'
  248. );
  249. return;
  250. }
  251. IC.myGM.removeStyle('enhancedView_moveLoadingCircle');
  252. }
  253. });
  254. // Hide the flying bird swarm.
  255. IC.Options.addCheckbox('hideBirds', 'enhancedView', 1, true, IC.Language.$('view.options.hideBirds'), {
  256. changeCallback: function(ib_newValue) {
  257. if(ib_newValue === true) {
  258. IC.myGM.addStyle(
  259. '.bird_swarm { display: none; }',
  260. 'enhancedView_hideBirds'
  261. );
  262. return;
  263. }
  264. IC.myGM.removeStyle('enhancedView_hideBirds');
  265. }
  266. });
  267. // Bind the town name and date to the top of the row in the town advisor.
  268. IC.Options.addCheckbox('noVerticalCenterInTownAdvisor', 'enhancedView', 1, true, IC.Language.$('view.options.noVerticalCenterInTownAdvisor'), {
  269. changeCallback: function(ib_newValue) {
  270. if(ib_newValue === true) {
  271. IC.myGM.addStyle(
  272. '#inboxCity td { vertical-align: top !important; }',
  273. 'enhancedView_noVerticalCenterInTownAdvisor'
  274. );
  275. return;
  276. }
  277. IC.myGM.removeStyle('enhancedView_noVerticalCenterInTownAdvisor');
  278. }
  279. });
  280. })();
  281. IC.con.timeStamp('IkariamEnhancedUI: view functions created');
  282. // Functions for the island view.
  283. (function() {
  284. /**
  285. * Storage for the colonizing city info functions.
  286. *
  287. * @type {object}
  288. */
  289. var _go_colonizingCityInfo = new function() {
  290. /**
  291. * Add the link to show the colonizing city information.
  292. */
  293. var _lf_doShowColonizingCityInfo = function() {
  294. var la_colonizingCities = IC.myGM.$$('.level0');
  295. la_colonizingCities.forEach(function(le_colonizingCity) {
  296. var ls_locationId = le_colonizingCity.id.replace(/\D/g, '');
  297. var ls_cityId = IC.ika.getScreen().data.cities[ls_locationId].id;
  298. IC.myGM.$('#js_cityLocation' + ls_locationId + 'Link').href = '?view=cityDetails&destinationCityId=' + ls_cityId;
  299. });
  300. };
  301. /**
  302. * Remove the link to show the colonizing city information.
  303. */
  304. var _lf_doHideColonizingCityInfo = function() {
  305. var la_colonizingCityLinks = IC.myGM.$$('.level0 .link_img');
  306. la_colonizingCityLinks.forEach(function(le_colonizingCityLink) {
  307. le_colonizingCityLink.href = '';
  308. });
  309. };
  310. /**
  311. * Update the settings to execute the callback or delete the handler.
  312. *
  313. * @param {boolean} ib_showColonizingCityInfo
  314. * If the user selected the checkbox to show the colonizing city info.
  315. */
  316. this.updateSettings = function(ib_showColonizingCityInfo) {
  317. if(IC.Ikariam.view !== 'island')
  318. return;
  319. if(ib_showColonizingCityInfo === true) {
  320. IC.RefreshHandler.add('*', 'showColonizingCityInfo', _lf_doShowColonizingCityInfo);
  321. _lf_doShowColonizingCityInfo();
  322. return;
  323. }
  324. IC.RefreshHandler.remove('*', 'showColonizingCityInfo');
  325. _lf_doHideColonizingCityInfo();
  326. };
  327. };
  328. // Retrieve information about colonies during colonization.
  329. IC.Options.addCheckbox('showColonizingCityInfo', 'diverseOptions', 1, true, IC.Language.$('island.options.showColonizingCityInfo'), { changeCallback: _go_colonizingCityInfo.updateSettings });
  330. // Add a divider line.
  331. IC.Options.addLine('diverseOptions', 1);
  332. })();
  333. IC.con.timeStamp('IkariamEnhancedUI: island functions created');
  334. // Functions for the finance popup.
  335. (function(){
  336. /**
  337. * Some general functions for the finance view enhancements.
  338. *
  339. * @type {object}
  340. */
  341. var _go_generalFunctions = new function() {
  342. /**
  343. * Extract the current income in the finance popup.
  344. *
  345. * @return {int}
  346. * The current income.
  347. */
  348. this.getIncome = function() {
  349. var le_incomeCell = IC.myGM.$$('.hidden')[IC.myGM.$$('.hidden').length - 1];
  350. while(le_incomeCell.firstChild.firstChild)
  351. le_incomeCell = le_incomeCell.firstChild;
  352. return IC.Ikariam.getInt(le_incomeCell.innerHTML);
  353. };
  354. /**
  355. * Create a new table row.
  356. *
  357. * @param {element} ie_parentTable
  358. * The table to add the row to.
  359. * @param {string[]} ia_classes
  360. * The class(es) of the table row. Set to null if no class should be set.
  361. * @param {object[]} ia_cells
  362. * The data for the table cells. Both properties of each cell are optional. If the cell object is empty, an empty cell is created.
  363. * Signature: <code>[{ className: ['class1', 'class2', ...], text: 'cellContent' }]</code>
  364. * @param {boolean} ib_isTableHeadRow
  365. * If the cells should be table header cells (th).
  366. *
  367. * @return {element}
  368. * The created row.
  369. */
  370. this.createTableRow = function(ie_parentTable, ia_classes, ia_cells, ib_isTableHeadRow) {
  371. var re_newRow = IC.myGM.addElement('tr', ie_parentTable, { classes: ia_classes });
  372. var ls_cellType = 'td';
  373. if(!!ib_isTableHeadRow)
  374. ls_cellType = 'th';
  375. for(var i = 0; i < ia_cells.length; i++) {
  376. var lo_options = {
  377. 'classes': ia_cells[i].className
  378. };
  379. if(!!ia_cells[i].text === true)
  380. lo_options['innerHTML'] = ia_cells[i].text;
  381. IC.myGM.addElement(ls_cellType, re_newRow, lo_options);
  382. }
  383. return re_newRow;
  384. };
  385. };
  386. /**
  387. * Storage for the income on top functions.
  388. *
  389. * @type {object}
  390. */
  391. var _go_incomeOnTop = new function() {
  392. /**
  393. * Callback to show the income on top.
  394. */
  395. var _lf_doShowIncomeOnTop = function() {
  396. var le_summaryTable = IC.myGM.$('.table01');
  397. var li_income = _go_generalFunctions.getIncome();
  398. var la_incomeCells = [
  399. { className: ['sigma'], text: IC.Language.$('finance.income.perHour') },
  400. { className: ['value', 'res'] },
  401. { className: ['value', 'res'] },
  402. { className: ['value', 'res'], text: IC.Ikariam.formatToIkaNumber(li_income) }
  403. ];
  404. _go_generalFunctions.createTableRow(le_summaryTable, ['result', 'alt'], la_incomeCells);
  405. la_incomeCells[0].text = IC.Language.$('finance.income.perDay');
  406. la_incomeCells[3].text = IC.Ikariam.formatToIkaNumber(li_income * 24);
  407. _go_generalFunctions.createTableRow(le_summaryTable, ['result'], la_incomeCells);
  408. // Adjust the size of the Scrollbar.
  409. IC.ika.controller.adjustSizes();
  410. };
  411. /**
  412. * Update the settings to execute the callback or delete the handler.
  413. *
  414. * @param {boolean} ib_showIncomeOnTop
  415. * If the user selected the checkbox to show the income on top.
  416. */
  417. this.updateSettings = function(ib_showIncomeOnTop) {
  418. if(ib_showIncomeOnTop === true) {
  419. IC.RefreshHandler.add('finances', 'showIncomeOnTop', _lf_doShowIncomeOnTop);
  420. return;
  421. }
  422. IC.RefreshHandler.remove('finances', 'showIncomeOnTop');
  423. };
  424. };
  425. /**
  426. * Storage for the short upkeep reduction table functions.
  427. *
  428. * @type {object}
  429. */
  430. var _go_shortUpkeepReductionTable = new function() {
  431. /**
  432. * Extract the data from the old tables.
  433. *
  434. * @param {element[]} ia_oldUpkeepReductionTables
  435. * The old upkeep tables to collapse.
  436. *
  437. * @return {object[]}
  438. * The data for the table rows.
  439. * Signature:
  440. * <code>[{
  441. * rows: [
  442. * { reason : 'reason', basicUpkeep: int, supplyUpkeep: int, result: int }
  443. * ]
  444. * priorToReduction: int
  445. * income: int
  446. * }]</code>
  447. */
  448. var _lf_getData = function(ia_oldUpkeepReductionTables) {
  449. var ro_data = {
  450. rows: [],
  451. priorToReduction: IC.Ikariam.getInt(IC.myGM.$('td.hidden', ia_oldUpkeepReductionTables[2]).innerHTML),
  452. income: _go_generalFunctions.getIncome()
  453. };
  454. // Get the data for the troops and ships redution rows.
  455. for(var i = 0; i < 3; i++) {
  456. var le_basicUpkeepCell = IC.myGM.$$('.alt.bottomLine td.hidden, .result td.hidden', ia_oldUpkeepReductionTables[0])[i];
  457. var le_supplyUpkeepCell = IC.myGM.$$('.alt.bottomLine td.hidden, .result td.hidden', ia_oldUpkeepReductionTables[1])[i];
  458. var li_basicUpkeep = IC.Ikariam.getInt(le_basicUpkeepCell.innerHTML);
  459. var li_supplyUpkeep = IC.Ikariam.getInt(le_supplyUpkeepCell.innerHTML);
  460. var lo_row = {
  461. reason: IC.Language.$('finance.upkeep.reason.' + i),
  462. basicUpkeep: li_basicUpkeep,
  463. supplyUpkeep: li_supplyUpkeep,
  464. result: li_basicUpkeep + li_supplyUpkeep
  465. };
  466. ro_data.rows.push(lo_row);
  467. }
  468. return ro_data;
  469. };
  470. /**
  471. * Prepare the table rows for easy adding to the new table.
  472. *
  473. * @param {element[]} ia_oldUpkeepReductionTables
  474. * The old upkeep tables to collapse.
  475. *
  476. * @return {object[]}
  477. * The data for the table rows.
  478. * Signature:
  479. * <code>[{
  480. * classes: 'class' || ['class1', 'class2', ...]
  481. * isHeadRow: true || false
  482. * cells: [
  483. * { className: 'class' || ['class1', 'class2', ...], text: 'cellContent' (optional) }
  484. * ]
  485. * }]</code>
  486. */
  487. var _lf_prepareTableRows = function(ia_oldUpkeepReductionTables) {
  488. var lo_data = _lf_getData(ia_oldUpkeepReductionTables);
  489. var ra_tableRows = [];
  490. // Header
  491. ra_tableRows.push({
  492. classes: [],
  493. isHeadRow: true,
  494. cells: [
  495. { className: ['city'] },
  496. { className: ['value', 'res'], text: IC.Language.$('finance.upkeep.basic') },
  497. { className: ['value', 'res'], text: IC.Language.$('finance.upkeep.supply') },
  498. { className: ['value', 'res'], text: IC.Language.$('finance.upkeep.result') }
  499. ]
  500. });
  501. // Income without reduction
  502. ra_tableRows.push({
  503. classes: ['alt', 'bottomLine'],
  504. isHeadRow: false,
  505. cells: [
  506. { className: ['city'], text: IC.Language.$('finance.income.start') },
  507. { className: ['value', 'res'] },
  508. { className: ['value', 'res'] },
  509. { className: ['value', 'res'], text: IC.Ikariam.formatToIkaNumber(lo_data.priorToReduction) }
  510. ]
  511. });
  512. // Income reduction
  513. lo_data.rows.forEach(function(io_row, ii_index) {
  514. var trClass = [];
  515. if(ii_index % 2 === 1)
  516. trClass = ['alt', 'bottomLine'];
  517. ra_tableRows.push({
  518. classes: trClass,
  519. isHeadRow: false,
  520. cells: [
  521. { className: ['city'], text: io_row.reason },
  522. { className: ['value', 'res'], text: IC.Ikariam.formatToIkaNumber(-io_row.basicUpkeep) },
  523. { className: ['value', 'res'], text: IC.Ikariam.formatToIkaNumber(-io_row.supplyUpkeep) },
  524. { className: ['hidden'], text: IC.Ikariam.formatToIkaNumber(-io_row.result) }
  525. ]
  526. });
  527. });
  528. // Result
  529. ra_tableRows.push({
  530. classes: ['result'],
  531. isHeadRow: false,
  532. cells: [
  533. { className: ['sigma'], text: '<img alt="Summe" src="skin/layout/sigma.png">' },
  534. { className: ['value', 'res'] },
  535. { className: ['value', 'res'] },
  536. { className: ['hidden'], text: IC.Ikariam.formatToIkaNumber(lo_data.income) }
  537. ]
  538. });
  539. return ra_tableRows;
  540. };
  541. /**
  542. * Create the new upkeep reduction table.
  543. *
  544. * @param {element[]} ia_oldUpkeepReductionTables
  545. * The old upkeep tables.
  546. */
  547. var _lf_createNewTable = function(ia_oldUpkeepReductionTables) {
  548. var le_shortTable = IC.myGM.addElement('table', ia_oldUpkeepReductionTables[0].parentNode, {
  549. 'id': 'balance',
  550. 'classes': ['table01', 'border', 'left']
  551. }, null, ia_oldUpkeepReductionTables[0]);
  552. var la_tableRows = _lf_prepareTableRows(ia_oldUpkeepReductionTables);
  553. la_tableRows.forEach(function(io_rowData) {
  554. _go_generalFunctions.createTableRow(le_shortTable, io_rowData.classes, io_rowData.cells, io_rowData.isHeadRow);
  555. });
  556. IC.myGM.addElement('hr', ia_oldUpkeepReductionTables[0].parentNode, {}, null, ia_oldUpkeepReductionTables[0]);
  557. };
  558. /**
  559. * Toggle the status of an old upkeep table (collapsed / non-collapsed).
  560. */
  561. var _lf_toggleUpkeepReductionTable = function() {
  562. IC.myGM.toggleShowHideButton(this);
  563. var la_rows = IC.myGM.$$('tr:not(:first-child)', this.parentNode.parentNode.parentNode);
  564. la_rows.forEach(function(ie_row) {
  565. ie_row.classList.toggle('invisible');
  566. });
  567. // Adjust the size of the Scrollbar.
  568. IC.ika.controller.adjustSizes();
  569. };
  570. /**
  571. * Minimize the old upkeep tables and make them collapsable.
  572. *
  573. * @param {element[]} ia_oldUpkeepReductionTables
  574. * The old upkeep tables to collapse.
  575. */
  576. var _lf_minimizeOldTables = function(ia_oldUpkeepReductionTables) {
  577. for(var i = 0; i < ia_oldUpkeepReductionTables.length; i++) {
  578. var la_rows = IC.myGM.$$('tr', ia_oldUpkeepReductionTables[i]);
  579. la_rows.forEach(function(ie_row, ii_index) {
  580. if(ii_index !== 0)
  581. ie_row.classList.add('invisible');
  582. });
  583. var le_buttonParent = IC.myGM.$('th', la_rows[0]);
  584. IC.myGM.addElement('div', le_buttonParent, {
  585. 'class': 'maximizeImg',
  586. 'style': [['cssFloat', 'left']],
  587. 'title': IC.Language.$('general.expand'),
  588. 'click': _lf_toggleUpkeepReductionTable
  589. }, null, le_buttonParent.firstChild);
  590. }
  591. };
  592. /**
  593. * Callback to show the short upkeep reduction table.
  594. */
  595. var _lf_doShowShortTable = function() {
  596. var la_oldUpkeepReductionTables = IC.myGM.$$('.upkeepReductionTable');
  597. _lf_createNewTable(la_oldUpkeepReductionTables);
  598. _lf_minimizeOldTables(la_oldUpkeepReductionTables);
  599. // Adjust the size of the Scrollbar.
  600. IC.ika.controller.adjustSizes();
  601. };
  602. /**
  603. * Update the settings to execute the callback or delete the handler.
  604. *
  605. * @param {boolean} ib_showShortTable
  606. * If the user selected the checkbox to show the short upkeep reduction table.
  607. */
  608. this.updateSettings = function(ib_showShortTable) {
  609. if(ib_showShortTable === true) {
  610. IC.RefreshHandler.add('finances', 'shortUpkeepReductionTable', function() { _lf_doShowShortTable(); });
  611. return;
  612. }
  613. IC.RefreshHandler.remove('finances', 'shortUpkeepReductionTable');
  614. };
  615. };
  616. // Show the income also on top in finance popup.
  617. IC.Options.addCheckbox('showIncomeOnTop', 'diverseOptions', 1, true, IC.Language.$('finance.options.showIncomeOnTop'), { changeCallback: _go_incomeOnTop.updateSettings });
  618. // Short overview upkeep reduction table in finance popup.
  619. IC.Options.addCheckbox('shortUpkeepReductionTable', 'diverseOptions', 1, true, IC.Language.$('finance.options.shortUpkeepReductionTable'), { changeCallback: _go_shortUpkeepReductionTable.updateSettings });
  620. // Add a divider line.
  621. IC.Options.addLine('diverseOptions', 1);
  622. })();
  623. IC.con.timeStamp('IkariamEnhancedUI: finance functions created');
  624. // Functions for missing resources.
  625. (function() {
  626. /**
  627. * Storage for the missing ressources functions.
  628. *
  629. * @type {object}
  630. */
  631. var _go_showMissingResources = new function() {
  632. /**
  633. * Update the information in the missing resources wrappers.
  634. *
  635. * @param {boolean} ib_isUpdateView
  636. * If the update is in the update view.
  637. */
  638. var _lf_updateInformation = function(ib_isUpdateView) {
  639. var la_currentResources = [
  640. IC.ika.getModel().currentResources.resource, // Wood.
  641. IC.ika.getModel().currentResources[1], // Wine.
  642. IC.ika.getModel().currentResources[2], // Marble.
  643. IC.ika.getModel().currentResources[3], // Crystal.
  644. IC.ika.getModel().currentResources[4] // Sulfur.
  645. ];
  646. var lb_showPositiveNumbers = IC.Options.getOption('missingResources', 'showPositive') === true && ib_isUpdateView === true;
  647. var lb_showMissingColoured = IC.Options.getOption('missingResources', 'showColoured');
  648. var ls_resourcesPattern = '%resources%';
  649. if(ib_isUpdateView !== true)
  650. ls_resourcesPattern = ' (' + ls_resourcesPattern + ')';
  651. for(var i = 0; i < IC.Ikariam.resourceNames.length; i++) {
  652. var la_missingWrappers = IC.myGM.$$('.' + IC.myGM.prefix + 'missingResources' + IC.Ikariam.resourceNames[i]);
  653. if(!!la_missingWrappers) {
  654. for(var k = 0; k < la_missingWrappers.length; k++) {
  655. var le_neededWrapper = la_missingWrappers[k].previousSibling;
  656. var li_missing = la_currentResources[i] - IC.Ikariam.getInt(le_neededWrapper.nodeValue);
  657. if(li_missing < 0 || lb_showPositiveNumbers === true) {
  658. var ls_formattedMissingValue = IC.Ikariam.formatToIkaNumber(li_missing, lb_showMissingColoured, true);
  659. la_missingWrappers[k].innerHTML = ls_resourcesPattern.replace(/\%resources\%/, ls_formattedMissingValue);
  660. } else {
  661. la_missingWrappers[k].innerHTML = '';
  662. }
  663. }
  664. }
  665. }
  666. };
  667. /**
  668. * Add the missing resources wrappers.
  669. *
  670. * @param {boolean} ib_isUpdateView
  671. * If the wrappers are added to the update view.
  672. */
  673. var _lf_addMissingWrappers = function(ib_isUpdateView) {
  674. var ls_wrapperSelector = '#buildingGround .resources';
  675. if(ib_isUpdateView === true)
  676. ls_wrapperSelector = '#sidebar .resources';
  677. var la_wrappers = IC.myGM.$$(ls_wrapperSelector);
  678. for(var i = 0; i < la_wrappers.length; i++) {
  679. for(var k = 0; k < IC.Ikariam.resourceNames.length; k++) {
  680. var le_resourceNode = IC.myGM.$('.' + IC.Ikariam.resourceNames[k], la_wrappers[i]);
  681. if(!!le_resourceNode) {
  682. IC.myGM.addElement('span', le_resourceNode, { 'classes': ['missingResources', 'missingResources' + IC.Ikariam.resourceNames[k]] }, true);
  683. }
  684. }
  685. }
  686. _lf_updateInformation(ib_isUpdateView);
  687. };
  688. /**
  689. * Update the missing resources in building ground popup.
  690. */
  691. var _lf_doUpdateInBuildingView = function() {
  692. if(!IC.myGM.$('#buildingGround_c')) {
  693. IC.Observer.remove('missingResourcesBuilding');
  694. return;
  695. }
  696.  
  697. _lf_updateInformation(false);
  698. };
  699. /**
  700. * Update the missing resources in update view.
  701. */
  702. var _lf_doUpdateInUpdateView = function() {
  703. if(!IC.myGM.$('#buildingUpgrade')) {
  704. IC.Observer.remove('missingResourcesUpdate');
  705. return;
  706. }
  707.  
  708. _lf_updateInformation(true);
  709. };
  710. /**
  711. * Show the missing resources in building ground popup.
  712. */
  713. var _lf_doShowInBuildingGround = function() {
  714. _lf_addMissingWrappers(false);
  715. IC.Observer.add('missingResourcesBuilding', IC.myGM.$('#cityResources'), { childList: true, subtree: true }, _lf_doUpdateInBuildingView, _lf_doUpdateInBuildingView);
  716. };
  717. /**
  718. * Show the missing resources in update view.
  719. */
  720. var _lf_doShowInUpdateView = function() {
  721. if(!IC.myGM.$('#buildingUpgrade') || IC.myGM.$$('.' + IC.myGM.prefix + 'missingResources').length > 0)
  722. return;
  723. _lf_addMissingWrappers(true);
  724. IC.Observer.add('missingResourcesUpgrade', IC.myGM.$('#cityResources'), { childList: true, subtree: true }, _lf_doUpdateInUpdateView, _lf_doUpdateInUpdateView);
  725. };
  726. /**
  727. * Update the settings to execute the callback or delete the handler.
  728. *
  729. * @param {boolean} ib_showMissingResources
  730. * If the user selected the checkbox to show the missing resources info.
  731. */
  732. this.updateSettings = function(ib_showMissingResources) {
  733. if(ib_showMissingResources === true) {
  734. IC.RefreshHandler.add('buildingGround', 'showMissingResources', _lf_doShowInBuildingGround);
  735. IC.RefreshHandler.add('%', 'showMissingResources', _lf_doShowInUpdateView);
  736. IC.myGM.addStyle(
  737. '#sidebar #buildingUpgrade ul.resources li { width: 120px; } \
  738. #sidebar #buildingUpgrade ul.resources li.time { width: 60px !important; } \
  739. #sidebar .' + IC.myGM.prefix + 'missingResources { float: right; }',
  740. 'showMissingResources'
  741. );
  742. return;
  743. }
  744. IC.RefreshHandler.remove('buildingGround', 'showMissingResources');
  745. IC.RefreshHandler.remove('%', 'showMissingResources');
  746. IC.myGM.removeStyle('showMissingResources');
  747. };
  748. };
  749. IC.Options.addWrapper('missingResources', IC.Language.$('missingResources.options.wrapperTitle'));
  750. // Show missing resources in upgrade / building view.
  751. IC.Options.addCheckbox('show', 'missingResources', 1, true, IC.Language.$('missingResources.options.show'), { changeCallback: _go_showMissingResources.updateSettings });
  752. // Disable coloring of the missing resources.
  753. IC.Options.addCheckbox('showPositive', 'missingResources', 2, true, IC.Language.$('missingResources.options.showPositive'), {});
  754. // Show only missing ressources, not also remaining.
  755. IC.Options.addCheckbox('showColoured', 'missingResources', 2, true, IC.Language.$('missingResources.options.showColoured'), {});
  756. })();
  757. IC.con.timeStamp('IkariamEnhancedUI: missing resource functions created');
  758. // Functions for tooltips.
  759. (function() {
  760. /**
  761. * Storage for the autoshow tootips functions.
  762. *
  763. * @type {object}
  764. */
  765. var _go_autoshowTooltips = new function() {
  766. /**
  767. * General function for autowhow.
  768. *
  769. * @param {string} onclickWrapperClass
  770. * The class of the wrapper which has the onclik attribute set.
  771. */
  772. var _lf_autoshowTooltipsGeneral = function(onclickWrapperClass) {
  773. IC.myGM.$$('.' + onclickWrapperClass).forEach(function(onclickWrapper) {
  774. var onclickFunction = onclickWrapper.onclick;
  775. onclickWrapper.onclick = 'return false;';
  776. var newHandler = IC.myGM.$('.magnify_icon', onclickWrapper);
  777. if(!newHandler)
  778. newHandler = onclickWrapper;
  779. newHandler.addEventListener('mouseover', function(e) { IC.ika.controller.captureMousePosition(e); onclickFunction(e); }, true);
  780. });
  781. IC.myGM.$('.templateView .mainContent').addEventListener('click', function() { IC.win.$(document).trigger("closeExclusiveInfo"); }, true);
  782. };
  783. /**
  784. * Autmatically show tooltips in alliance member lists.
  785. */
  786. var _lf_doAutoshowTooltipsAlliance = function() {
  787. _lf_autoshowTooltipsGeneral('cityInfo');
  788. };
  789. /**
  790. * Autmatically show tooltips in military advisor.
  791. */
  792. var _lf_doAutoshowTooltipsMilitaryAdvisor = function() {
  793. if(IC.Options.getOption('moduleOptions', 'showDirectMilitaryTooltips') === true)
  794. return;
  795. _lf_autoshowTooltipsGeneral('spyMilitary');
  796. };
  797. /**
  798. * Update the settings to execute the callback or delete the handler.
  799. *
  800. * @param {boolean} autoshowTooltips
  801. * If the user selected the checkbox to autoshow tooltips.
  802. */
  803. this.updateSettings = function(autoshowTooltips) {
  804. var alliancePopupIds = ['diplomacyAllyMemberlist', 'embassy'];
  805. if(autoshowTooltips === true) {
  806. IC.RefreshHandler.add('militaryAdvisor', 'autoshowTooltips', _lf_doAutoshowTooltipsMilitaryAdvisor);
  807. IC.RefreshHandler.add(alliancePopupIds, 'autoshowTooltips', _lf_doAutoshowTooltipsAlliance);
  808. return;
  809. }
  810. IC.RefreshHandler.remove('militaryAdvisor', 'autoshowTooltips');
  811. IC.RefreshHandler.remove(alliancePopupIds, 'autoshowTooltips');
  812. };
  813. };
  814. /**
  815. * Storage for the direct military tooltip functions.
  816. *
  817. * @type {object}
  818. */
  819. var _go_directMilitaryTooltips = new function() {
  820. /**
  821. * Storage for the class ids and their corresponding translations. Each class is a property of the object with the translation stored in it.
  822. *
  823. * @type {object}
  824. */
  825. var _lo_idTranslation = {};
  826. /**
  827. * Fill the id translation object.
  828. */
  829. var _lf_fillIdTranslation = function() {
  830. if(_lo_idTranslation.length === 0)
  831. return;
  832. var la_troops = ['swordsman', 'phalanx', 'archer', 'marksman', 'mortar', 'slinger', 'catapult', 'ram', 'steamgiant', 'bombardier', 'cook', 'medic', 'gyrocopter', 'spearman', 'spartan'];
  833. var la_ships = ['balliasta', 'catapult', 'flamethrower', 'mortar', 'ram', 'steamboat', 'rocketship', 'submarine', 'paddlespeedship', 'balloncarrier', 'tender', 'transport', 'premium_transport'];
  834. var la_resources = IC.Ikariam.resourceNames;
  835. la_resources.push('gold');
  836. la_troops.forEach(function(is_troopName) {
  837. _lo_idTranslation[is_troopName] = IC.Language.$('diverse.name.unit.' + is_troopName);
  838. });
  839. la_ships.forEach(function(is_shipName) {
  840. _lo_idTranslation['ship_' + is_shipName] = IC.Language.$('diverse.name.ship.' + is_shipName.replace('premium_', ''));
  841. });
  842. la_resources.forEach(function(is_resourceName) {
  843. _lo_idTranslation[is_resourceName] = IC.Language.$('diverse.name.resource.' + is_resourceName);
  844. });
  845. };
  846. /**
  847. * Hide the number of ships for the own peaceful missions (trade / transport).
  848. */
  849. var _lf_hideShipNumberOwnPeacefulMissions = function() {
  850. var la_ownEventTableRows = IC.myGM.$$('#js_MilitaryMovementsFleetMovementsTable .military_event_table tr.own');
  851. la_ownEventTableRows.forEach(function(ie_tableRow) {
  852. var le_missionDiv = IC.myGM.$('td:nth-child(1) div.mission_icon', ie_tableRow);
  853. var lb_peacefulMission = le_missionDiv.classList.contains('transport') || le_missionDiv.classList.contains('trade');
  854. if(lb_peacefulMission === true) {
  855. IC.myGM.$('td:nth-child(4) div', ie_tableRow).classList.add('invisible');
  856. }
  857. });
  858. };
  859. /**
  860. * Show the military tooltips directly.
  861. */
  862. var _lf_doShowDirectMilitaryTooltips = function() {
  863. _lf_fillIdTranslation();
  864. _lf_hideShipNumberOwnPeacefulMissions();
  865. IC.myGM.$$('.spyMilitary').forEach(function(ie_movementWrapper) {
  866. ie_movementWrapper.onclick = 'return false;';
  867. });
  868. var le_movementsTable = IC.myGM.$('#js_MilitaryMovementsFleetMovementsTable');
  869. IC.myGM.forEach(_lo_idTranslation, function(is_classId, is_translation) {
  870. IC.myGM.$$('.icon40.' + is_classId, le_movementsTable).forEach(function(ie_detailIcon) {
  871. ie_detailIcon.title = is_translation;
  872. });
  873. });
  874. };
  875. /**
  876. * Update the settings to execute the callback or delete the handler.
  877. *
  878. * @param {boolean} ib_showDirectMilitaryTooltips
  879. * If the user selected the checkbox to show the military tooltips directly.
  880. */
  881. this.updateSettings = function(ib_showDirectMilitaryTooltips) {
  882. if(ib_showDirectMilitaryTooltips === true) {
  883. IC.RefreshHandler.add('militaryAdvisor', 'showDirectMilitaryTooltips', _lf_doShowDirectMilitaryTooltips);
  884. IC.myGM.addStyle(
  885. '#js_MilitaryMovementsFleetMovementsTable .military_event_table .magnify_icon { background-image: none; cursor: default; width: 240px; } \
  886. #js_MilitaryMovementsFleetMovementsTable .military_event_table .magnify_icon .infoTip { display: inline; position: relative; padding: 0px; border: none; } \
  887. #js_MilitaryMovementsFleetMovementsTable .military_event_table .magnify_icon .infoTip h5 { display: none; } \
  888. #js_MilitaryMovementsFleetMovementsTable .military_event_table .icon40 { background-size: 25px 25px; background-color: transparent; padding: 26px 3px 0px 3px; width: 30px; } \
  889. #js_MilitaryMovementsFleetMovementsTable .military_event_table .icon40.resource_icon { background-size: 20px 16px; }',
  890. 'showDirectMilitaryTooltips'
  891. );
  892. return;
  893. }
  894. IC.RefreshHandler.remove('militaryAdvisor', 'showDirectMilitaryTooltips');
  895. IC.myGM.removeStyle('showDirectMilitaryTooltips');
  896. };
  897. };
  898. // Show alliance / military tooltips directly.
  899. IC.Options.addCheckbox('autoshowTooltips', 'diverseOptions', 1, true, IC.Language.$('tooltips.options.autoshow'), { changeCallback: _go_autoshowTooltips.updateSettings });
  900. // Show military tooltips directly.
  901. IC.Options.addCheckbox('showDirectMilitaryTooltips', 'diverseOptions', 1, false, IC.Language.$('tooltips.options.showDirectInMilitaryAdvisor'), { changeCallback: _go_directMilitaryTooltips.updateSettings });
  902. // Add a divider line.
  903. IC.Options.addLine('diverseOptions', 1);
  904. })();
  905. IC.con.timeStamp('IkariamEnhancedUI: tooltip functions created');
  906. // Zoom function.
  907. (function() {
  908. /**
  909. * Storage for the zoom functions.
  910. *
  911. * @type {object}
  912. */
  913. var _go_zoomView = new function() {
  914. /**
  915. * Storage for the minimum zoom factor.
  916. *
  917. * @type {int}
  918. */
  919. var _li_minZoom = 55;
  920. /**
  921. * Storage for the maximum zoom factor.
  922. *
  923. * @type {int}
  924. */
  925. var _li_maxZoom = 150;
  926. /**
  927. * Storage for the zoom step size.
  928. *
  929. * @type {int}
  930. */
  931. var _li_zoomStep = 5;
  932. /**
  933. * Storage for the actual mousewheel callback.
  934. *
  935. * @type {function}
  936. */
  937. var _lf_mousewheelCallbackStorage = IC.ika.getController().mouseScrollHandle;
  938. /**
  939. * Getter for the minimum zoom factor.
  940. *
  941. * @return {int}
  942. * The minimum zoom factor.
  943. */
  944. this.__defineGetter__('minZoom', function() { return _li_minZoom; });
  945. /**
  946. * Getter for the maximum zoom factor.
  947. *
  948. * @return {int}
  949. * The maximum zoom factor.
  950. */
  951. this.__defineGetter__('maxZoom', function() { return _li_maxZoom; });
  952. /**
  953. * Getter for the zoom step size.
  954. *
  955. * @return {int}
  956. * The zoom step size.
  957. */
  958. this.__defineGetter__('zoomStep', function() { return _li_zoomStep; });
  959. /**
  960. * Initialize the zoom bounds (min and max zoom).
  961. */
  962. var _lf_initBounds = function() {
  963. var li_minZoom = Math.round(IC.ika.worldview_scale_min * 100);
  964. if(li_minZoom % 5 != 0)
  965. li_minZoom = li_minZoom + (5 - (li_minZoom % 5));
  966.  
  967. _li_minZoom = li_minZoom;
  968. IC.ika.worldview_scale_min = _li_minZoom / 100;
  969. IC.ika.worldview_scale_max = _li_maxZoom / 100;
  970. };
  971. /**
  972. * Zoom the world view, as there is no function provided by Ikariam.
  973. *
  974. * @param {decimal} in_zoomFactor
  975. * The zoom factor as decimal number (1 =^= 100%)
  976. */
  977. var _lf_zoomWorldView = function(in_zoomFactor) {
  978. var li_translateXY = (100 - 100 / in_zoomFactor) / 2;
  979. var ls_heightWidth = (100 / in_zoomFactor) + '% !important';
  980. var ls_transformString = 'scale(' + in_zoomFactor + ') translate(' + li_translateXY + '%, ' + li_translateXY + '%)';
  981. IC.myGM.addStyle(
  982. '#scrollcover { transform: ' + ls_transformString + '; -webkit-transform: ' + ls_transformString + '; height: ' + ls_heightWidth + '; width: ' + ls_heightWidth + '; }',
  983. 'zoomWorld', true
  984. );
  985. var le_map = IC.myGM.$('#map1');
  986. le_map.style.top = '0px';
  987. le_map.style.left = '0px';
  988. };
  989. /**
  990. * Rescale the badges and symbols.
  991. *
  992. * @param {decimal} in_zoomFactorNumber
  993. * The zoom factor as decimal number (1 =^= 100%)
  994. */
  995. var _lf_scaleChildren = function(in_zoomFactorNumber) {
  996. var ls_transformString = 'transform: scale(' + 1 / in_zoomFactorNumber + '); -webkit-transform: scale(' + 1 / in_zoomFactorNumber + ');';
  997. var ls_style = '';
  998. if(IC.Ikariam.view == 'world') {
  999. var ls_ownerState = '';
  1000. if(in_zoomFactorNumber < 1)
  1001. ls_ownerState = ', .ownerState';
  1002. ls_style = '.islandTile .wonder, .islandTile .tradegood, .islandTile .cities, .islandTile .piracyInRange' + ls_ownerState + ' { ' + ls_transformString + ' } \
  1003. .islandTile .cities { bottom: 10px !important; }';
  1004. }
  1005. if(IC.Ikariam.view == 'island') {
  1006. var ls_movePiracy = 'transform: translate(0px, -' + (1 - in_zoomFactorNumber) * 20 + 'px) scale(' + 1 / in_zoomFactorNumber + ');';
  1007. ls_style = '.cityLocation .scroll_img, .cityLocationScroll .scroll_img { ' + ls_transformString + ' } \
  1008. .piracyRaid { ' + ls_movePiracy + ' }';
  1009. }
  1010. if(IC.Ikariam.view == 'town')
  1011. ls_style = '.timetofinish { ' + ls_transformString + ' }';
  1012. IC.myGM.addStyle(ls_style, 'scaleChildren', true);
  1013. };
  1014. /**
  1015. * Update the zoom in and zoom out button and the percentage in the middle.
  1016. *
  1017. * @param {int} ii_zoomFactor
  1018. * The zoom factor as percentage.
  1019. */
  1020. var _lf_updateZoomButtons = function(ii_zoomFactor) {
  1021. var le_zoomFactorDiv = IC.myGM.$('#' + IC.myGM.prefix + 'zoomFactor');
  1022. var le_zoomIn = IC.myGM.$('#' + IC.myGM.prefix + 'zoomIn');
  1023. var le_zoomOut = IC.myGM.$('#' + IC.myGM.prefix + 'zoomOut');
  1024. if(!!le_zoomFactorDiv) {
  1025. le_zoomFactorDiv.innerHTML = ii_zoomFactor + '%';
  1026. }
  1027. if(!!le_zoomIn) {
  1028. le_zoomIn.style.visibility = '';
  1029. if(ii_zoomFactor >= _li_maxZoom)
  1030. le_zoomIn.style.visibility = 'hidden';
  1031. }
  1032. if(!!le_zoomOut) {
  1033. le_zoomOut.style.visibility = '';
  1034. if(ii_zoomFactor <= _li_minZoom)
  1035. le_zoomOut.style.visibility = 'hidden';
  1036. }
  1037. };
  1038. /**
  1039. * Calculate the zoom factor as decimal number and execute the zoom function. If it is requestet, call also the rescale function for child elements.
  1040. *
  1041. * @param {int} ii_zoomFactor
  1042. * The zoom factor as percentage.
  1043. */
  1044. var _lf_zoomView = function(ii_zoomFactor) {
  1045. var ln_zoomFactorNumber = ii_zoomFactor / 100.0;
  1046. var li_scale = 0;
  1047. if(IC.Ikariam.view == 'island')
  1048. li_scale = IC.ika.worldview_scale_island;
  1049. if(IC.Ikariam.view == 'town')
  1050. li_scale = IC.ika.worldview_scale_city;
  1051. if(IC.Ikariam.view == 'world') {
  1052. _lf_zoomWorldView(ln_zoomFactorNumber);
  1053. } else {
  1054. var li_stepNumber = Math.round((ln_zoomFactorNumber - li_scale) / .05);
  1055. var le_worldview = IC.myGM.$('#worldview');
  1056. var li_posX = le_worldview.offsetLeft + le_worldview.offsetWidth / 2;
  1057. var li_posY = le_worldview.offsetTop + le_worldview.offsetHeight / 2;
  1058. IC.ika.controller.scaleWorldMap(li_stepNumber, li_posX, li_posY);
  1059. }
  1060. if(IC.Options.getOption('zoom', IC.Ikariam.view + 'ScaleChildren') === true)
  1061. _lf_scaleChildren(ln_zoomFactorNumber);
  1062. };
  1063. /**
  1064. * Ensure that the requested zoom factor is in the bounds and update the view.
  1065. *
  1066. * @param {int} ii_zoomFactor
  1067. * The zoom factor as percentage.
  1068. */
  1069. var _lf_zoom = function(ii_zoomFactor) {
  1070. if(ii_zoomFactor > _li_maxZoom)
  1071. ii_zoomFactor = _li_maxZoom;
  1072. if(ii_zoomFactor < _li_minZoom)
  1073. ii_zoomFactor = _li_minZoom;
  1074. IC.Options.setOption('zoom', IC.Ikariam.view + 'Factor', ii_zoomFactor);
  1075. _lf_updateZoomButtons(ii_zoomFactor);
  1076. _lf_zoomView(ii_zoomFactor);
  1077. };
  1078. /**
  1079. * Zoom one step in.
  1080. */
  1081. var _lf_zoomIn = function() {
  1082. var li_factor = IC.Ikariam.getInt(IC.Options.getOption('zoom', IC.Ikariam.view + 'Factor', 100)) + _li_zoomStep;
  1083. _lf_zoom(li_factor);
  1084. };
  1085. /**
  1086. * Zoom one step out.
  1087. */
  1088. var _lf_zoomOut = function() {
  1089. var li_factor = IC.Options.getOption('zoom', IC.Ikariam.view + 'Factor', 100) - _li_zoomStep;
  1090. _lf_zoom(li_factor);
  1091. };
  1092. /**
  1093. * Add the zoom buttons.
  1094. */
  1095. var _lf_addZoomButtons = function() {
  1096. var le_zoomWrapper = IC.myGM.addElement('div', ge_toolbar, { 'id': 'zoomWrapper' });
  1097. IC.myGM.addElement('div', le_zoomWrapper, {
  1098. 'id': 'zoomIn',
  1099. 'class': 'maximizeImg',
  1100. 'title': IC.Language.$('zoom.zoomIn'),
  1101. 'click': _lf_zoomIn
  1102. });
  1103. IC.myGM.addElement('div', le_zoomWrapper, {
  1104. 'id': 'zoomFactor',
  1105. 'title': IC.Language.$('zoom.factor')
  1106. });
  1107. IC.myGM.addElement('div', le_zoomWrapper, {
  1108. 'id': 'zoomOut',
  1109. 'class': 'minimizeImg',
  1110. 'title': IC.Language.$('zoom.zoomOut'),
  1111. 'click': _lf_zoomOut
  1112. });
  1113. IC.myGM.addStyle(
  1114. '#' + IC.myGM.prefix + 'zoomWrapper { width: 72px; margin: 0px -5px !important; transform: scale(0.75); scale(0.75); -webkit-transform: scale(0.75); } \
  1115. #' + IC.myGM.prefix + 'zoomWrapper > div { display: inline-block; position: relative; } \
  1116. #' + IC.myGM.prefix + 'zoomFactor { top: -4px; width: 35px; text-align: center; }',
  1117. 'zoomButtons'
  1118. );
  1119. };
  1120. /**
  1121. * 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.
  1122. */
  1123. var _lf_resetZoom = function() {
  1124. 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')
  1125. _lf_zoomView(100);
  1126. IC.ika.worldview_scale_max = 1;
  1127. IC.myGM.removeElement(IC.myGM.$('#' + IC.myGM.prefix + 'zoomWrapper'));
  1128. IC.myGM.removeStyle('zoomButtons');
  1129. IC.myGM.removeStyle('zoomWorld');
  1130. IC.myGM.removeStyle('scaleChildren');
  1131. };
  1132. /**
  1133. * Check, if the key are pressed which are required to zoom with the mouse.
  1134. *
  1135. * @param {object} io_event
  1136. * The "event object" with information about the mouse scroll and pressed keys.
  1137. *
  1138. * @return {boolean}
  1139. * If the correct keys were pressed.
  1140. */
  1141. var _lf_keysOK = function(io_event) {
  1142. var lb_ctrlOK = !!io_event.ctrlKey;
  1143. if(IC.Options.getOption('zoom', 'ctrlAsAccessKey') === false)
  1144. lb_ctrlOK = true;
  1145. var lb_altOK = !!io_event.altKey;
  1146. if(IC.Options.getOption('zoom', 'altAsAccessKey') === false)
  1147. lb_altOK = true;
  1148. var lb_shiftOK = !!io_event.shiftKey;
  1149. if(IC.Options.getOption('zoom', 'shiftAsAccessKey') === false)
  1150. lb_shiftOK = true;
  1151. return lb_ctrlOK && lb_altOK && lb_shiftOK;
  1152. };
  1153. /**
  1154. * Calculate the delta the mousewheel was turned.
  1155. *
  1156. * @param {object} io_event
  1157. * The "event object" with information about the mouse scroll and pressed keys.
  1158. *
  1159. * @return {int}
  1160. * The delta the mousewheel was moved.
  1161. */
  1162. var _lf_calculateDelta = function(io_event) {
  1163. var ri_stepNumber = 0;
  1164.  
  1165. // Get the number of steps to scroll.
  1166. if(io_event.wheelDelta)
  1167. ri_stepNumber = io_event.wheelDelta / 120;
  1168.  
  1169. if (io_event.detail)
  1170. ri_stepNumber = -io_event.detail / 3;
  1171.  
  1172. if (io_event.wheelDeltaY !== undefined)
  1173. ri_stepNumber = io_event.wheelDeltaY / 120;
  1174. // If the number is between -1 and 0, set it to -1.
  1175. if(ri_stepNumber < 0)
  1176. ri_stepNumber = ri_stepNumber > -1 ? -1 : Math.round(ri_stepNumber);
  1177.  
  1178. // If the number is between 0 and 1, set it to 1.
  1179. else
  1180. ri_stepNumber = ri_stepNumber < 1 ? 1 : Math.round(ri_stepNumber);
  1181. return ri_stepNumber;
  1182. };
  1183. /**
  1184. * Handler for mousescroll to zoom.
  1185. *
  1186. * @param {object} io_event
  1187. * The "event object" with information about the mouse scroll and pressed keys.
  1188. *
  1189. * @return false
  1190. * If the prevent default method is not available to prevent the default action.
  1191. */
  1192. var _lf_mouseScroll = function(io_event) {
  1193. if(_lf_keysOK(io_event) === true) {
  1194. // If the scrolling is horizontally return.
  1195. if(io_event.axis !== undefined && io_event.axis === io_event.HORIZONTAL_AXIS)
  1196. return;
  1197. var li_factor = IC.Ikariam.getInt(IC.Options.getOption('zoom', IC.Ikariam.view + 'Factor')) + _li_zoomStep * _lf_calculateDelta(io_event);
  1198. _lf_zoom(li_factor);
  1199. // Prevent the default event.
  1200. if(io_event.preventDefault)
  1201. io_event.preventDefault();
  1202. else
  1203. return false;
  1204. }
  1205. };
  1206. /**
  1207. * Change the mousewheel listener to a new callback.
  1208. *
  1209. * @param {function} if_newCallback
  1210. * The new callback for the mousewheel listener.
  1211. */
  1212. var _lf_changeMouseWheelListener = function(if_newCallback) {
  1213. if(_lf_mousewheelCallbackStorage == if_newCallback)
  1214. return;
  1215. var ls_scrollDivId = '#worldmap';
  1216. if(IC.Ikariam.view == 'world')
  1217. ls_scrollDivId = '#map1';
  1218. if(_lf_mousewheelCallbackStorage == IC.ika.getController().mouseScrollHandle) {
  1219. // Remove the ikariam mouse wheel listener and add the own. (with the use of Ikariam-jQuery)
  1220. IC.win.$(ls_scrollDivId).unbind('mousewheel');
  1221. var scrollDiv = IC.myGM.$(ls_scrollDivId);
  1222. scrollDiv.addEventListener('DOMMouseScroll', if_newCallback, false);
  1223. scrollDiv.addEventListener('mousewheel', if_newCallback, false);
  1224. } else {
  1225. var scrollDiv = IC.myGM.$(ls_scrollDivId);
  1226. scrollDiv.removeEventListener('DOMMouseScroll', _lf_mousewheelCallbackStorage, false);
  1227. scrollDiv.removeEventListener('mousewheel', _lf_mousewheelCallbackStorage, false);
  1228. IC.win.$(ls_scrollDivId).on('mousewheel', if_newCallback);
  1229. }
  1230. _lf_mousewheelCallbackStorage = if_newCallback;
  1231. };
  1232. /**
  1233. * Update the settings to execute the callback or delete the handler.
  1234. *
  1235. * @param {boolean} ib_zoomView
  1236. * If the user selected the checkbox to zoom.
  1237. */
  1238. this.updateSettings = function(ib_zoomView) {
  1239. _lf_initBounds();
  1240. _go_zoomOptions.renewFactorSelects();
  1241. if(ib_zoomView === true) {
  1242. _lf_addZoomButtons();
  1243. _lf_changeMouseWheelListener(_lf_mouseScroll);
  1244. _lf_zoom(IC.Options.getOption('zoom', IC.Ikariam.view + 'Factor'));
  1245. return;
  1246. }
  1247. _lf_resetZoom();
  1248. _lf_changeMouseWheelListener(IC.ika.getController().mouseScrollHandle);
  1249. };
  1250. };
  1251. /**
  1252. * Storage for the option creation functions.
  1253. *
  1254. * @type {object}
  1255. */
  1256. var _go_zoomOptions = new function() {
  1257. /**
  1258. * If the zoom wrapper is already created.
  1259. */
  1260. var _lb_zoomWrapperCreated = false;
  1261. /**
  1262. * Add the select fields for the zoom factors.
  1263. */
  1264. var _lf_addFactorSelects = function(ib_replace) {
  1265. var la_options = [];
  1266. for(var i = _go_zoomView.minZoom; i <= _go_zoomView.maxZoom; i = i + _go_zoomView.zoomStep) {
  1267. la_options.push({ value: i, label: i + '%' });
  1268. }
  1269. IC.Ikariam.viewNames.forEach(function(is_view, ii_index) {
  1270. IC.Options.addSelect(is_view + 'Factor', 'zoom', 'factors', 100, IC.Language.$('zoom.options.factor.' + is_view), la_options, { replace: !!ib_replace });
  1271. });
  1272. };
  1273. /**
  1274. * Add the checkboxes fields for rescaling the badges and icons.
  1275. */
  1276. var _lf_addScaleChildrenCheckboxes = function() {
  1277. IC.Options.addHTML('scaleChildrenDescription', 'zoom', 'scale', { html: '<p>' + IC.Language.$('zoom.options.scaleChildren.label') + '</p>' });
  1278. IC.Ikariam.viewNames.forEach(function(is_view) {
  1279. IC.Options.addCheckbox(is_view + 'ScaleChildren', 'zoom', 'scale', true, IC.Language.$('zoom.options.scaleChildren.' + is_view), {});
  1280. });
  1281. };
  1282. /**
  1283. * Add the checkboxes for the access keys.
  1284. */
  1285. var _lf_addAccessKeyCheckboxes = function() {
  1286. IC.Options.addHTML('accessKeyDescription', 'zoom', 'accessKeys', { html: '<p>' + IC.Language.$('zoom.options.accessKeyLabel') + '</p>' });
  1287. var la_accessKeys = ['ctrl', 'alt', 'shift'];
  1288. la_accessKeys.forEach(function(is_accessKey) {
  1289. var lb_defaultEnabled = (is_accessKey == 'ctrl');
  1290. IC.Options.addCheckbox(is_accessKey + 'AsAccessKey', 'zoom', 'accessKeys', lb_defaultEnabled, IC.Language.$('general.' + is_accessKey), {});
  1291. });
  1292. };
  1293. /**
  1294. * Create the zoom options wrapper and add the option elements.
  1295. */
  1296. this.create = function() {
  1297. _lf_addFactorSelects();
  1298. _lf_addScaleChildrenCheckboxes();
  1299. _lf_addAccessKeyCheckboxes();
  1300. _lb_zoomWrapperCreated = true;
  1301. };
  1302. /**
  1303. * Recreate the select fields for the zoom factor (and keep the old zoom factor).
  1304. */
  1305. this.renewFactorSelects = function() {
  1306. if(_lb_zoomWrapperCreated === false)
  1307. return;
  1308. _lf_addFactorSelects(true);
  1309. };
  1310. };
  1311. IC.Options.addWrapper('zoom', IC.Language.$('zoom.options.wrapperTitle'));
  1312. // Show missing resources in upgrade / building view.
  1313. IC.Options.addCheckbox('view', 'zoom', 'general', true, IC.Language.$('zoom.options.zoomView'), { changeCallback: _go_zoomView.updateSettings });
  1314. // Add the zoom function settings.
  1315. _go_zoomOptions.create();
  1316. })();
  1317. IC.con.timeStamp('IkariamEnhancedUI: zoom functions created');
  1318. // Ressource information.
  1319. (function() {
  1320. /**
  1321. * Storage for the style functions for the capacity bar and the direct income.
  1322. *
  1323. * @type {object}
  1324. */
  1325. var _go_styleFunctions = new function() {
  1326. /**
  1327. * Get the style for the #js_GlobalMenu_ elements.
  1328. *
  1329. * @param {string} is_incomeStyle
  1330. * How the income is styled.
  1331. *
  1332. * @return {string}
  1333. * The style string.
  1334. */
  1335. var _lf_getGlobalMenuStyle = function(is_incomeStyle) {
  1336. if(is_incomeStyle != 'alignLeft')
  1337. return '#js_GlobalMenu_wood, #js_GlobalMenu_wine, #js_GlobalMenu_marble, #js_GlobalMenu_crystal, #js_GlobalMenu_sulfur { padding-right: 4px; } ';
  1338. return '';
  1339. };
  1340. /**
  1341. * Gets the style for the separation of the resource values.
  1342. *
  1343. * @param {string} is_incomeStyle
  1344. * How the income is styled.
  1345. *
  1346. * @return {string}
  1347. * The style string.
  1348. */
  1349. var _lf_getSeparationStyle = function(is_incomeStyle) {
  1350. if(is_incomeStyle == 'withSeparation')
  1351. return '#resources_wood, #resources_wine, #resources_marble, #resources_glass { border-right: 1px dotted #542C0F; } ';
  1352. return '';
  1353. };
  1354. /**
  1355. * Get styles which are independent of the activation of the cpacity bar or direct income.
  1356. *
  1357. * @param {string} is_incomeStyle
  1358. * How the income is styled.
  1359. *
  1360. * @return {string}
  1361. * The style string.
  1362. */
  1363. var _lf_getGeneralStyles = function(is_incomeStyle) {
  1364. var ls_globalMenuStyle = _lf_getGlobalMenuStyle(is_incomeStyle);
  1365. var ls_separationStyle = _lf_getSeparationStyle(is_incomeStyle);
  1366. return ls_globalMenuStyle + ls_separationStyle;
  1367. };
  1368. /**
  1369. * Get the style for the capacity bar "wrapper".
  1370. *
  1371. * @param {string} is_capacityBarOrientation
  1372. * The orientation of the capacity bar.
  1373. * @param {string} is_incomeStyle
  1374. * How the income is styled.
  1375. *
  1376. * @return {string}
  1377. * The style string.
  1378. */
  1379. var _lf_getCapacityBarStyle = function(is_capacityBarOrientation, is_incomeStyle) {
  1380. var ls_height = 'height: 4px; ';
  1381. var ls_width = 'width: 79px;';
  1382. var ls_right = 'right: 4px; ';
  1383. var ls_marginLeft = '';
  1384. if(is_capacityBarOrientation == 'horizontal')
  1385. ls_width = 'width: 50px; ';
  1386. if(is_capacityBarOrientation == 'vertical') {
  1387. ls_height = 'height: 21px; ';
  1388. ls_width = 'width: 4px; ';
  1389. ls_right = '';
  1390. if(is_incomeStyle == 'alignLeft')
  1391. ls_marginLeft = 'margin-left: -7px; ';
  1392. }
  1393. return '.' + IC.myGM.prefix + 'capacityInformation { position: absolute; bottom: 4px; ' + ls_height + ls_width + ls_right + ls_marginLeft + '} ';
  1394. };
  1395. /**
  1396. * Get the style for the capacity bar with a border.
  1397. *
  1398. * @param {string} is_capacityBarOrientation
  1399. * The orientation of the capacity bar.
  1400. *
  1401. * @return {string}
  1402. * The style string.
  1403. */
  1404. var _lf_getCapacityBarWithBorderStyle = function(is_capacityBarOrientation) {
  1405. var ls_height = 'height: 3px; ';
  1406. var ls_width = 'width: 78px; ';
  1407. var ls_right = 'right: 3px; ';
  1408. if(is_capacityBarOrientation == 'horizontal')
  1409. ls_width = 'width: 50px; ';
  1410. if(is_capacityBarOrientation == 'vertical') {
  1411. ls_height = 'height: 20px; ';
  1412. ls_width = 'width: 3px; ';
  1413. ls_right = '';
  1414. }
  1415. return '.' + IC.myGM.prefix + 'capacityInformation.' + IC.myGM.prefix + 'border { border: 1px inset #906646; bottom: 3px; ' + ls_height + ls_width + ls_right + '} ';
  1416. };
  1417. /**
  1418. * Get the style for the capacity bar.
  1419. *
  1420. * @param {string} is_capacityBarOrientation
  1421. * The orientation of the capacity bar.
  1422. * @param {string} is_incomeStyle
  1423. * How the income is styled.
  1424. *
  1425. * @return {string}
  1426. * The style string.
  1427. */
  1428. var _lf_getCapacityStyle = function(is_capacityBarOrientation, is_incomeStyle) {
  1429. var ls_prefix = IC.myGM.prefix;
  1430. var ls_barStyle = '.' + ls_prefix + 'bar { height: 100%; width: 100%; bottom: 0px; position: absolute; } \
  1431. .' + ls_prefix + 'bar.' + ls_prefix + 'red { background-color: #AA0000; } \
  1432. .' + ls_prefix + 'bar.' + ls_prefix + 'yellow { background-color: #FFD700; } \
  1433. .' + ls_prefix + 'bar.' + ls_prefix + 'green { background-color: #669900; }';
  1434. var ls_capacityStyle = _lf_getCapacityBarStyle(is_capacityBarOrientation, is_incomeStyle);
  1435. var ls_capacityBorderStyle = _lf_getCapacityBarWithBorderStyle(is_capacityBarOrientation);
  1436. return ls_barStyle + ls_capacityStyle + ls_capacityBorderStyle;
  1437. };
  1438. /**
  1439. * Get the style for the direct hourly income in the town view.
  1440. *
  1441. * @param {boolean} ib_capacityBarActive
  1442. * If the capacity bar is shown.
  1443. * @param {string} is_capacityBarOrientation
  1444. * The orientation of the capacity bar.
  1445. * @param {string} is_incomeStyle
  1446. * How the income is styled.
  1447. *
  1448. * @return {string}
  1449. * The style string.
  1450. */
  1451. var _lf_getHourlyIncomeStyle = function(ib_capacityBarActive, is_capacityBarOrientation, is_incomeStyle) {
  1452. var ls_display = 'display: block; ';
  1453. var ls_fontSize = 'font-size: 11px; ';
  1454. var ls_paddingRight = 'padding-right: 4px; ';
  1455. if(ib_capacityBarActive === true && is_capacityBarOrientation !== 'horizontalFull')
  1456. ls_fontSize = 'font-size: 9px; ';
  1457. if(is_incomeStyle == 'alignLeft')
  1458. ls_paddingRight = '';
  1459. return '.' + IC.myGM.prefix + 'hourlyIncomeResource { ' + ls_display + ls_fontSize + ls_paddingRight + '} ';
  1460. };
  1461. /**
  1462. * Get some resource styles which are only set if the capacity bar is active.
  1463. *
  1464. * @param {boolean} ib_directIncomeActive
  1465. * If the direct income is shown.
  1466. * @param {string} is_capacityBarOrientation
  1467. * The orientation of the capacity bar.
  1468. * @param {string} is_incomeStyle
  1469. * How the income is styled.
  1470. *
  1471. * @return {string}
  1472. * The style string.
  1473. */
  1474. var _lf_getResourceStyleCapacityActive = function(ib_directIncomeActive, is_capacityBarOrientation, is_incomeStyle) {
  1475. var ls_height = '';
  1476. var ls_top = '';
  1477. var ls_paddingLeft = '';
  1478. var ls_fontSize = '';
  1479. if(is_capacityBarOrientation == 'horizontalFull') {
  1480. ls_height = 'height: 32px !important; ';
  1481. ls_top = 'top: -2px !important; ';
  1482. }
  1483. if(is_capacityBarOrientation == 'vertical' && is_incomeStyle == 'alignLeft')
  1484. ls_paddingLeft = 'padding-left: 38px !important; ';
  1485. if(is_capacityBarOrientation == 'vertical' || (ib_directIncomeActive === true && is_capacityBarOrientation != 'horizontalFull'))
  1486. ls_fontSize = 'font-size: 11px; ';
  1487. return ls_height + ls_top + ls_paddingLeft + ls_fontSize;
  1488. };
  1489. /**
  1490. * Get the line height for the sored resources.
  1491. *
  1492. * @param {boolean} ib_capacityBarActive
  1493. * If the capacity bar is shown.
  1494. * @param {boolean} ib_directIncomeActive
  1495. * If the direct income is shown.
  1496. * @param {string} is_capacityBarOrientation
  1497. * The orientation of the capacity bar.
  1498. *
  1499. * @return {string}
  1500. * The style string.
  1501. */
  1502. var _lf_getResourceStyleLineHeigth = function(ib_capacityBarActive, ib_directIncomeActive, is_capacityBarOrientation) {
  1503. if(ib_directIncomeActive === true) {
  1504. if(ib_capacityBarActive === true && is_capacityBarOrientation == 'horizontal')
  1505. return 'line-height: 9px !important; ';
  1506. return 'line-height: 11px !important; ';
  1507. }
  1508. if(is_capacityBarOrientation == 'horizontal')
  1509. return 'line-height: 12px !important; ';
  1510. if(is_capacityBarOrientation == 'vertical')
  1511. return 'line-height: 24px !important; ';
  1512. return '';
  1513. };
  1514. /**
  1515. * Get the style for the resource fields.
  1516. *
  1517. * @param {boolean} ib_capacityBarActive
  1518. * If the capacity bar is shown.
  1519. * @param {boolean} ib_directIncomeActive
  1520. * If the direct income is shown.
  1521. * @param {string} is_capacityBarOrientation
  1522. * The orientation of the capacity bar.
  1523. * @param {string} is_incomeStyle
  1524. * How the income is styled.
  1525. *
  1526. * @return {string}
  1527. * The style string.
  1528. */
  1529. var _lf_getResourceStyle = function(ib_capacityBarActive, ib_directIncomeActive, is_capacityBarOrientation, is_incomeStyle) {
  1530. var ls_align = 'text-align: right; ';
  1531. var ls_capacityActive = '';
  1532. var ls_lineHeight = _lf_getResourceStyleLineHeigth(ib_capacityBarActive, ib_directIncomeActive, is_capacityBarOrientation);
  1533. if(is_incomeStyle == 'alignLeft')
  1534. ls_align = '';
  1535. if(ib_capacityBarActive === true)
  1536. ls_capacityActive = _lf_getResourceStyleCapacityActive(ib_directIncomeActive, is_capacityBarOrientation, is_incomeStyle);
  1537. return '#resources_wood, #resources_wine, #resources_marble, #resources_glass, #resources_sulfur { ' + ls_align + ls_lineHeight + ls_capacityActive + ' } ';
  1538. };
  1539. /**
  1540. * Set the styles for the direct income and the capacity bar.
  1541. */
  1542. this.setStyles = function() {
  1543. var lb_capacityBarActive = IC.Options.getOption('resourceInformation', 'showCapacityBar');
  1544. var lb_directIncomeActive = IC.Options.getOption('resourceInformation', 'showDirectIncome');
  1545. // If not both of the checkboxes have been defined yet, do nothing!
  1546. if(lb_capacityBarActive === null || lb_directIncomeActive === null)
  1547. return;
  1548. if(lb_capacityBarActive === false && lb_directIncomeActive === false) {
  1549. IC.myGM.removeStyle('resourceInformation');
  1550. return;
  1551. }
  1552. var ls_capacityBarOrientation = IC.Options.getOption('resourceInformation', 'capacityBarOrientation');
  1553. var ls_incomeStyle = IC.Options.getOption('resourceInformation', 'incomeStyle');
  1554. var ls_incomeStyleString = _lf_getGeneralStyles(ls_incomeStyle)
  1555. + _lf_getResourceStyle(lb_capacityBarActive, lb_directIncomeActive, ls_capacityBarOrientation, ls_incomeStyle);
  1556. if(lb_capacityBarActive === true)
  1557. ls_incomeStyleString += _lf_getCapacityStyle(ls_capacityBarOrientation, ls_incomeStyle);
  1558. if(lb_directIncomeActive === true)
  1559. ls_incomeStyleString += _lf_getHourlyIncomeStyle(lb_capacityBarActive, ls_capacityBarOrientation, ls_incomeStyle);
  1560. IC.myGM.addStyle(ls_incomeStyleString, 'resourceInformation', true);
  1561. };
  1562. };
  1563. /**
  1564. * Storage for the functions for the capacity bar.
  1565. *
  1566. * @type {object}
  1567. */
  1568. var _go_capacityInformation = new function() {
  1569. /**
  1570. * Update the capacity information bars.
  1571. */
  1572. var _lf_updateFields = function() {
  1573. if(IC.ika.model.isOwnCity === false)
  1574. return;
  1575. var la_capacityInformation = [];
  1576. var la_resourceIdentifiers = ['resource', 1, 2, 3, 4];
  1577. la_resourceIdentifiers.forEach(function(im_identifier, ii_index) {
  1578. la_capacityInformation.push({
  1579. warehouse: IC.Ikariam.getInt(IC.ika.getModel().maxResources[im_identifier]),
  1580. branchOffice: IC.Ikariam.getInt(IC.ika.getModel().branchOfficeResources[im_identifier]),
  1581. current: IC.Ikariam.getInt(IC.ika.getModel().currentResources[im_identifier])
  1582. });
  1583. });
  1584. var ls_prefix = '#' + IC.myGM.prefix;
  1585. var ls_styleToChange = 'width';
  1586. if(IC.Options.getOption('resourceInformation', 'capacityBarOrientation') == 'vertical')
  1587. ls_styleToChange = 'height';
  1588. la_capacityInformation.forEach(function(io_capacity, ii_index) {
  1589. var ls_resource = IC.Ikariam.resourceNames[ii_index];
  1590. var li_warehousePercentage = 100;
  1591. var li_resourcePercentage = io_capacity.current / io_capacity.warehouse * 100;
  1592. if(IC.Options.getOption('resourceInformation', 'capacityBarShowBranchOfficeResources') === true) {
  1593. var li_maximumCapacity = io_capacity.warehouse + io_capacity.branchOffice;
  1594. li_warehousePercentage = io_capacity.warehouse / li_maximumCapacity * 100;
  1595. li_resourcePercentage = io_capacity.current / li_maximumCapacity * 100;
  1596. }
  1597. IC.myGM.$(ls_prefix + 'maxCapacity' + ls_resource).style[ls_styleToChange] = '100%';
  1598. IC.myGM.$(ls_prefix + 'warehouseCapacity' + ls_resource).style[ls_styleToChange] = li_warehousePercentage + '%';
  1599. IC.myGM.$(ls_prefix + 'currentResource' + ls_resource).style[ls_styleToChange] = li_resourcePercentage + '%';
  1600. });
  1601. };
  1602. /**
  1603. * Add the capacity information bars.
  1604. */
  1605. var _lf_addFields = function() {
  1606. var la_classes = ['capacityInformation'];
  1607. if(IC.Options.getOption('resourceInformation', 'capacityBarHasBorder') === true)
  1608. la_classes.push('border');
  1609. IC.Ikariam.resourceNames.forEach(function(is_resource) {
  1610. var le_wrapper = IC.myGM.addElement('div', IC.myGM.$('#resources_' + is_resource), { 'id': 'capacityInfo' + is_resource, 'classes': la_classes }, true);
  1611. IC.myGM.addElement('div', le_wrapper, { 'id': 'maxCapacity' + is_resource, 'classes': ['bar', 'yellow'] }, true);
  1612. IC.myGM.addElement('div', le_wrapper, { 'id': 'warehouseCapacity' + is_resource, 'classes': ['bar', 'green'] }, true);
  1613. IC.myGM.addElement('div', le_wrapper, { 'id': 'currentResource' + is_resource, 'classes': ['bar', 'red'] }, true);
  1614. });
  1615. _lf_updateFields();
  1616. };
  1617. /**
  1618. * Remove the capacity information bars.
  1619. */
  1620. var _lf_removeFields = function() {
  1621. IC.myGM.removeElement(IC.myGM.$$('.' + IC.myGM.prefix + 'capacityInformation'));
  1622. };
  1623. /**
  1624. * Update the settings to execute the callback or delete the handler.
  1625. *
  1626. * @param {boolean} ib_showCapacityBar
  1627. * If the user selected the checkbox to show the capacity information.
  1628. */
  1629. this.updateSettings = function(ib_showCapacityBar) {
  1630. _go_styleFunctions.setStyles();
  1631. if(ib_showCapacityBar === true) {
  1632. _lf_addFields();
  1633. IC.Observer.add('updateCapacityBar', IC.myGM.$('#cityResources'), { childList: true, subtree: true }, _lf_updateFields, _lf_updateFields);
  1634. return;
  1635. }
  1636. IC.Observer.remove('updateCapacityBar');
  1637. _lf_removeFields();
  1638. };
  1639. };
  1640. /**
  1641. * Storage for the functions for the direct income.
  1642. *
  1643. * @type {object}
  1644. */
  1645. var _go_directIncome = new function() {
  1646. /**
  1647. * Storage for the tradegood of the last town selected.
  1648. *
  1649. * @type {int}
  1650. */
  1651. var _li_lastTradegood = null;
  1652. /**
  1653. * Delete the data of the tradegood of the last town selected.
  1654. *
  1655. * @param {string} is_hourlyPrefix
  1656. * The prefix for the hourly income wrapper selector.
  1657. * @param {string} is_dailyPrefix
  1658. * The prefix for the daily income wrapper selector.
  1659. */
  1660. var _lf_deleteLastTradegoodData = function(is_hourlyPrefix, is_dailyPrefix) {
  1661. IC.myGM.$(is_hourlyPrefix + IC.Ikariam.resourceNames[_li_lastTradegood]).innerHTML = '';
  1662. IC.myGM.$(is_dailyPrefix + IC.Ikariam.resourceNames[_li_lastTradegood]).innerHTML = '';
  1663. if(_li_lastTradegood !== 1) {
  1664. IC.myGM.$(is_hourlyPrefix + IC.Ikariam.resourceNames[_li_lastTradegood]).classList.add('invisible');
  1665. IC.myGM.$(is_dailyPrefix + 'Wrapper' + IC.Ikariam.resourceNames[_li_lastTradegood]).classList.add('invisible');
  1666. }
  1667. };
  1668. /**
  1669. * Update the direct icome fields.
  1670. *
  1671. * @param {boolean} ib_firstRun
  1672. * If this is the first run after adding the fields.
  1673. */
  1674. var _lf_updateFields = function(ib_firstRun) {
  1675. if(IC.ika.model.isOwnCity === false)
  1676. return;
  1677. var ls_hourlyPrefix = '#' + IC.myGM.prefix + 'hourlyIncomeResource';
  1678. var ls_dailyPrefix = '#' + IC.myGM.prefix + 'dailyIncomeResource';
  1679. if(_li_lastTradegood !== null)
  1680. _lf_deleteLastTradegoodData(ls_hourlyPrefix, ls_dailyPrefix);
  1681. var li_producedTradegood = IC.Ikariam.getInt(IC.ika.getModel().producedTradegood);
  1682. var li_tradegoodProduction = IC.ika.getModel().tradegoodProduction * 3600 + 0.001;
  1683. var li_woodProduction = IC.ika.getModel().resourceProduction * 3600 + 0.001;
  1684. var li_wineSpending = IC.ika.getModel().wineSpendings;
  1685. var li_producesWine = IC.ika.getModel().cityProducesWine;
  1686. var ls_tradegoodName = IC.Ikariam.resourceNames[li_producedTradegood];
  1687. IC.myGM.$(ls_hourlyPrefix + IC.Ikariam.resourceNames[0]).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(li_woodProduction), true, true);
  1688. IC.myGM.$(ls_dailyPrefix + IC.Ikariam.resourceNames[0]).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(li_woodProduction * 24), false);
  1689. IC.myGM.$(ls_hourlyPrefix + IC.Ikariam.resourceNames[1]).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(-1 * li_wineSpending), true, true);
  1690. IC.myGM.$(ls_dailyPrefix + IC.Ikariam.resourceNames[1]).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(-1 * li_wineSpending * 24), false);
  1691. if(li_producesWine === true)
  1692. li_tradegoodProduction = li_tradegoodProduction - li_wineSpending;
  1693. IC.myGM.$(ls_hourlyPrefix + ls_tradegoodName).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(li_tradegoodProduction), true, true);
  1694. IC.myGM.$(ls_dailyPrefix + ls_tradegoodName).innerHTML = IC.Ikariam.formatToIkaNumber(Math.floor(li_tradegoodProduction * 24), false);
  1695. IC.myGM.$(ls_hourlyPrefix + ls_tradegoodName).classList.remove('invisible');
  1696. IC.myGM.$(ls_dailyPrefix + 'Wrapper' + ls_tradegoodName).classList.remove('invisible');
  1697. _li_lastTradegood = li_producedTradegood;
  1698. };
  1699. /**
  1700. * Add the direct income fields.
  1701. */
  1702. var _lf_addFields = function() {
  1703. IC.Ikariam.resourceNames.forEach(function(is_resource, ii_index) {
  1704. var la_hourlyClasses = [IC.myGM.prefix + 'hourlyIncomeResource'];
  1705. var la_dailyClasses = ['smallFont', IC.myGM.prefix + 'dailyIncomeResourceWrapper'];
  1706. if(ii_index >= 2) {
  1707. la_hourlyClasses.push('invisible');
  1708. la_dailyClasses.push('invisible');
  1709. }
  1710. IC.myGM.addElement('span', IC.myGM.$('#resources_' + is_resource), { 'id': 'hourlyIncomeResource' + is_resource, 'classes': la_hourlyClasses });
  1711. var le_dailyIncomeParent = IC.myGM.$('#resources_' + is_resource + ' .tooltip');
  1712. var le_dailyIncomeWrapper = IC.myGM.addElement('p', le_dailyIncomeParent, {
  1713. 'id': 'dailyIncomeResourceWrapper' + is_resource,
  1714. 'classes': la_dailyClasses,
  1715. 'innerHTML': IC.Language.$('resourceInformation.dailyProduction', [IC.Language.$('diverse.name.resource.' + is_resource)]) + ' '
  1716. }, null, IC.myGM.$('p:nth-child(2)', le_dailyIncomeParent));
  1717. IC.myGM.addElement('span', le_dailyIncomeWrapper, { 'id': 'dailyIncomeResource' + is_resource });
  1718. });
  1719. _lf_updateFields(true);
  1720. };
  1721. /**
  1722. * Remove the direct income fields.
  1723. */
  1724. var _lf_removeFields = function() {
  1725. IC.myGM.removeElement(IC.myGM.$$('.' + IC.myGM.prefix + 'hourlyIncomeResource' + ', .' + IC.myGM.prefix + 'dailyIncomeResourceWrapper'));
  1726. };
  1727. /**
  1728. * Update the settings to execute the callback or delete the handler.
  1729. *
  1730. * @param {boolean} ib_showDirectIncome
  1731. * If the user selected the checkbox to show the income directly in town view.
  1732. */
  1733. this.updateSettings = function(ib_showDirectIncome) {
  1734. _go_styleFunctions.setStyles();
  1735. if(ib_showDirectIncome === true) {
  1736. _lf_addFields();
  1737. IC.RefreshHandler.add('*', 'directIncome', _lf_updateFields);
  1738. return;
  1739. }
  1740. IC.RefreshHandler.remove('*', 'directIncome');
  1741. _lf_removeFields();
  1742. };
  1743. };
  1744. /**
  1745. * Storage for the functions for the resource quicklinks enhancements.
  1746. *
  1747. * @type {object}
  1748. */
  1749. var _go_resourceQuicklinkEnhancements = new function() {
  1750. /**
  1751. * Open the town hall of the selected town.
  1752. */
  1753. var _lf_openTownHall = function() {
  1754. var ls_selectedCity = IC.ika.getModel().relatedCityData.selectedCity;
  1755. var ls_cityId = IC.ika.getModel().relatedCityData[ls_selectedCity].id;
  1756. if(IC.Ikariam.view == 'town') {
  1757. IC.win.ajaxHandlerCall('?view=townHall&cityId=' + ls_cityId + '&position=0');
  1758. return;
  1759. }
  1760. IC.win.ajaxHandlerCall('?view=city&dialog=townHall&cityId=' + ls_cityId + '&position=0');
  1761. };
  1762. /**
  1763. * Update the css to hover only the resources which are clickable.
  1764. */
  1765. var _lf_updateCSS = function() {
  1766. var ls_activeResource = IC.Ikariam.resourceNames[IC.ika.getModel().producedTradegood];
  1767. IC.myGM.addStyle(
  1768. '#resources_population:hover, #resources_wood:hover, #resources_' + ls_activeResource + ':hover { text-shadow: 2px 2px 2px #666; cursor: pointer; color: #333; }',
  1769. 'resourceQuicklinkEnhancements', true
  1770. );
  1771. };
  1772. /**
  1773. * Update the settings to execute the callback or delete the handler.
  1774. *
  1775. * @param {boolean} ib_enhanceResourceQuicklinks
  1776. * If the user selected the checkbox to enhance the resource quicklinks.
  1777. */
  1778. this.updateSettings = function(ib_enhanceResourceQuicklinks) {
  1779. if(ib_enhanceResourceQuicklinks === true) {
  1780. IC.myGM.$('#resources_population').addEventListener('click', _lf_openTownHall, true);
  1781. IC.RefreshHandler.add('*', 'resourceQuicklinkEnhancements', _lf_updateCSS);
  1782. return;
  1783. }
  1784. IC.RefreshHandler.remove('*', 'resourceQuicklinkEnhancements');
  1785. IC.myGM.$('#resources_population').removeEventListener('click', _lf_openTownHall, true);
  1786. IC.myGM.removeStyle('resourceQuicklinkEnhancements');
  1787. };
  1788. };
  1789. IC.Options.addWrapper('resourceInformation', IC.Language.$('resourceInformation.options.wrapperTitle'));
  1790. // Option to show the income directly in town view.
  1791. IC.Options.addCheckbox('showDirectIncome', 'resourceInformation', 1, true, IC.Language.$('resourceInformation.options.directIncome.show'), { changeCallback: _go_directIncome.updateSettings });
  1792. // Option to enhance the resource quicklinks and add one to population.
  1793. IC.Options.addCheckbox('resourceQuicklinkEnhancements', 'resourceInformation', 1, true, IC.Language.$('resourceInformation.options.resourceQuicklinkEnhancements'), { changeCallback: _go_resourceQuicklinkEnhancements.updateSettings });
  1794. // Option to show the capacity information.
  1795. IC.Options.addCheckbox('showCapacityBar', 'resourceInformation', 2, true, IC.Language.$('resourceInformation.options.capacityBar.show'), { changeCallback: _go_capacityInformation.updateSettings });
  1796. // Option to show the capacity bar with border.
  1797. IC.Options.addCheckbox('capacityBarHasBorder', 'resourceInformation', 2, true, IC.Language.$('resourceInformation.options.capacityBar.hasBorder'), {});
  1798. // Option to show also branch office ressources.
  1799. IC.Options.addCheckbox('capacityBarShowBranchOfficeResources', 'resourceInformation', 2, true, IC.Language.$('resourceInformation.options.capacityBar.showBranchOfficeResources'), {});
  1800. // Style of the resources in warehouse / daily income.
  1801. IC.Options.addSelect('incomeStyle', 'resourceInformation', 3, 'alignRight', IC.Language.$('resourceInformation.options.directIncome.style.label'), [
  1802. { value: 'alignRight', label: IC.Language.$('resourceInformation.options.directIncome.style.alignRight') },
  1803. { value: 'alignLeft', label: IC.Language.$('resourceInformation.options.directIncome.style.alignLeft') },
  1804. { value: 'withSeparation', label: IC.Language.$('resourceInformation.options.directIncome.style.withSeparation') }
  1805. ], {});
  1806. // Style of the capacity bar.
  1807. IC.Options.addSelect('capacityBarOrientation', 'resourceInformation', 3, 'vertical', IC.Language.$('resourceInformation.options.capacityBar.orientation.label'), [
  1808. { value: 'vertical', label: IC.Language.$('resourceInformation.options.capacityBar.orientation.vertical') },
  1809. { value: 'horizontal', label: IC.Language.$('resourceInformation.options.capacityBar.orientation.horizontal') },
  1810. { value: 'horizontalFull', label: IC.Language.$('resourceInformation.options.capacityBar.orientation.horizontalFull') }
  1811. ], {});
  1812. })();
  1813. IC.con.timeStamp('IkariamEnhancedUI: resource information functions created');
  1814. // Member information in highscore view.
  1815. (function() {
  1816. /**
  1817. * Storage for the member information functions.
  1818. *
  1819. * @type {object}
  1820. */
  1821. var _go_memberInformation = new function() {
  1822. /**
  1823. * Storage for the member data.
  1824. *
  1825. * @type {object}
  1826. */
  1827. var _lo_data = null;
  1828. /**
  1829. * Key for the storage of the member information.
  1830. *
  1831. * @type {string}
  1832. */
  1833. var _ls_dataKey = '';
  1834. /**
  1835. * Key for the storage of the last reset date.
  1836. *
  1837. * @type {string}
  1838. */
  1839. var _ls_timeKey = '';
  1840. /**
  1841. * Show the data.
  1842. */
  1843. var _lf_clickShow = function() {
  1844. IC.myGM.setValue('memberInfo_infoLinkClicked', true);
  1845. IC.myGM.$('#tab_highscore input[name="searchUser"]').value = '';
  1846. IC.myGM.$('#searchOnlyFriends').checked = false;
  1847. IC.myGM.$('#searchOnlyAllies').checked = true;
  1848. IC.myGM.$('#tab_highscore input[type="submit"]').click();
  1849. };
  1850. /**
  1851. * Reset the stored data.
  1852. */
  1853. var _lf_clickReset = function() {
  1854. IC.myGM.setValue(_ls_dataKey, _lo_data);
  1855. IC.myGM.setValue(_ls_timeKey, (new Date).getTime());
  1856. _lf_clickShow();
  1857. };
  1858. /**
  1859. * Add the button to show the data.
  1860. */
  1861. var _lf_addShowButton = function() {
  1862. var le_button = IC.myGM.addButton(IC.myGM.$('#tab_highscore .centerButton'), IC.Language.$('highscore.memberInformation.show'), _lf_clickShow, true);
  1863. le_button.id = IC.myGM.prefix + 'showInfo';
  1864. };
  1865. /**
  1866. * Add the button to resset the stored data.
  1867. */
  1868. var _lf_addResetButton = function() {
  1869. var le_button = IC.myGM.addButton(IC.myGM.$('#tab_highscore .content p'), IC.Language.$('highscore.memberInformation.reset'), _lf_clickReset, true);
  1870. le_button.id = IC.myGM.prefix + 'resetInfo';
  1871. };
  1872. /**
  1873. * Get the own data and show the differences to the last stored data.
  1874. *
  1875. * @param {object} io_oldMemberInfo
  1876. * The last stored data.
  1877. *
  1878. * @return {object}
  1879. * The own data.
  1880. */
  1881. var _lf_getOwnDataShowDifference = function(io_oldMemberInfo) {
  1882. var le_ownRow = IC.myGM.$('table.highscore tr.own');
  1883. var ro_ownData = {
  1884. 'place': IC.Ikariam.getInt(IC.myGM.$('.place', le_ownRow).innerHTML),
  1885. 'score': IC.Ikariam.getInt(IC.myGM.$('.score', le_ownRow).innerHTML)
  1886. };
  1887. var ls_placeDifference = '-';
  1888. var ls_scoreDifference = '-';
  1889. if(!!io_oldMemberInfo === true && !!io_oldMemberInfo['own'] === true) {
  1890. ls_placeDifference = IC.Ikariam.formatToIkaNumber(io_oldMemberInfo['own']['place'] - ro_ownData['place'], true, true);
  1891. ls_scoreDifference = IC.Ikariam.formatToIkaNumber(ro_ownData['score'] - io_oldMemberInfo['own']['score'], true, true);
  1892. }
  1893. IC.myGM.addElement('span', IC.myGM.$('.place', le_ownRow), { 'innerHTML': ls_placeDifference });
  1894. IC.myGM.addElement('span', IC.myGM.$('.score', le_ownRow), { 'innerHTML': ls_scoreDifference });
  1895. return ro_ownData;
  1896. };
  1897. /**
  1898. * Get the data and show the differences to the last stored data.
  1899. *
  1900. * @return {object}
  1901. * The member data.
  1902. */
  1903. var _lf_getDataShowDifference = function() {
  1904. var ro_memberInfo = {};
  1905. var lo_oldMemberInfo = IC.myGM.getValue(_ls_dataKey, null);
  1906. var la_allyMemberRows = IC.myGM.$$('table.highscore tr.ownally');
  1907. la_allyMemberRows.forEach(function(ie_allyMemberRow) {
  1908. var ls_actionLink = IC.myGM.$('.action a', ie_allyMemberRow).href;
  1909. var ls_memberId = ls_actionLink.match(/receiverId=([0-9]*)/i)[1];
  1910. ro_memberInfo[ls_memberId] = {
  1911. 'place': IC.Ikariam.getInt(IC.myGM.$('.place', ie_allyMemberRow).innerHTML),
  1912. 'score': IC.Ikariam.getInt(IC.myGM.$('.score', ie_allyMemberRow).innerHTML)
  1913. };
  1914. var ls_placeDifference = '-';
  1915. var ls_scoreDifference = '-';
  1916. if(!!lo_oldMemberInfo === true && !!lo_oldMemberInfo[ls_memberId] === true) {
  1917. ls_placeDifference = IC.Ikariam.formatToIkaNumber(lo_oldMemberInfo[ls_memberId]['place'] - ro_memberInfo[ls_memberId]['place'], true, true);
  1918. ls_scoreDifference = IC.Ikariam.formatToIkaNumber(ro_memberInfo[ls_memberId]['score'] - lo_oldMemberInfo[ls_memberId]['score'], true, true);
  1919. }
  1920. IC.myGM.addElement('span', IC.myGM.$('.place', ie_allyMemberRow), { 'innerHTML': ls_placeDifference });
  1921. IC.myGM.addElement('span', IC.myGM.$('.score', ie_allyMemberRow), { 'innerHTML': ls_scoreDifference });
  1922. });
  1923. ro_memberInfo['own'] = _lf_getOwnDataShowDifference(lo_oldMemberInfo);
  1924. return ro_memberInfo;
  1925. };
  1926. /**
  1927. * Add the span with the time of the last reset.
  1928. */
  1929. var _lf_addLastResetTime = function() {
  1930. var li_lastResetTime = IC.myGM.getValue(_ls_timeKey, 0);
  1931. var li_differenceInSec = ((new Date()).getTime() - li_lastResetTime) / 1000;
  1932. var ls_lastReset = IC.Language.$('highscore.memberInformation.noReset');
  1933. if(li_lastResetTime > 0) {
  1934. var li_days = Math.floor(li_differenceInSec / 86400);
  1935. var li_hours = Math.floor(li_differenceInSec / 3600);
  1936. var li_minutes = Math.floor(li_differenceInSec / 60);
  1937. ls_lastReset = li_days + 'd ' + li_hours + 'h ' + li_minutes + 'min';
  1938. }
  1939. IC.myGM.addElement('span', IC.myGM.$('#tab_highscore .content p'), {
  1940. 'classes': ['bold', 'brown'],
  1941. 'innerHTML': IC.Language.$('highscore.memberInformation.lastReset', [ls_lastReset])
  1942. });
  1943. };
  1944. /**
  1945. * Prepare the highscore popup to show the data and show the data if requested.
  1946. */
  1947. var _lf_doPreparePopup = function() {
  1948. _ls_dataKey = IC.Ikariam.getServerCode + '_memberInfo_data_' + IC.myGM.getSelectValue('js_highscoreType', true, true);
  1949. _ls_timeKey = IC.Ikariam.getServerCode + '_memberInfo_time_' + IC.myGM.getSelectValue('js_highscoreType', true, true);
  1950. _lf_addShowButton();
  1951. if(IC.myGM.getValue('memberInfo_infoLinkClicked', false) === true) {
  1952. IC.myGM.deleteValue('memberInfo_infoLinkClicked');
  1953. _lo_data = _lf_getDataShowDifference();
  1954. _lf_addResetButton();
  1955. _lf_addLastResetTime();
  1956. }
  1957. };
  1958. /**
  1959. * Update the settings to execute the callback or delete the handler.
  1960. *
  1961. * @param {boolean} ib_showMemberInformation
  1962. * If the user selected the checkbox to show the member information.
  1963. */
  1964. this.updateSettings = function(ib_showMemberInformation) {
  1965. if(ib_showMemberInformation === true) {
  1966. IC.RefreshHandler.add('highscore', 'memberInformation', _lf_doPreparePopup);
  1967. IC.myGM.addStyle(
  1968. '#' + IC.myGM.prefix + "resetInfo { float: right; margin-top: -6px; margin-right: 6px; } \
  1969. .highscore .score span { float: right; text-align: right; width: 70px; } \
  1970. .highscore .place span { float: right; text-align: right; width: 30px; } \
  1971. .highscore th:nth-child(4) { width: 30% !important; } \
  1972. .highscore th:nth-child(5) { width: 10% !important; } \
  1973. #tab_highscore .centerButton { margin: 10px 0px; }",
  1974. 'memberInformation', true
  1975. );
  1976. return;
  1977. }
  1978. IC.RefreshHandler.remove('highscore', 'memberInformation');
  1979. IC.myGM.removeStyle('memberInformation');
  1980. };
  1981. };
  1982. // Show the member information.
  1983. IC.Options.addCheckbox('showMemberInformation', 'diverseOptions', 1, false, IC.Language.$('highscore.options.showMemberInformation'), { changeCallback: _go_memberInformation.updateSettings });
  1984. })();
  1985. IC.con.timeStamp('IkariamEnhancedUI: highscore functions created');
  1986. // Message enhancements.
  1987. (function() {
  1988. /**
  1989. * Storage for the url replacement functions.
  1990. *
  1991. * @type {object}
  1992. */
  1993. var _go_replaceURL = new function() {
  1994. /**
  1995. * Show a warning when a replaced link is clicked.
  1996. */
  1997. var _lf_showNotification = function() {
  1998. var ls_urlToOpen = this.innerHTML.IC.decodeHTML();
  1999. var lo_notificationText = {
  2000. header: IC.Language.$('message.replacedUrl.notification.header'),
  2001. body: IC.Language.$('message.replacedUrl.notification.text', ['<span class="bold red">"' + ls_urlToOpen + '"</span>']),
  2002. confirm: IC.Language.$('general.yes'),
  2003. abort: IC.Language.$('general.no')
  2004. };
  2005. var lo_notificationCallback = {
  2006. confirm: function() { IC.win.open(ls_urlToOpen); },
  2007. abort: function() { /* Only set to show the abort button */ }
  2008. };
  2009. IC.myGM.notification(lo_notificationText, lo_notificationCallback);
  2010. };
  2011. /**
  2012. * Replace the links.
  2013. */
  2014. var _lf_doReplace = function() {
  2015. var la_messageBodys = IC.myGM.$$('.msgText');
  2016. la_messageBodys.forEach(function(ie_messageBody) {
  2017. var ls_text = ie_messageBody.innerHTML;
  2018. ie_messageBody.innerHTML = ls_text.replace(/(?:^|\s)(http(s?)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,4}(\/[^<\s]*)?)/g, ' <span class="' + IC.myGM.prefix + 'replacedUrl" title="$1">$1</span> ');
  2019. });
  2020. var la_replacedURLs = IC.myGM.$$('.' + IC.myGM.prefix + 'replacedUrl');
  2021. la_replacedURLs.forEach(function(ie_replacedURL) {
  2022. ie_replacedURL.addEventListener('click', _lf_showNotification, true);
  2023. });
  2024. };
  2025. /**
  2026. * Update the settings to execute the callback or delete the handler.
  2027. *
  2028. * @param {boolean} ib_replaceURL
  2029. * If the user selected the checkbox to replace the url.
  2030. */
  2031. this.updateSettings = function(ib_replaceURL) {
  2032. var la_postboxes = ['diplomacyAdvisor', 'diplomacyAdvisorOutBox', 'diplomacyAdvisorArchive', 'diplomacyAdvisorArchiveOutBox'];
  2033. if(ib_replaceURL === true) {
  2034. IC.RefreshHandler.add(la_postboxes, 'replaceURL', _lf_doReplace);
  2035. IC.myGM.addStyle(
  2036. '.' + IC.myGM.prefix + 'replacedUrl { font-weight: bold; font-style: italic; } \
  2037. .' + IC.myGM.prefix + 'replacedUrl:hover { text-decoration: underline; cursor: pointer; }',
  2038. 'replaceURL', true
  2039. );
  2040. return;
  2041. }
  2042. IC.RefreshHandler.remove(la_postboxes, 'replaceURL');
  2043. IC.myGM.removeStyle('replaceURL');
  2044. };
  2045. };
  2046. /**
  2047. * Storage for the message signature functions.
  2048. *
  2049. * @type {object}
  2050. */
  2051. var _go_messageSignature = new function() {
  2052. /**
  2053. * Add the signature to a new message.
  2054. */
  2055. var _lf_addSignature = function() {
  2056. var ls_signature = IC.Options.getOption('messages', 'globalSignature');
  2057. if(IC.Options.getOption('messages', 'useServerSignature') === true)
  2058. ls_signature = IC.Options.getOption('messages', 'serverSignature');
  2059. if(ls_signature === '')
  2060. return;
  2061. var le_textarea = IC.myGM.$('#js_msgTextConfirm');
  2062. var ls_text = le_textarea.value;
  2063. if(IC.Options.getOption('messages', 'placementTop'))
  2064. ls_text = '\n\n' + ls_signature + ls_text;
  2065. else
  2066. ls_text = ls_text + '\n\n' + ls_signature;
  2067. le_textarea.value = ls_text;
  2068. le_textarea.setSelectionRange(0,0);
  2069. le_textarea.focus();
  2070. };
  2071. /**
  2072. * Update the settings to execute the callback or delete the handler.
  2073. *
  2074. * @param {boolean} ib_addMessageSignature
  2075. * If the user selected the checkbox to add signatures to messages.
  2076. */
  2077. this.updateSettings = function(ib_addMessageSignature) {
  2078. if(ib_addMessageSignature === true) {
  2079. IC.RefreshHandler.add('sendIKMessage', 'addMessageSignature', _lf_addSignature);
  2080. return;
  2081. }
  2082. IC.RefreshHandler.remove('sendIKMessage', 'addMessageSignature');
  2083. };
  2084. };
  2085. /**
  2086. * Storage for the easy circular message link functions.
  2087. *
  2088. * @type {object}
  2089. */
  2090. var _go_easyCircularMessageLink = new function() {
  2091. /**
  2092. * Add the circular message link and style.
  2093. */
  2094. var _lf_addLink = function() {
  2095. if(IC.ika.getModel().hasAlly !== true)
  2096. return;
  2097. // Add the message link (workaround for ajaxHandlerCall).
  2098. var ls_id = IC.myGM.prefix + 'circularMessageLink';
  2099. var ls_href = '?view=sendIKMessage&msgType=51&allyId=' + IC.ika.getModel().avatarAllyId;
  2100. var ls_title = IC.Language.$('message.easyCircular.send');
  2101. IC.myGM.addElement('div', ge_toolbar, {
  2102. 'id': 'circularMessageLinkWrapper',
  2103. 'innerHTML': '<a id="' + ls_id + '" href="' + ls_href + '" title="' + ls_title + '" onclick="ajaxHandlerCall(this.href); return false;"></a>'
  2104. });
  2105. IC.myGM.addStyle(
  2106. '#' + IC.myGM.prefix + 'circularMessageLink { height: 9px; width: 13px; margin: 0px !important; background: url("skin/interface/icon_send_message.png") repeat scroll 0 0 transparent; }\
  2107. #' + IC.myGM.prefix + 'circularMessageLink:hover { background-position: 0px -9px; }',
  2108. 'easyCircularMessage', true
  2109. );
  2110. };
  2111. /**
  2112. * Remove the circular message link and style.
  2113. */
  2114. var _lf_removeLink = function() {
  2115. IC.myGM.removeElement(IC.myGM.$('#' + IC.myGM.prefix + 'circularMessageLinkWrapper'));
  2116. IC.myGM.removeStyle('easyCircularMessage');
  2117. };
  2118. /**
  2119. * Update the settings to execute the callback or delete the handler.
  2120. *
  2121. * @param {boolean} ib_addEasyCircularMessageLink
  2122. * If the user selected the checkbox to add signatures to messages.
  2123. */
  2124. this.updateSettings = function(ib_addEasyCircularMessageLink) {
  2125. if(ib_addEasyCircularMessageLink === true) {
  2126. _lf_addLink();
  2127. return;
  2128. }
  2129. _lf_removeLink();
  2130. };
  2131. };
  2132. IC.Options.addWrapper('messages', IC.Language.$('messages.options.wrapperTitle'));
  2133. // Replace urls.
  2134. IC.Options.addCheckbox('replaceURL', 'messages', 1, true, IC.Language.$('message.options.replaceURL'), { changeCallback: _go_replaceURL.updateSettings });
  2135. // Provide link for easy circular messages.
  2136. IC.Options.addCheckbox('easyCircularMessage', 'messages', 1, true, IC.Language.$('message.options.easyCircularMessage'), { changeCallback: _go_easyCircularMessageLink.updateSettings });
  2137. // Add a signature.
  2138. IC.Options.addCheckbox('messageSignature', 'messages', 2, true, IC.Language.$('message.options.signature.use'), { changeCallback: _go_messageSignature.updateSettings });
  2139. // Place the signature on top.
  2140. IC.Options.addCheckbox('signaturePlacementTop', 'messages', 2, true, IC.Language.$('message.options.signature.placementTop'), {});
  2141. // Define a global signature.
  2142. IC.Options.addTextArea('globalSignature', 'messages', 3, '', IC.Language.$('message.options.signature.global'), {});
  2143. // Use the server signature.
  2144. IC.Options.addCheckbox('useServerSignature', 'messages', 4, false, IC.Language.$('message.options.signature.useServerSpecific'), { 'serverSpecific': true });
  2145. // Define a server specific signature.
  2146. IC.Options.addTextArea('serverSignature', 'messages', 4, '', IC.Language.$('message.options.signature.server'), { 'serverSpecific': true });
  2147. })();
  2148. IC.con.timeStamp('IkariamEnhancedUI: message functions created');
  2149. // Troop information.
  2150. (function() {
  2151. /**
  2152. * Provider for data storages.
  2153. *
  2154. * @type {object}
  2155. */
  2156. var _go_storageProvider = new function() {
  2157. /**
  2158. * Constructor for troop list.
  2159. */
  2160. var _lf_troopList = function() {
  2161. /**
  2162. * Storage for troop information.
  2163. *
  2164. * @type {lf_troop[]}
  2165. */
  2166. var la_troopList = [];
  2167. /**
  2168. * Troop information storage.
  2169. *
  2170. * @param {string} is_name
  2171. * The name of the troop.
  2172. * @param {int} ii_number
  2173. * The number of the troop.
  2174. */
  2175. var lf_troop = function(is_name, ii_number) {
  2176. var ls_name = is_name;
  2177. var li_number = ii_number;
  2178. this.toString = function() {
  2179. return '\n' + ls_name + ': ' + li_number;
  2180. };
  2181. };
  2182. /**
  2183. * If the troop list contains no entries.
  2184. *
  2185. * @return {boolean}
  2186. * If the troop list is empty.
  2187. */
  2188. this.__defineGetter__('isEmpty', function() {
  2189. return la_troopList.length < 1;
  2190. });
  2191. /**
  2192. * Add a new troop to the troop list.
  2193. *
  2194. * @param {string} is_name
  2195. * The name of the troop.
  2196. * @param {int} ii_number
  2197. * The number of the troop.
  2198. */
  2199. this.addTroop = function(is_name, ii_number) {
  2200. la_troopList.push(new lf_troop(is_name, ii_number));
  2201. };
  2202. /**
  2203. * Transform the troop list to a string.
  2204. *
  2205. * @return {string}
  2206. * The string representation of the troop list.
  2207. */
  2208. this.toString = function() {
  2209. return la_troopList.join('');
  2210. };
  2211. };
  2212. /**
  2213. * Constructor for troop list of foreign player.
  2214. *
  2215. * @param {string} is_playerName
  2216. * The name of the player who owns the troops.
  2217. */
  2218. var _lf_foreignTroopList = function(is_playerName) {
  2219. /**
  2220. * The name of the player who owns the troops.
  2221. *
  2222. * @type {string}
  2223. */
  2224. var ls_playerName = is_playerName;
  2225. /**
  2226. * Storage for troop information.
  2227. *
  2228. * @type {_lf_troopList[]}
  2229. */
  2230. var lo_troopList = new _lf_troopList();
  2231. /**
  2232. * If the troop list contains no entries.
  2233. *
  2234. * @return {boolean}
  2235. * If the troop list is empty.
  2236. */
  2237. this.__defineGetter__('isEmpty', function() {
  2238. return lo_troopList.isEmpty;
  2239. });
  2240. /**
  2241. * Add a new troop to the troop list.
  2242. *
  2243. * @param {string} is_name
  2244. * The name of the troop.
  2245. * @param {int} ii_number
  2246. * The number of the troop.
  2247. */
  2248. this.addTroop = function(is_name, ii_number) {
  2249. lo_troopList.addTroop(is_name, ii_number);
  2250. };
  2251. /**
  2252. * Transform the troop list to a string.
  2253. *
  2254. * @return {string}
  2255. * The string representation of the troop list.
  2256. */
  2257. this.toString = function() {
  2258. return '\n* ' + ls_playerName + ' *' + lo_troopList;
  2259. };
  2260. };
  2261. /**
  2262. * Storage for multiple troop lists.
  2263. *
  2264. * @param {string} is_type
  2265. * The type of the troops (units / ships)
  2266. * @param {string} is_status
  2267. * The status of the troops (own / friends / enemies)
  2268. */
  2269. var _lf_troopListStorage = function(is_type, is_status) {
  2270. /**
  2271. * The type of the troops (units / ships).
  2272. *
  2273. * @type {string}
  2274. */
  2275. var ls_type = is_type;
  2276. /**
  2277. * The status of the troops (own / friends / enemies).
  2278. *
  2279. * @type {string}
  2280. */
  2281. var ls_status = is_status;
  2282. /**
  2283. * The troop lists.
  2284. *
  2285. * @type {(_lf_troopList||_lf_foreignTroopList)[]}
  2286. */
  2287. var la_troopLists = [];
  2288. /**
  2289. * The status of the troop lists (own / friends / enemies).
  2290. *
  2291. * @return {boolean}
  2292. * The status of the lists.
  2293. */
  2294. this.__defineGetter__('status', function() {
  2295. return ls_status;
  2296. });
  2297. /**
  2298. * Add a new troop list to the storage.
  2299. *
  2300. * @param {_lf_troopList||_lf_foreignTroopList} io_troopList
  2301. * The troop list to add.
  2302. */
  2303. this.addTroopList = function(io_troopList) {
  2304. la_troopLists.push(io_troopList);
  2305. };
  2306. /**
  2307. * Transform the troop list storage to a string.
  2308. *
  2309. * @return {string}
  2310. * The string representation of the troop list storage.
  2311. */
  2312. this.toString = function() {
  2313. return '\n--- ' + IC.Language.$('troopInformation.' + ls_type + '.' + ls_status) + ' ---' + la_troopLists.join('\n');
  2314. };
  2315. };
  2316. /**
  2317. * Storage for data of all troops of one type.
  2318. *
  2319. * @param {string} is_type
  2320. * The type of the troops (units / ships)
  2321. */
  2322. var _lf_troopData = function(is_type) {
  2323. /**
  2324. * The type of the troops (units / ships).
  2325. *
  2326. * @type {string}
  2327. */
  2328. var ls_type = is_type;
  2329. /**
  2330. * The troop list storages.
  2331. *
  2332. * @type {_lf_troopListStorage[]}
  2333. */
  2334. var la_listStorages = [];
  2335. /**
  2336. * If the troop list contains no entries.
  2337. *
  2338. * @return {boolean}
  2339. * If the troop list is empty.
  2340. */
  2341. this.__defineGetter__('isEmpty', function() {
  2342. return la_listStorages.length < 1;
  2343. });
  2344. /**
  2345. * Add a new troop list to the storage.
  2346. *
  2347. * @param {string} is_status
  2348. * The status of the troop list.
  2349. * @param {_lf_troopList||_lf_foreignTroopList} io_troopList
  2350. * The troop list to add.
  2351. */
  2352. this.addTroopList = function(is_status, io_troopList) {
  2353. for(var i = 0; i < la_listStorages.length; i++) {
  2354. if(la_listStorages[i].status === is_status) {
  2355. la_listStorages[i].addTroopList(io_troopList);
  2356. return;
  2357. }
  2358. }
  2359. var lo_listStorage = new _lf_troopListStorage(ls_type, is_status);
  2360. lo_listStorage.addTroopList(io_troopList);
  2361. la_listStorages.push(lo_listStorage);
  2362. };
  2363. /**
  2364. * Transform the troop data to a string.
  2365. *
  2366. * @param {string} is_townInformation
  2367. * The information about the town for which the troop data is displayed.
  2368. *
  2369. * @return {string}
  2370. * The string representation of the troop data.
  2371. */
  2372. this.getString = function(is_townInformation) {
  2373. return '===== ' + IC.Language.$('troopInformation.' + ls_type + '.label', [is_townInformation]) + ' =====' + la_listStorages.join('\n\n');
  2374. };
  2375. };
  2376. /**
  2377. * Get a new troop list representation for own troops.
  2378. *
  2379. * @return {_lf_troopList}
  2380. * The troop list.
  2381. */
  2382. this.ownTroopList = function() {
  2383. return new _lf_troopList();
  2384. };
  2385. /**
  2386. * Get a new troop list representation for foreign troops.
  2387. *
  2388. * @param {string} is_playerName
  2389. * The name of the player who owns the troops.
  2390. *
  2391. * @return {_lf_foreignTroopList}
  2392. * The troop list.
  2393. */
  2394. this.foreignTroopList = function(is_playerName) {
  2395. return new _lf_foreignTroopList(is_playerName);
  2396. };
  2397. /**
  2398. * Get a new troop data storage representation for all troops of one type.
  2399. *
  2400. * @param {string} is_type
  2401. * The type of the troops (units / ships).
  2402. *
  2403. * @return {_lf_troopData}
  2404. * The troop data storage.
  2405. */
  2406. this.troopData = function(is_type) {
  2407. return new _lf_troopData(is_type);
  2408. };
  2409. };
  2410. /**
  2411. * Storage for the dta extraction functions.
  2412. *
  2413. * @type {object}
  2414. */
  2415. var _go_dataExtractor = new function() {
  2416. /**
  2417. * Extract own troops from a wrapper.
  2418. *
  2419. * @param {element} ie_wrapper
  2420. * The wrapper to extract the troops from.
  2421. *
  2422. * @return {_go_storageProvider.ownTroopList[]}
  2423. * The extracted troops.
  2424. */
  2425. var _lf_extractOwnTroops = function(ie_wrapper) {
  2426. var la_nameCells = IC.myGM.$$('.table01 .title_img_row th', ie_wrapper);
  2427. var la_numberCells = IC.myGM.$$('.table01 .count td', ie_wrapper);
  2428. var ro_troops = _go_storageProvider.ownTroopList();
  2429. for(var i = 0; i < la_nameCells.length; i++) {
  2430. var li_number = IC.Ikariam.getInt(la_numberCells[i].innerHTML);
  2431. if(li_number > 0)
  2432. ro_troops.addTroop(la_nameCells[i].title, li_number);
  2433. }
  2434. return ro_troops;
  2435. };
  2436. /**
  2437. * Extract foreign troops from a wrapper.
  2438. *
  2439. * @param {element} ie_wrapper
  2440. * The wrapper to extract the troops from.
  2441. *
  2442. * @return {_go_storageProvider.foreignTroopList[]}
  2443. * The extracted troops.
  2444. */
  2445. var _lf_extractForeignTroops = function(ie_wrapper) {
  2446. var la_nameCells = IC.myGM.$$('.table01 .title_img_row th:not(:first-child)', ie_wrapper);
  2447. var la_numberRows = IC.myGM.$$('.table01 tr:not(.title_img_row)', ie_wrapper);
  2448. var li_distance = la_numberRows.length / 2;
  2449. var ra_troops = [];
  2450. for(var i = 0; i < li_distance; i++) {
  2451. var la_numberCells = IC.myGM.$$('td:not(:first-child)', la_numberRows[i]).concat(IC.myGM.$$('td:not(:first-child)', la_numberRows[i + li_distance]));
  2452. var ls_playerName = IC.myGM.$('td a', la_numberRows[i]).innerHTML;
  2453. var lo_playerTroops = _go_storageProvider.foreignTroopList(ls_playerName);
  2454. for(var i = 0; i < la_nameCells.length; i++) {
  2455. var li_number = IC.Ikariam.getInt(la_numberCells[i].innerHTML);
  2456. if(li_number > 0)
  2457. lo_playerTroops.addTroop(la_nameCells[i].title, li_number);
  2458. }
  2459. if(lo_playerTroops.isEmpty === false)
  2460. ra_troops.push(lo_playerTroops);
  2461. }
  2462. return ra_troops;
  2463. };
  2464. /**
  2465. * Extract all troop of one type.
  2466. *
  2467. * @param {string} is_type
  2468. * The type of the troops to extract (units / ships).
  2469. * @param {string} is_wrapperTabId
  2470. * The id of the tab which contains the wrappers.
  2471. *
  2472. * @return {_go_storageProvider.troopData}
  2473. * The extracted data.
  2474. */
  2475. var _lf_extractTroops = function(is_type, is_wrapperTabId) {
  2476. var ro_return = _go_storageProvider.troopData(is_type);
  2477. var la_wrappers = IC.myGM.$$('#' + is_wrapperTabId + ' .contentBox01h');
  2478. var lo_ownTroops = _lf_extractOwnTroops(la_wrappers[0]);
  2479. if(lo_ownTroops.isEmpty === false)
  2480. ro_return.addTroopList('own', lo_ownTroops);
  2481. var la_foreignStatus = ['friends', 'enemies'];
  2482. for(var i = 0; i < la_foreignStatus.length; i++) {
  2483. var la_foreignTroops = _lf_extractForeignTroops(la_wrappers[i + 1]);
  2484. for(var j = 0; j < la_foreignTroops.length; j++) {
  2485. ro_return.addTroopList(la_foreignStatus[i], la_foreignTroops[j]);
  2486. }
  2487. }
  2488. return ro_return;
  2489. };
  2490. /**
  2491. * Extract all troop from the popup.
  2492. *
  2493. * @return {object}
  2494. * All extracted troops.
  2495. * Signature: { units: <_go_storageProvider.troopData>, ships: <_go_storageProvider.troopData> }
  2496. */
  2497. this.extract = function() {
  2498. return {
  2499. units: _lf_extractTroops('units', 'tabUnits'),
  2500. ships: _lf_extractTroops('ships', 'tabShips')
  2501. };
  2502. };
  2503. };
  2504. /**
  2505. * Storage for the troop information functions.
  2506. *
  2507. * @type {object}
  2508. */
  2509. var _go_troopInformation = new function() {
  2510. /**
  2511. * Show the troop information popup.
  2512. *
  2513. * @param {object} io_data
  2514. * All extracted troop.
  2515. * Signature: { units: <_go_storageProvider.troopData>, ships: <_go_storageProvider.troopData> }
  2516. */
  2517. var _ls_showPopup = function(io_data) {
  2518. var la_output = [];
  2519. var ls_townInformation = function() {
  2520. var lo_allTowns = IC.ika.getModel().relatedCityData;
  2521. var lo_selectedTown = lo_allTowns[lo_allTowns.selectedCity];
  2522. return lo_selectedTown.name + ' ' + lo_selectedTown.coords;
  2523. };
  2524. if(!!io_data === true) {
  2525. if(!!io_data.units.isEmpty === false)
  2526. la_output.push(io_data.units.getString(ls_townInformation));
  2527. if(!!io_data.ships.isEmpty === false)
  2528. la_output.push(io_data.ships.getString(ls_townInformation));
  2529. }
  2530. var ls_output = la_output.join('\n\n-------------------------------------------------------------------------------------\n\n');
  2531. if(ls_output.length === 0)
  2532. ls_output = IC.Language.$('troopInformation.noTroops', [ls_townInformation]);
  2533. var lo_text = {
  2534. header: IC.Language.$('troopInformation.header', [ls_townInformation]),
  2535. body: ls_output
  2536. };
  2537. IC.myGM.notification(lo_text, null, { textarea: true, readonly: true, autoselect: true });
  2538. };
  2539. /**
  2540. * Extract the data and show the popup.
  2541. */
  2542. var _lf_showInformation = function() {
  2543. _ls_showPopup(_go_dataExtractor.extract());
  2544. };
  2545. /**
  2546. * Show the troop information link.
  2547. */
  2548. var _lf_doShowTroopInformationLink = function() {
  2549. var le_button = IC.myGM.addButton(IC.myGM.$('#cityMilitary_c .buildingDescription'), IC.Language.$('troopInformation.button'), _lf_showInformation, true);
  2550. var la_cssRules = [['position', 'absolute'], ['top', '5px'], ['right', '20px']];
  2551. for(var i = 0; i < la_cssRules.length; i++) {
  2552. le_button.style[la_cssRules[i][0]] = la_cssRules[i][1];
  2553. }
  2554. };
  2555. /**
  2556. * Update the settings to execute the callback or delete the handler.
  2557. *
  2558. * @param {boolean} ib_enableTroopInformation
  2559. * If the user selected the checkbox to show the troop information.
  2560. */
  2561. this.updateSettings = function(ib_enableTroopInformation) {
  2562. if(ib_enableTroopInformation === true) {
  2563. IC.RefreshHandler.add('cityMilitary', 'troopInformation', _lf_doShowTroopInformationLink);
  2564. return;
  2565. }
  2566. IC.RefreshHandler.remove('cityMilitary', 'troopInformation');
  2567. };
  2568. };
  2569. IC.Options.addCheckbox('showTroopInformation', 'diverseOptions', 1, true, IC.Language.$('troopInformation.options.show'), { changeCallback: _go_troopInformation.updateSettings });
  2570. })();
  2571. IC.con.timeStamp('IkariamEnhancedUI: troop information functions created');
  2572. IC.con.groupEnd();
  2573. }
  2574.  
  2575. /**
  2576. * Main function of the script.<br>
  2577. * Inits the Ikariam Core and calls the script functions.<br>
  2578. * Must be called with <pre>setTimeout(main, 0)</pre> for correct setting of some core variables.
  2579. */
  2580. function main() {
  2581. // Get the Ikariam core.
  2582. var IC = new IkariamCore('3.0', 4369, 'Ikariam Enhanced UI', 'Tobbe', false);
  2583. if(IC.myGM.alreadyExecuted === true)
  2584. return;
  2585. IC.Language.setDefaultLanguage('en');
  2586. 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","easyCircularMessage":"Show button for faster sending of circular messages","signature": {"use":"Enable message signatures","placementTop":"Insert signature above cited messages","global":"Global signature, which would be used on every world:","useServerSpecific":"Use local signature","server":"Local signature, which only would be used on this world:"}},"replacedUrl": {"notification": {"header":"Attention!","text":"You're going to open the link %$1. This happens on your own risk. Proceed?"}},"easyCircular": {"send":"Send circular message"}},"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"}}}});
  2587. var la_language = ['de', 'gr', 'it', 'lv', 'ru'];
  2588. for(var i = 0; i < la_language.length; i++) {
  2589. IC.Language.registerLanguageResource(la_language[i], la_language[i], 'http://resources.ikascripts.de/IkariamEnhancedUI/v3.0/' + la_language[i] + '.json');
  2590. }
  2591. // Instantiate the ui script.
  2592. new EnhancedUI(IC);
  2593. }
  2594.  
  2595. // Call the main function of the script.
  2596. setTimeout(main, 0);