Ikariam Enhanced UI

Enhancements for the user interface of Ikariam.

目前为 2015-03-20 提交的版本。查看 最新版本

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