STS Helper

In Steam Translation Server, add many features to make translate easier.

安裝腳本?
作者推薦腳本

您可能也會喜歡 Steam Auto Sign In

安裝腳本
  1. // ==UserScript==
  2. // @name STS Helper
  3. // @author 7-elephant
  4. // @namespace iFantz7E.StsHelper
  5. // @version 2.73
  6. // @description In Steam Translation Server, add many features to make translate easier.
  7. // @match *://translation.steampowered.com/*
  8. // @icon https://translation.steampowered.com/public/favicon.ico
  9. // @run-at document-start
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @grant GM_addStyle
  13. // @grant GM_setClipboard
  14. // @license GPL-3.0-only
  15. // @copyright 2014, 7-elephant
  16. // @supportURL https://steamcommunity.com/id/7-elephant/
  17. // @contributionURL https://www.paypal.me/iFantz7E
  18. // ==/UserScript==
  19.  
  20. // License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
  21. // Compatibility: Firefox 14+ from Mutation Observer
  22.  
  23. // Since 4 Feb 2014
  24. // http://userscripts.org/scripts/show/325610
  25. // https://greasyfork.org/scripts/2250-sts-helper/
  26.  
  27. (function ()
  28. {
  29. "use strict";
  30. // jshint multistr:true
  31. function initStyle()
  32. {
  33. GM_addStyle
  34. (" \
  35. /* STSH Modify CSS */ \
  36. body { color: #acacac; } \
  37. #logout { \
  38. position: fixed; z-index: 1001; right: 12px; top: 10px; \
  39. line-height: 24px; text-align: right; } \
  40. input[type='button'], input[type='submit'] { \
  41. cursor: pointer; padding: 1px 9px; } \
  42. input[type='button']:disabled, input[type='submit']:disabled { \
  43. cursor: default; color: #777; } \
  44. #suggestionmain > div:nth-child(4) > form:nth-child(2) > div:nth-child(1) { \
  45. text-align: left; } \
  46. .lbAction > div > input[value^='SUBMIT'] { \
  47. width: 670px; height: 30px; border-color: #777 #333 #777 #777; } \
  48. .lbAction > div > input[value^='SUBMIT'][disabled] { border-color: #777; } \
  49. .lbAction > div > input[value^='RESUBMIT'] { \
  50. width: 561px; height: 30px; border-color: #777 #333 #777 #777; } \
  51. .lbAction > div > input[value='CANCEL'] { \
  52. width: 100px; height: 30px; margin-right: 5px; } \
  53. form.lbAction:nth-child(1) > div:nth-child(2) > input:nth-child(1) { \
  54. width: 90%; margin-top: 5px; } \
  55. .suggestion .lbAction textarea { \
  56. max-width: 700px !important; min-height: 50px; } \
  57. .progress td { vertical-align: top; } \
  58. div#suggestions_nav { \
  59. z-index: 3; position: absolute; width: 440px; \
  60. left: 543px; top: 2px; text-align: right; line-height: 24px; \
  61. color: #E1E1E1; } \
  62. #suggestionmain .smallcopy { width: 855px; min-height: 70px; max-height: 70px; } \
  63. #suggestionmain .progress { margin-top: -12px; } \
  64. #suggestionmain > div[style='padding-left: 10px;'] { padding-left: 6px !important; } \
  65. #suggestions_box { margin-top: 1px !important; position: relative; z-index: 20; } \
  66. #suggestions_iframe { min-height: 100px !important; } \
  67. #keylist td:nth-child(1) > div { \
  68. background-image: none !important; min-height: 43px; } \
  69. #keylist tr:nth-child(2n) > td:nth-child(1) > div { \
  70. background-color: #060606 !important; } \
  71. #keylist tr:nth-child(2n) > td:nth-child(1) > div:hover { \
  72. background-color: #0D0D0D !important; } \
  73. #keylist td:nth-child(1) > div:hover { \
  74. background-repeat: no-repeat; background-position: center; \
  75. background-color: #0D0D0D !important; \
  76. background-image: url('./public/images/row_over.gif') !important; } \
  77. #keylist td.progress { \
  78. color: #fff; max-width: 430px; overflow: hidden; \
  79. text-overflow: ellipsis; white-space: nowrap; } \
  80. .progress h1 { display: inline-block; } \
  81. div#suggestions_box iframe { background-color: #111 !important; } \
  82. .suggestions_list { border-right: 0px none; } \
  83. .suggestions_list:nth-child(2) { border: 0px none; } \
  84. .suggestion { \
  85. resize: both; overflow-x: hidden; overflow-y: auto; \
  86. border: 1px solid #505050; border-top: none; \
  87. max-width: 953px; min-width: 200px; min-height: 50px; } \
  88. .suggestion:first-child { border-top: 1px solid #505050; } \
  89. .suggestion_signature { font-family: Verdana; margin-top: 4px; } \
  90. .suggestion_signature input:disabled { color: #777 !important; } \
  91. .lbAction input[value~='COMMENT'] { \
  92. vertical-align: top; margin-top: 1px; height: 52px; } \
  93. .lbAction input[value~='DISCUSS'] { \
  94. vertical-align: top; margin-top: 1px; height: 21px; top: 0px !important; } \
  95. #votes_container a[title='not translated'] { background-color: #333; } \
  96. #suggestion_value_new { min-height: 84px; max-width: 960px; min-width: 200px; overflow-y: auto; } \
  97. #hours > table > tbody > tr:nth-child(2) > th:nth-child(1) { width: 106px; text-align: center; } \
  98. #hours > table > tbody > tr:nth-child(2) > th:nth-child(3) { text-align: center; } \
  99. #hours > table > tbody > tr:nth-child(2) > th:nth-child(4) { text-align: center; } \
  100. #hours > table > tbody > tr > td:nth-child(1) { padding-right: 4px; } \
  101. #hours > table input[name*='[remarks]'] { width: 520px; } \
  102. #hours > table input[name*='[hours]'] { width: 100px; } \
  103. #hours > table input[name*='[minutes]'] { width: 100px; } \
  104. #suggestions_box_outer { overflow: hidden !important; } \
  105. #add_to_discussion { height: 19px; min-height: 19px; } \
  106. .gradienttable td > div { top: 1px !important; } \
  107. .copysmall > td:nth-child(1) { \
  108. white-space: nowrap; overflow: hidden; text-overflow: ellipsis; \
  109. display: inline-block; width: 430px; direction: ltr; } \
  110. div:hover > table > tbody > tr.copysmall > td:nth-child(1) { \
  111. direction: rtl; text-shadow: 1px 1px 1px #0D0D0D;} \
  112. #search input[type='radio'], #search input[type='checkbox'] \
  113. , #search button, #search label { cursor: pointer; } \
  114. .suggestion_error { max-width: 600px; margin-left: 80px; } \
  115. #country_list_id + #hidethis { display: block; margin-top: 8px; } \
  116. .row0:nth-child(odd), .row1:nth-child(odd), .row-1:nth-child(odd), .row-9:nth-child(odd), .row10:nth-child(odd) { \
  117. background-color: #161616; } \
  118. .row0:nth-child(even), .row1:nth-child(even), .row-1:nth-child(even), .row-9:nth-child(even), .row10:nth-child(even) { \
  119. background-color: #202020; } \
  120. .row2:nth-child(odd) { background-color: #1C2117; } \
  121. .row2:nth-child(even) { background-color: #22291B; } \
  122. #replacementstatus { \
  123. top: 0px !important; left: 176px !important; \
  124. display: block !important; opacity: 1.0 !important; } \
  125. a + br + #replacementstatus { left: 326px !important; } \
  126. #keylist_container { margin-left: 10px; } \
  127. img[src='<?=BASE_URL_CURRENT?>public/images/hr.gif'] { background-image: url('./public/images/hr.gif'); } \
  128. ");
  129. GM_addStyle
  130. (" \
  131. /* STSH Main CSS */ \
  132. .stsh_body_crop { overflow-x: hidden; } \
  133. .stsh_btn { width: 90px; } \
  134. .stsh_btn_med { min-width: 112px; } \
  135. .stsh_btn_long { min-width: 136px; } \
  136. .stsh_btn_short { min-width: 66px; } \
  137. .stsh_btn_right { position: relative; float: right; } \
  138. .stsh_text_right { \
  139. position: relative; float: right; \
  140. display: block; margin-right: 4px; text-transform: none; \
  141. font-size: 13px; font-style: normal; padding-top: 2px; } \
  142. .stsh_border_left { border-right-color: #333 !important; } \
  143. .stsh_border_right { border-left-color: #333 !important; } \
  144. .stsh_border_center { border-left-color: #333 !important; border-right-color: #333 !important; } \
  145. .stsh_border_top { border-bottom-color: #333 !important; } \
  146. .stsh_border_middle { border-top-color: #333 !important; } \
  147. .stsh_border_bottom { border-top-color: #333 !important; border-bottom-color: #333 !important; } \
  148. .stsh_suggestion_header { color: #A4B23C; } \
  149. .stsh_suggestion_comment:before { background-color: #E15417 !important; } \
  150. .stsh_suggestion_pending:before { background-color: #DDD !important; } \
  151. .stsh_suggestion_approved:before { background-color: #A4B23C !important; } \
  152. .stsh_suggestion_declined:before { background-color: #F22 !important; } \
  153. .stsh_suggestion_applied:before { background-color: #2EBCEB !important; } \
  154. .stsh_suggestion_removed:before { background-color: #777 !important; } \
  155. .stsh_suggestion { list-style: none; } \
  156. .stsh_suggestion:before { \
  157. content: ''; display: inline-block; position: relative; height: 6px; width: 6px; \
  158. border-radius: 3px; background-clip: padding-box; margin-right: -6px; \
  159. top: -1px; left: -12px; background-color: green; }\
  160. #stsh_frame { \
  161. text-align: center; position: fixed; z-index: 10; \
  162. top: 100px; left: 50%; margin-left: -322px;} \
  163. #stsh_frame_sub { \
  164. background-color: #111; width: 600px; display: inline-block; \
  165. padding: 20px; border: 2px solid #cf9e5f; } \
  166. .stsh_blue { color: #2EBCEB; } \
  167. .stsh_blue_light { color: #87BEED; } \
  168. .stsh_blue_light2 { color: #5C80A1; } \
  169. .stsh_blue_dark { color: #1B6A85; } \
  170. .stsh_green { color: #a4b23c !important; } \
  171. .stsh_green_dark { color: #3a482a; } \
  172. .stsh_red { color: #F22; } \
  173. .stsh_red_light { color: #4dc0f0; } \
  174. .stsh_white { color: #e1e1e1; } \
  175. .stsh_grey { color: #777 !important; } \
  176. .stsh_orange { color: #E15417; } \
  177. .stsh_orange_light { color: #CF8B37; } \
  178. .stsh_orange_light2 { color: #EDB687; } \
  179. .stsh_orange_light3 { color: #FFAA40; } \
  180. .stsh_orange_dark { color: #a75124; } \
  181. .stsh_aqua { color: #538583; } \
  182. .stsh_pink { color: pink; } \
  183. .stsh_yellow { color: #E0B816; } \
  184. .stsh_yellow_light { color: #E0CA70; } \
  185. .stsh_greenyellow_light { color: #D1E070; } \
  186. .stsh_purple { color: #a166f4; } \
  187. .stsh_border_green { border-color: #76802B !important; } \
  188. .stsh_border_green_left { border-color: #76802B #474D1A #76802B #76802B !important; } \
  189. .stsh_cursor_notallowed { cursor: not-allowed !important; } \
  190. .stsh_cursor_pointer { cursor: pointer !important; } \
  191. .stsh_cursor_default { cursor: default !important; } \
  192. .stsh_cursor_help { cursor: help !important; } \
  193. .stsh_inline { display: inline; } \
  194. #stsh_showing { \
  195. color: #CCDAD6; position: fixed; z-index: 1001; \
  196. right: 12px; bottom: 12px; text-align: right; line-height: 14px;} \
  197. #stsh_showing_current { \
  198. color: #CCDAD6; position: fixed; z-index: 1001; \
  199. right: 12px; bottom: 28px; text-align: right; line-height: 14px;} \
  200. .stsh_showing_counter { \
  201. display: inline-block; min-width: 60px; text-align: center; } \
  202. .stsh_showing_header { \
  203. color: #CCDAD6; display: inline-block; width: 135px; \
  204. text-align: center; padding-top: 10px; } \
  205. .stsh_showing_group { \
  206. position: fixed; z-index: 3; right: 10px; top: 74px; \
  207. line-height: 24px; text-align: right; } \
  208. .stsh_home_header { color: #CCDAD6; display: inline-block; padding-top: 10px; } \
  209. .stsh_home_group { \
  210. position: fixed; z-index: 3; right: 0px; top: 74px; \
  211. line-height: 24px; text-align: center; width: 164px; } \
  212. .stsh_home_group > div > .stsh_a_button { border-top-color: #333; border-bottom-color: #333; } \
  213. .stsh_home_group > div > .stsh_a_button:first-child { border-top-color: #777; } \
  214. .stsh_home_group > div > .stsh_a_button:last-child { border-bottom-color: #777; } \
  215. .stsh_home_group > div > div > .stsh_a_button { border-top-color: #333; border-bottom-color: #333; } \
  216. .stsh_home_group > div > div > .stsh_a_button:first-child:not(:last-child) { border-right-color: #333; } \
  217. .stsh_home_group > div > div > .stsh_a_button:last-child:not(:first-child) { border-left-color: #333; } \
  218. .stsh_home_group > div > div:first-child > .stsh_a_button { border-top-color: #777; } \
  219. .stsh_home_group > div > div:last-child > .stsh_a_button { border-bottom-color: #777; } \
  220. .stsh_home_group .stsh_a_button { cursor: pointer; } \
  221. .stsh_menu_group { \
  222. position: fixed; z-index: 3; right: 12px; top: 84px; \
  223. line-height: 24px; text-align: right; } \
  224. .stsh_group_space { margin-top: 3px; } \
  225. .stsh_scroll_header { \
  226. color: #CCDAD6; display: inline-block; width: 130px; \
  227. text-align: center; padding-top: 10px; } \
  228. #stsh_specialEvent { position: absolute; z-index: 2; right: 164px; top: 13px; } \
  229. @media screen and (min-width: 1500px) { \
  230. #stsh_specialEvent { position: fixed; } \
  231. } \
  232. .stsh_snapshot { \
  233. position: absolute; top: 320px; left: 790px; \
  234. width: 140px; text-align: center; color: #FFF; } \
  235. .stsh_text_comment_header { vertical-align: top; user-select: none; } \
  236. .stsh_text_comment { vertical-align: top; display: inline-block; max-width: 850px; user-select: text; } \
  237. .stsh_action_approve, .stsh_action_approve_next { color: #A4B23C; } \
  238. .stsh_action_decline, .stsh_action_decline_next { color: #F22; } \
  239. .stsh_action_apply, .stsh_action_apply_next { color: #2EBCEB; } \
  240. #stsh_autoApprove { vertical-align: -2px; margin-left: 15px; margin-right: 1px; } \
  241. .stsh_unselectable { \
  242. -webkit-touch-callout: none !important; \
  243. -webkit-user-select: none !important; \
  244. -khtml-user-select: none !important; \
  245. -moz-user-select: none !important; \
  246. -ms-user-select: none !important; \
  247. user-select: none !important; } \
  248. .stsh_a_button { \
  249. background-color: #1D1D1D; \
  250. font-family: tahoma,arial,helvetica,trebuchet ms,sans-serif; \
  251. color: #E1E1E1; font-size: 13px; border: 1px solid #777; padding: 1px 9px; } \
  252. .stsh_a_button:link, .stsh_a_button:hover, .stsh_a_button:active, .stsh_a_button:visited { \
  253. color: #E1E1E1; text-decoration: none; } \
  254. .stsh_a_button.stsh_btn { \
  255. display: inline-block; padding: 0px; \
  256. height: 19px; line-height: 19px; width: 88px; } \
  257. .stsh_a_button.stsh_btn_short { \
  258. display: inline-block; padding: 0px; \
  259. height: 19px; line-height: 19px; min-width: 54px; } \
  260. .stsh_a_button.stsh_btn_med { \
  261. display: inline-block; padding: 0px; \
  262. height: 19px; line-height: 19px; min-width: 110px; } \
  263. .stsh_a_button.stsh_btn_long { \
  264. display: inline-block; padding: 0px; \
  265. height: 19px; line-height: 19px; min-width: 134px; } \
  266. .stsh_lineCounter_outer { position: relative; } \
  267. .stsh_lineCounter { \
  268. position: absolute; width: 30px; left: -35px; top: -28px; \
  269. line-height: 28px; text-align: right; \
  270. color: #ACACAC; font-size: 9px; text-shadow: 1px 1px 1px #111; } \
  271. .stsh_glossary_term { min-width: 50px; display: inline-block; } \
  272. .stsh_glossary_header { font-family: Verdana; } \
  273. .stsh_glossary_header, .stsh_glossary_header td { color: #DDD; } \
  274. .stsh_glossary_header *, .stsh_glossary_header td * { color: #858585; } \
  275. .stsh_glossary_header > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(4) { \
  276. width: 10px !important; } \
  277. .stsh_comment_img { \
  278. display: block; max-width: 400px; max-height: 225px; \
  279. margin-top: 5px; margin-bottom: 20px; } \
  280. .stsh_comment_img_zoom { cursor: zoom-in; cursor: -webkit-zoom-in; cursor: -moz-zoom-in; } \
  281. .stsh_hours_curDate { color: #A4B23C; } \
  282. .stsh_hours_curDate input { border-color: #A4B23C; } \
  283. .stsh_text_submit_right { \
  284. height: 30px; width: 214px; margin-right: 5px; border-color: #777 #777 #777 #333; } \
  285. .stsh_truncate { \
  286. white-space: nowrap; overflow: hidden; text-overflow: ellipsis; \
  287. display: inline-block; vertical-align: bottom; } \
  288. .stsh_token_name { max-width: 500px; } \
  289. .stsh_token_share { max-width: 600px; font-size: 0.8em; direction: rtl; } \
  290. .stsh_token_share:hover { direction: ltr; } \
  291. .stsh_pad { padding-left: 2px; padding-right: 2px; } \
  292. .stsh_pad_left { padding-left: 4px; } \
  293. .stsh_pad_right { padding-right: 4px; } \
  294. .stsh_margin_left { margin-left: 4px; } \
  295. .stsh_margin_right { margin-right: 4px; } \
  296. .stsh_hidden { display: none !important; } \
  297. table.gradienttable .stsh_curLang td, table.gradienttable .stsh_dst_curLang td \
  298. , table.gradienttable .stsh_dst_curLang th { \
  299. background: transparent \
  300. linear-gradient(to bottom, #171717 0%, rgba(71, 77, 26, 0.66) 40%, #121212 100%) \
  301. repeat scroll 0% 0% !important; } \
  302. .stsh_delta #suggestion_value_new { border-color: #1B6A85; } \
  303. .stsh_delta .stsh_text_submit { \
  304. color: #2EBCEB; border-color: #1B6A85 #083F52 #1B6A85 #1B6A85 !important; } \
  305. .stsh_delta .stsh_text_submit_right { \
  306. color: #2EBCEB; border-color: #1B6A85 #1B6A85 #1B6A85 #083F52 !important; } \
  307. .stsh_delta .suggestions_list, .stsh_delta .suggestion { \
  308. border-color: #083F52 !important; } \
  309. .stsh_usThem tr:nth-child(odd) { background-color: #161616; } \
  310. .stsh_usThem tr:nth-child(even) { background-color: #202020; } \
  311. .stsh_usThem_langCur { background-color: #2F3317 !important; color: #E1E1E1; } \
  312. .stsh_dst_curLang, table.gradienttable .stsh_dst_curLang th, .stsh_dst_curLang a { \
  313. color: #2ebceb; } \
  314. .stsh_text_trn .lbAction textarea { max-width: 450px !important; } \
  315. .stsh_text_trn .lbAction input[value~='COMMENT'] { height: auto; } \
  316. .stsh_text_trn .stsh_text_submit { width: 190px !important; } \
  317. .stsh_text_trn .stsh_text_submit_right { \
  318. width: 184px !important; margin-right: 16px !important; } \
  319. .stsh_text_trn .suggestion { \
  320. color: #858585; border-width: 1px solid; \
  321. margin-top: -2px; padding-top: 0px; } \
  322. .stsh_text_trn .stsh_counter:after { margin-top: 3px; } \
  323. .stsh_text_trn .suggestion_error { \
  324. max-width: 450px; margin-left: 0px; margin-top: 16px; margin-bottom: -14px; } \
  325. .stsh_text_trn #stsh_autoApprove { display: none; } \
  326. .stsh_text_trn .stsh_autoApprove_label { display: none; } \
  327. .stsh_text_trn input[value='+1'] { display: none; } \
  328. .stsh_text_trn #replacementstatus { left: 140px !important; } \
  329. .stsh_text_trn .stsh_autoReplace_notice { margin-top: 14px; padding-left: 88px; } \
  330. .stsh_text_org, .stsh_text_trn { \
  331. min-height: 21px; display: block; max-width: 470px !important; line-height: 17px; word-break: break-word; } \
  332. .stsh_text_org { margin-bottom: 3px; } \
  333. .stsh_text_org img, .stsh_text_trn img { max-width: 100%; max-height: 100%; } \
  334. .stsh_autoLoginOption { display: inline-block; vertical-align: top; line-height: 69px; padding-left: 30px; } \
  335. #stsh_autoLogin { margin-right: 0px; } \
  336. .stsh_moveSuggestionContainer { margin-top: -3px; } \
  337. #stsh_moveSuggestionBox, #stsh_moveSuggestionList { margin-right: 5px; } \
  338. #stsh_hoursCalc_from { width: 130px; } \
  339. #stsh_hoursCalc_to { width: 130px; border-right: 1px #333 solid; } \
  340. #stsh_hoursCalc_toNow { border-left: 1px #333 solid; } \
  341. .stsh_nav_prev { border-right-color: #333; } \
  342. .stsh_nav_next { border-left-color: #333; } \
  343. .stsh_nav_group { display: inline-block; } \
  344. .stsh_nav_group .stsh_a_button { \
  345. display: inline-block; text-align: center; \
  346. line-height: 17px; min-width: 40px; } \
  347. .stsh_nav_group .stsh_a_button:first-child:not(:last-child) { border-right-color: #333; } \
  348. .stsh_nav_group .stsh_a_button:last-child:not(:first-child) { border-left-color: #333; } \
  349. .stsh_nav_group .stsh_a_button:not(:first-child):not(:last-child) { \
  350. border-left-color: #333; border-right-color: #333; } \
  351. .stsh_img_min { max-width: 200px !important; height: auto !important; } \
  352. .stsh_showHidden { \
  353. display: inherit !important; background-color: #1d1d1d; padding: 1px 5px; \
  354. max-height: inherit !important; height: inherit !important; } \
  355. .stsh_discussion_header input[type='button'] { \
  356. padding: 1px 6px; } \
  357. .stsh_counter { display: inline-block; } \
  358. .stsh_counter[data-counter='Char: 0 :: Word: 0 :: Byte: 0'] { display: none; } \
  359. .stsh_counter:after { content: attr(data-counter); position: absolute; \
  360. margin-left: -280px; width: 278px; text-align: right; } \
  361. .stsh_spanStatusOrg, .stsh_spanStatusTrn { display: block; margin-top: -4px; margin-bottom: 8px; } \
  362. .stsh_spanStatusSug { display: block; margin-top: 8px; margin-bottom: 12px; } \
  363. .stsh_autoCopy_header font { color: #a4b23c !important; font-weight: normal; font-family: Verdana;} \
  364. .stsh_glossary_move { color: #e1e1e1; margin-left: 4px; } \
  365. .stsh_sametoken_file { display: inline-block; } \
  366. .stsh_marker { color: #777 !important; display: inline-block; } \
  367. .stsh_sametoken_header .stsh_marker, .stsh_text_comment .stsh_marker { color: #e1e1e1 !important; } \
  368. .stsh_glossary_header .insertword { display: inline-block; } \
  369. .stsh_glossary_header td { padding-left: 16px; padding-right: 6px; } \
  370. .stsh_glossary_header td .stsh_glossary_term { margin-left: -16px; } \
  371. .stsh_profile_count { width: 100px; display: inline-block; text-align: center; } \
  372. .stsh_profile_count_sugg { margin-left: 13px; } \
  373. .stsh_comment_resolved_label { display: block; width: 300px; margin-bottom: 10px; } \
  374. .stsh_comment_resolved { vertical-align: -2px; margin-left: 0px; margin-right: 1px; } \
  375. .stsh_suggestion_comment_detail > strong:first-child, .stsh_comment_resolved_label > strong:first-child { \
  376. min-width: 64px; display: inline-block; } \
  377. .stsh_discussion_text { display: inline; max-width: 850px; overflow-wrap: break-word; } \
  378. .stsh_discussion_text.stsh_discussion_text_long { display: block; margin-left: 20px; } \
  379. .stsh_date_group { text-align: center; } \
  380. .stsh_date_group button { line-height: 19px; } \
  381. .stsh_date_group .stsh_date_cur { border-left-color: #333; border-right-color: #333; \
  382. margin-top: 22px !important; } \
  383. .stsh_date_group .stsh_date_prev { border-right-color: #333; margin-left: 2px; } \
  384. .stsh_date_group .stsh_date_next { border-left-color: #333; } \
  385. .stsh_autoReplace_header { font-family: Verdana; } \
  386. .stsh_autoReplace_instruction { width: 870px; } \
  387. .stsh_autoReplace_text { width: 300px; cursor: auto !important; } \
  388. .stsh_checkbox_label { margin-left: 10px; } \
  389. .stsh_checkbox_label > input[type='checkbox'] { vertical-align: -2px; margin-left: 0px; margin-right: 1px; } \
  390. .stsh_usThem_translation { min-width: 400px; } \
  391. .stsh_page_userActivity .dial { display: none; } \
  392. .stsh_page_userActivity table.curved { border: 2px solid #444; } \
  393. .stsh_page_usAndThem #leftAreaContainer > table > tbody:nth-child(1) > tr > td:nth-child(1) { \
  394. vertical-align: top; } \
  395. .stsh_page_usAndThem #leftAreaContainer > table, \
  396. .stsh_page_usAndThem #leftAreaContainer > table th, \
  397. .stsh_page_usAndThem #leftAreaContainer > table td { \
  398. border: 1px solid #333; border-collapse: collapse; padding: 4px; } \
  399. .stsh_btn_display { border-left-color: #333; border-right-color: #333; } \
  400. .stsh_btn_display:first-child { border-right-color: #777; } \
  401. .stsh_btn_display:last-child { border-left-color: #777; } \
  402. .stsh_autoReplace_notice { text-align: left; padding-left: 208px; } \
  403. a + br + #replacementstatus + br + .stsh_autoReplace_notice { \
  404. text-align: center; padding-left: 0px; } \
  405. .stsh_suggestion_list_empty { \
  406. border-top: 1px solid #505050 !important; border-left: 1px solid #505050 !important; padding-left: 2px; } \
  407. .stsh_suggestion_border_approved { border-color: #76802B !important; border-top: 1px solid; } \
  408. .stsh_suggestion_border_declined { border-color: #720D0D !important; } \
  409. .stsh_suggestion_border_approved + .stsh_suggestion_border_approved { border-top: none; } \
  410. .stsh_action_edit { border-left-color: #333; } \
  411. .stsh_header_org, .stsh_header_trn { width: 484px; position: relative; } \
  412. .stsh_copy_org, .stsh_copy_trn { position: absolute; margin-left: 8px; margin-top: 22px; border-color: #555; } \
  413. .stsh_copy_new { width: 80px; height: 30px; border-left-color: #333; border-right-color: #333; } \
  414. .stsh_copy_sug { border-right-color: #333; } \
  415. .stsh_suggestion_list_header { width: 961px; } \
  416. .stsh_suggestion_list_history { padding-left: 2px; } \
  417. .stsh_suggestion_list_history_related { border-color: #4D6C87; } \
  418. .stsh_page_home font[style='color:#EDB687;'] { padding-right: 4px; } \
  419. .stsh_home_discussion_file { cursor: pointer; } \
  420. .stsh_home_discussion_comment { overflow-wrap: break-word; } \
  421. .stsh_suggestion_list_history_header { user-select: none; } \
  422. @media screen and (max-height: 600px) { .stsh_home_section_scroll { display: none; } } \
  423. .stsh_home_hideOtherLang { margin-left: 16px; margin-top: 10px; width: 152px; } \
  424. ");
  425. }
  426.  
  427. var timingInit =
  428. {
  429. initNameSpace: 100,
  430. refreshError: 60000,
  431. cleanLinks: 100,
  432. removeHorizonScroll: 100,
  433. resizeTextNew: 100,
  434. improveGlossary: 200,
  435. bindLastText: 100,
  436. insertAtCaret: 500,
  437. pasteLastComment: 250,
  438. autoApprove: 2000,
  439. pasteLastSuggestion: 300,
  440. hideCursor: 3000,
  441. expandTextarea: 100,
  442. focusModAction: 200,
  443. autoReplaceText: 250,
  444. findNextUnmatched: 500,
  445. openFrame: 1000,
  446. improveStatistics: 100,
  447. autoLogin: 3000,
  448. authSubmit: 3000,
  449. bindObserverKeyList: 200,
  450. pageUserActivity: 100,
  451. disableOnClick: 100,
  452. reenableAfterClick: 1000,
  453. };
  454.  
  455. function attachOnLoad(callback)
  456. {
  457. window.addEventListener("load", function (e)
  458. {
  459. callback();
  460. });
  461. }
  462.  
  463. function attachOnReady(callback)
  464. {
  465. document.addEventListener("DOMContentLoaded", function (e)
  466. {
  467. callback();
  468. });
  469. }
  470.  
  471. function insertBeforeElement(newNode, referenceNode)
  472. {
  473. referenceNode.parentNode.insertBefore(newNode, referenceNode);
  474. }
  475.  
  476. function insertAfterElement(newNode, referenceNode)
  477. {
  478. referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
  479. }
  480.  
  481. function removeElement(node)
  482. {
  483. node.parentElement.removeChild(node);
  484. }
  485.  
  486. function getByteCount(str)
  487. {
  488. str = String(str);
  489.  
  490. var count = 0;
  491. for (var i = 0; i < str.length; i++)
  492. {
  493. var c = str.charCodeAt(i);
  494. count += c < 128 ? 1 :
  495. c < 2048 ? 2 :
  496. c < 65536 ? 3 :
  497. c < 2097152 ? 4 :
  498. c < 67108864 ? 5 :
  499. c < 2147483648 ? 6 : 0;
  500. }
  501. return count;
  502. }
  503.  
  504. function escapeRegExp(str)
  505. {
  506. if (typeof str === "string")
  507. {
  508. return str.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
  509. }
  510. return "";
  511. }
  512.  
  513. function addKey(eleListener, eleClick, keyCodes, keyName, keyTitleMode, keyModifierName, checkModifierCallback)
  514. {
  515. /*
  516. eleClick:
  517. element, query
  518. keyCodes:
  519. code, name, array
  520. keyTitleMode:
  521. 0: do nothing
  522. 1: append value
  523. 2: add title if not exist
  524. 4: override title
  525. 8: append textContent
  526. 16: append textContent of firstElementChild
  527. keyModifierName:
  528. Ctrl, Ctrl+Shift, Alt
  529. */
  530. keyCodes = keyCodes || [0];
  531. keyName = keyName || "";
  532. keyTitleMode = keyTitleMode || 0;
  533. keyModifierName = keyModifierName || "";
  534. if (typeof checkModifierCallback !== "function")
  535. {
  536. checkModifierCallback = function(ev)
  537. {
  538. return ev.ctrlKey && ev.shiftKey && ev.altKey;
  539. };
  540. }
  541. if (typeof eleClick === "string")
  542. {
  543. keyTitleMode = 0;
  544. }
  545. if (!Array.isArray(keyCodes))
  546. {
  547. keyCodes = [keyCodes];
  548. }
  549. if (eleListener && eleClick)
  550. {
  551. // apply title
  552. var keyTitle = keyModifierName ? keyModifierName + "+" + keyName : "";
  553. if (keyTitle !== "" && keyTitleMode !== 0)
  554. {
  555. if ((keyTitleMode & 1) === 1)
  556. {
  557. // 1: append value
  558. if (typeof eleClick.value !== "undefined")
  559. {
  560. eleClick.value += " (" + keyTitle + ")";
  561. }
  562. }
  563. if ((keyTitleMode & 2) === 2)
  564. {
  565. // 2: add title if not exist
  566. if (!eleClick.title)
  567. {
  568. eleClick.title = keyTitle;
  569. }
  570. }
  571. if ((keyTitleMode & 4) === 4)
  572. {
  573. // 4: override title
  574. eleClick.title = keyTitle;
  575. }
  576. if ((keyTitleMode & 8) === 8)
  577. {
  578. // 8: append textContent
  579. eleClick.textContent += " (" + keyTitle + ")";
  580. }
  581. if ((keyTitleMode & 16) === 16)
  582. {
  583. // 16: append textContent of firstElementChild
  584. if (eleClick.firstElementChild)
  585. {
  586. eleClick.firstElementChild.textContent += " (" + keyTitle + ")";
  587. }
  588. }
  589. }
  590. eleListener.addEventListener("keydown", function (ev)
  591. {
  592. if (checkModifierCallback(ev))
  593. {
  594. var isSameKey = false;
  595. for (var i = 0; i < keyCodes.length; i++)
  596. {
  597. var keyCode = keyCodes[i];
  598. if (typeof keyCode === "number")
  599. {
  600. isSameKey = (ev.keyCode === keyCode);
  601. }
  602. else
  603. {
  604. // Firefox 32+
  605. isSameKey = (typeof ev.code !== "undefined" && ev.code === keyCode)
  606. }
  607. if (isSameKey)
  608. {
  609. break;
  610. }
  611. }
  612. if (isSameKey)
  613. {
  614. ev.preventDefault();
  615. var eleClickCur = null;
  616. if (typeof eleClick === "string")
  617. {
  618. eleClickCur = document.querySelector(eleClick);
  619. }
  620. else
  621. {
  622. eleClickCur = eleClick;
  623. }
  624. if (eleClickCur)
  625. {
  626. eleClickCur.focus();
  627. eleClickCur.click();
  628. }
  629. return false;
  630. }
  631. }
  632. }, true);
  633. }
  634. }
  635.  
  636. function addKeyCtrl(eleListener, eleClick, keyCode, keyName, keyTitleMode)
  637. {
  638. addKey(eleListener, eleClick, keyCode, keyName, keyTitleMode, "Ctrl", function(ev)
  639. {
  640. return ev.ctrlKey && !ev.shiftKey && !ev.altKey;
  641. });
  642. }
  643.  
  644. function addKeyCtrlShift(eleListener, eleClick, keyCode, keyName, keyTitleMode)
  645. {
  646. addKey(eleListener, eleClick, keyCode, keyName, keyTitleMode, "Ctrl+Shift", function(ev)
  647. {
  648. return ev.ctrlKey && ev.shiftKey && !ev.altKey;
  649. });
  650. }
  651.  
  652. function addKeyAlt(eleListener, eleClick, keyCode, keyName, keyTitleMode)
  653. {
  654. addKey(eleListener, eleClick, keyCode, keyName, keyTitleMode, "Alt", function(ev)
  655. {
  656. return !ev.ctrlKey && !ev.shiftKey && ev.altKey;
  657. });
  658. }
  659.  
  660. function addKeyCtrlEnter(form, input)
  661. {
  662. addKeyCtrl(form, input, ["Enter", 13], "Enter", 1|2);
  663. }
  664.  
  665. function addKeyCtrlShiftEnter(form, input)
  666. {
  667. addKeyCtrlShift(form, input, ["Enter", 13], "Enter", 1|2);
  668. }
  669.  
  670. function disableAfterClick(ele)
  671. {
  672. ele.addEventListener("click", function (e)
  673. {
  674. var ele = e.target;
  675. var attrClick = ele.getAttribute("onclick");
  676. if (attrClick && attrClick.indexOf("confirm") > -1)
  677. {
  678. // skip if has confirm
  679. return;
  680. }
  681. var tagName = ele.tagName;
  682. if (tagName === "INPUT")
  683. {
  684. // don't change color after disable
  685. var styleCp = window.getComputedStyle(ele);
  686. if (styleCp)
  687. {
  688. ele.style.setProperty("color", styleCp.color, "important");
  689. }
  690.  
  691. setTimeout(function(ele)
  692. {
  693. ele.disabled = true;
  694. }, timingInit.disableOnClick, ele);
  695. setTimeout(function(ele)
  696. {
  697. ele.disabled = false;
  698. }, timingInit.reenableAfterClick, ele);
  699. }
  700. else if (tagName === "IMG")
  701. {
  702. setTimeout(function(ele)
  703. {
  704. ele.dataset.stshOldonclick = ele.getAttribute("onclick") || "";
  705. ele.removeAttribute("onclick");
  706. }, timingInit.disableOnClick, ele);
  707.  
  708. setTimeout(function(ele)
  709. {
  710. ele.setAttribute("onclick", ele.dataset.stshOldonclick);
  711. }, timingInit.reenableAfterClick, ele);
  712. }
  713. else if (tagName === "A")
  714. {
  715. setTimeout(function(ele)
  716. {
  717. ele.dataset.stshOldonclick = ele.getAttribute("onclick") || "";
  718. ele.setAttribute("onclick", "return false;");
  719. }, timingInit.disableOnClick, ele);
  720. setTimeout(function(ele)
  721. {
  722. ele.setAttribute("onclick", ele.dataset.stshOldonclick);
  723. }, timingInit.reenableAfterClick, ele);
  724. }
  725. }, true);
  726. }
  727.  
  728. function removeAllEventListeners(element)
  729. {
  730. if (element)
  731. {
  732. var clone = element.cloneNode(false);
  733. while (element.firstChild)
  734. {
  735. clone.appendChild(element.firstChild);
  736. }
  737. element.parentNode.replaceChild(clone, element);
  738. }
  739. }
  740.  
  741. function focusWithoutScroll(selector)
  742. {
  743. var ele = null;
  744. if (selector instanceof HTMLElement)
  745. {
  746. ele = selector;
  747. }
  748. else
  749. {
  750. ele = document.querySelector(selector);
  751. }
  752. if (ele)
  753. {
  754. var x = window.scrollX;
  755. var y = window.scrollY;
  756. ele.focus();
  757. window.scrollTo(x, y);
  758. }
  759. }
  760.  
  761. function scrollToId(id, offset)
  762. {
  763. scrollToElement("#" + id, offset);
  764. }
  765.  
  766. function scrollToElement(selector, offset)
  767. {
  768. if (typeof offset === "undefined")
  769. {
  770. offset = -20;
  771. }
  772. var ele = null;
  773. if (selector)
  774. {
  775. if (selector instanceof HTMLElement)
  776. {
  777. ele = selector;
  778. }
  779. else
  780. {
  781. ele = document.querySelector(selector);
  782. }
  783. if (ele)
  784. {
  785. ele.scrollIntoView(true);
  786. window.scrollBy(0, offset);
  787. }
  788. }
  789. }
  790.  
  791. function resizeSuggestionBox()
  792. {
  793. var script = document.createElement('script');
  794. script.innerHTML =
  795. " \
  796. /* STSH JS - resizeSuggestionBox */ \
  797. var stsh_showSuggestionsBox_start = getTimeMs(); \
  798. var stsh_showSuggestionsBox_itv = setIntervalCustom(function() \
  799. { \
  800. var stsh_showSuggestionsBox_isEnd = false; \
  801. var stsh_showSuggestionsBox_cur = getTimeMs(); \
  802. if (typeof showSuggestionsBox !== 'undefined') \
  803. { \
  804. showSuggestionsBox = function(url) \
  805. { \
  806. /* Edit from STS */ \
  807. g_suggestionsBoxIsOpen = true; \
  808. $('suggestions_box_outer').appear( \
  809. { \
  810. duration : 0.1 \
  811. } \
  812. ); \
  813. $('suggestions_iframe').setAttribute('src', url); \
  814. if (!Prototype.Browser.IE) \
  815. { \
  816. $('suggestions_iframe').focus(); \
  817. } \
  818. $('suggestions_iframe').style.height = (document.viewport.getHeight() * 0.99) + 'px'; \
  819. return false; \
  820. }; \
  821. stsh_showSuggestionsBox_isEnd = true; \
  822. } \
  823. if (stsh_showSuggestionsBox_isEnd || stsh_showSuggestionsBox_cur - stsh_showSuggestionsBox_start > 10000) \
  824. { \
  825. clearInterval(stsh_showSuggestionsBox_itv); \
  826. } \
  827. }, 300); \
  828. ";
  829. document.head.appendChild(script);
  830.  
  831. window.addEventListener("resize", function()
  832. {
  833. var iframe = document.querySelector("#suggestions_iframe");
  834. if (iframe)
  835. {
  836. iframe.style.height = (window.innerHeight * 0.99) + "px";
  837. }
  838. });
  839. }
  840.  
  841. function isRally()
  842. {
  843. var date = new Date();
  844. var year = date.getUTCFullYear();
  845. var month = date.getUTCMonth() + 1;
  846. var day = date.getUTCDate();
  847. if ((month > 9) || (month === 9 && day >= 22) || (month === 0 && day <= 2))
  848. {
  849. return true;
  850. }
  851. return false;
  852. }
  853.  
  854. function getQueryByName(name, url)
  855. {
  856. if (!url)
  857. {
  858. url = (!window.location) ? "" : window.location.search;
  859. }
  860. name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
  861. var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
  862. var results = regex.exec(url);
  863. var retVal = "";
  864. if (results)
  865. {
  866. retVal = results[1].replace(/\+/g, " ");
  867. try
  868. {
  869. retVal = decodeURIComponent(retVal);
  870. }
  871. catch (ex)
  872. {
  873. console.error("getQueryByName", ex.message);
  874. }
  875. }
  876. return retVal;
  877. }
  878.  
  879. function padZero(num, size)
  880. {
  881. return (1e15 + num + "").slice(-size);
  882. }
  883.  
  884. function padZeroHex(num, size)
  885. {
  886. return ("00000000000000000000000" + num.toString(16)).slice(-size).toUpperCase();
  887. }
  888.  
  889. function randNum(min, max)
  890. {
  891. return Math.round(Math.random() * (max - min) + min);
  892. }
  893.  
  894. function isLastIndex(src, des)
  895. {
  896. if (src !== null && src !== "" && des !== null && des !== "")
  897. {
  898. if (src.lastIndexOf(des) === src.length - 1)
  899. {
  900. return true;
  901. }
  902. }
  903. return false;
  904. }
  905.  
  906. function isSpecialChar(ch)
  907. {
  908. var chCode = -1;
  909. if (typeof ch === 'number')
  910. {
  911. chCode = ch;
  912. }
  913. else
  914. {
  915. chCode = ch.charCodeAt(0);
  916. }
  917. if ((chCode > -1 && chCode < 9) // 0-8
  918. || (chCode > 10 && chCode < 13) // 11-12
  919. || (chCode > 13 && chCode < 32)) // 14-31
  920. {
  921. return true;
  922. }
  923. return false;
  924. }
  925.  
  926. function hasSpecialChar(str)
  927. {
  928. var rgxSpCh = /[\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u000B\u000C\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F]+/;
  929. return rgxSpCh.test(str);
  930. }
  931. function checkSpecialCharMatched(str1, str2)
  932. {
  933. // return (status, numSp1, numSp2)
  934. // status: 0:Match, 1:NotMatch, 2:NotEqual
  935. str1 = str1 || "";
  936. str2 = str2 || "";
  937. var strOut1 = "";
  938. var strOut2 = "";
  939. for (var i = 0; i < str1.length; i++)
  940. {
  941. if (isSpecialChar(str1[i]))
  942. {
  943. strOut1 += str1[i];
  944. }
  945. }
  946. for (var i = 0; i < str2.length; i++)
  947. {
  948. if (isSpecialChar(str2[i]))
  949. {
  950. strOut2 += str2[i];
  951. }
  952. }
  953. var retVal = 0;
  954. if (strOut1 === strOut2)
  955. retVal = 0;
  956. else if (strOut1.length === strOut2.length)
  957. retVal = 1;
  958. else
  959. retVal = 2;
  960. return new Array(retVal, strOut1.length, strOut2.length);
  961. }
  962.  
  963. function countDiacriticalMark(str)
  964. {
  965. str = str || "";
  966. var rgxDct = /[\u0300-\u036F]/g;
  967. var matchDct = str.match(rgxDct);
  968. var countDct = matchDct ? matchDct.length : 0;
  969.  
  970. return countDct;
  971. }
  972.  
  973. function countDescendantElement(ele)
  974. {
  975. var countElement = 0;
  976. if (ele instanceof Element)
  977. {
  978. var children = ele.children;
  979. countElement = children.length;
  980. for (var i = 0; i < children.length; i++)
  981. {
  982. countElement += countDescendantElement(children[i]);
  983. }
  984. }
  985. return countElement;
  986. }
  987.  
  988. function trimSpace(str)
  989. {
  990. if (str !== null)
  991. {
  992. return str.replace(/^[ \r\n\t]+/, "").replace(/[ \r\n\t]+$/, "");
  993. }
  994. return str;
  995. }
  996.  
  997. function trimTab(str)
  998. {
  999. if (str !== null)
  1000. {
  1001. return str.replace(/^[\r\n\t]+/, "").replace(/[\r\n\t]+$/, ""); //.replace(/\t+<\//, "<");
  1002. }
  1003. return str;
  1004. }
  1005.  
  1006. function trimTabLeft(str)
  1007. {
  1008. if (str !== null)
  1009. {
  1010. return str.replace(/^[\r\n\t]+/, "");
  1011. }
  1012. return str;
  1013. }
  1014.  
  1015. function trimTabRight(str)
  1016. {
  1017. if (str !== null)
  1018. {
  1019. return str.replace(/[\r\n\t]+$/, "");
  1020. }
  1021. return str;
  1022. }
  1023.  
  1024. function trimElement(ele)
  1025. {
  1026. if (ele instanceof Element)
  1027. {
  1028. if (!ele.firstElementChild)
  1029. {
  1030. ele.textContent = trimTab(ele.textContent);
  1031. }
  1032. else
  1033. {
  1034. if (ele.firstChild.nodeType === document.TEXT_NODE)
  1035. {
  1036. ele.firstChild.textContent = trimTabLeft(ele.firstChild.textContent);
  1037. }
  1038. if (ele.lastChild.nodeType === document.TEXT_NODE)
  1039. {
  1040. ele.lastChild.textContent = trimTabRight(ele.lastChild.textContent);
  1041. }
  1042. }
  1043. }
  1044. return ele;
  1045. }
  1046.  
  1047. if (!String.prototype.endsWith)
  1048. {
  1049. String.prototype.endsWith = function(searchString, position)
  1050. {
  1051. var subjectString = this.toString();
  1052. if (typeof position !== 'number' || !isFinite(position)
  1053. || Math.floor(position) !== position || position > subjectString.length)
  1054. {
  1055. position = subjectString.length;
  1056. }
  1057. position -= searchString.length;
  1058. var lastIndex = subjectString.indexOf(searchString, position);
  1059. return lastIndex !== -1 && lastIndex === position;
  1060. };
  1061. }
  1062.  
  1063. function reload()
  1064. {
  1065. var curHref = window.location.href;
  1066. var posHashtag = curHref.indexOf("#");
  1067. if (posHashtag > -1)
  1068. {
  1069. window.location = curHref.substr(0, posHashtag);
  1070. }
  1071. else
  1072. {
  1073. window.location = curHref;
  1074. }
  1075. }
  1076.  
  1077. function getCookie(c_name)
  1078. {
  1079. var c_value = document.cookie;
  1080. var c_start = c_value.indexOf(" " + c_name + "=");
  1081. if (c_start === -1) {
  1082. c_start = c_value.indexOf(c_name + "=");
  1083. }
  1084. if (c_start === -1) {
  1085. c_value = null;
  1086. }
  1087. else {
  1088. c_start = c_value.indexOf("=", c_start) + 1;
  1089. var c_end = c_value.indexOf(";", c_start);
  1090. if (c_end === -1) {
  1091. c_end = c_value.length;
  1092. }
  1093. c_value = unescape(c_value.substring(c_start, c_end));
  1094. }
  1095. return c_value;
  1096. }
  1097.  
  1098. var isVisible = (function()
  1099. {
  1100. var stateKey;
  1101. var eventKey;
  1102. var keys =
  1103. {
  1104. hidden: "visibilitychange",
  1105. webkitHidden: "webkitvisibilitychange",
  1106. mozHidden: "mozvisibilitychange",
  1107. msHidden: "msvisibilitychange"
  1108. };
  1109. for (stateKey in keys)
  1110. {
  1111. if (stateKey in document)
  1112. {
  1113. eventKey = keys[stateKey];
  1114. break;
  1115. }
  1116. }
  1117. return function(c)
  1118. {
  1119. if (c)
  1120. {
  1121. document.addEventListener(eventKey, c);
  1122. }
  1123. return !document[stateKey];
  1124. }
  1125. })();
  1126.  
  1127. function isDstUs(year, month, day, hour)
  1128. {
  1129. // Support: 2007 - 2029
  1130. // Params: 2016, 3, 1, 15 === 1 Mar 2016 15:00
  1131. var isDst = false;
  1132. try
  1133. {
  1134. var y = parseInt(year);
  1135. var m = parseInt(month);
  1136. var d = parseInt(day);
  1137. var h = parseInt(hour);
  1138. var checkDstUsa = function(dayMar, dayNov, m, d, h)
  1139. {
  1140. var isDst = false;
  1141. if ((m === 3 && d >= dayMar) || (m > 3 && m < 11) || (m === 11 && d <= dayNov))
  1142. isDst = true;
  1143. if ((m === 3 && d === dayMar && h < 2) || (m === 11 && d === dayNov && h >= 2))
  1144. isDst = false;
  1145. return isDst;
  1146. }
  1147. if (y === 2007 || y === 2012 || y === 2018 || y === 2029)
  1148. {
  1149. isDst = checkDstUsa(11, 4, m, d, h);
  1150. }
  1151. else if (y === 2013 || y === 2019 || y === 2024)
  1152. {
  1153. isDst = checkDstUsa(10, 3, m, d, h);
  1154. }
  1155. else if (y === 2008 || y === 2014 || y === 2025)
  1156. {
  1157. isDst = checkDstUsa(9, 2, m, d, h);
  1158. }
  1159. else if (y === 2009 || y === 2015 || y === 2020 || y === 2026)
  1160. {
  1161. isDst = checkDstUsa(8, 1, m, d, h);
  1162. }
  1163. else if (y === 2010 || y === 2021 || y === 2027)
  1164. {
  1165. isDst = checkDstUsa(14, 7, m, d, h);
  1166. }
  1167. else if (y === 2011 || y === 2016 || y === 2022)
  1168. {
  1169. isDst = checkDstUsa(13, 6, m, d, h);
  1170. }
  1171. else if (y === 2017 || y === 2023 || y === 2028)
  1172. {
  1173. isDst = checkDstUsa(12, 5, m, d, h);
  1174. }
  1175. }
  1176. catch (ex)
  1177. {
  1178. console.error("isDstUs", ex.message);
  1179. }
  1180. return isDst;
  1181. }
  1182.  
  1183. function getDateIsoUs(unixTs)
  1184. {
  1185. var dateUs = unixTs ? new Date(unixTs * 1000) : new Date();
  1186. dateUs.setTime(dateUs.getTime() - (1000 * 60 * 60 * 8)); // GMT-8
  1187. if (isDstUs(dateUs.getUTCFullYear(), dateUs.getUTCMonth() + 1, dateUs.getUTCDate(), dateUs.getUTCHours()))
  1188. {
  1189. dateUs.setTime(dateUs.getTime() + (1000 * 60 * 60 * 1)); // GMT-7
  1190. }
  1191. return dateUs.toISOString();
  1192. }
  1193.  
  1194. function getDateUs(unixTs)
  1195. {
  1196. return getDateIsoUs(unixTs).substr(0, 10);
  1197. }
  1198.  
  1199. function getDateTimeUs(unixTs)
  1200. {
  1201. var dateIso = getDateIsoUs(unixTs);
  1202. return dateIso.substr(0, 10) + " " + dateIso.substr(11, 8);
  1203. }
  1204.  
  1205. function getTimeUs(unixTs)
  1206. {
  1207. return getDateIsoUs(unixTs).substr(11, 5);
  1208. }
  1209.  
  1210. function getDateIsoGmt(unixTs)
  1211. {
  1212. var date = unixTs ? new Date(unixTs * 1000) : new Date();
  1213. return date.toISOString();
  1214. }
  1215.  
  1216. function getDateGmt(unixTs)
  1217. {
  1218. return getDateIsoGmt(unixTs).substr(0, 10);
  1219. }
  1220.  
  1221. function getTimeMs(unixTs)
  1222. {
  1223. return unixTs ? new Date(unixTs * 1000).getTime() : new Date().getTime();
  1224. }
  1225.  
  1226. function getUnixTimestamp(date)
  1227. {
  1228. return parseInt((date ? new Date(date) : new Date()).getTime() / 1000);
  1229. }
  1230. var pattUrlTimestamp =
  1231. {
  1232. type1: /\?t=[0-9]{6,}\&/g,
  1233. type2: /\&t=[0-9]{6,}/g,
  1234. type3: /\?t=[0-9]{6,}/g,
  1235. type4: /\&[0-9]{6,}\&/g,
  1236. type5: /\&$/,
  1237. };
  1238.  
  1239. function cleanUrlTimestamp(eles)
  1240. {
  1241. if (!eles || !eles.length)
  1242. return;
  1243.  
  1244. for (var i = 0; i < eles.length; i++)
  1245. {
  1246. var val = "";
  1247. var attr = "";
  1248. if (eles[i].tagName === "A")
  1249. {
  1250. attr = "href";
  1251. }
  1252. else if (eles[i].tagName === "FORM")
  1253. {
  1254. attr = "action";
  1255. }
  1256. else if (eles[i].tagName === "DIV")
  1257. {
  1258. attr = "onclick";
  1259. }
  1260. else if (eles[i].tagName === "INPUT")
  1261. {
  1262. attr = "onclick";
  1263. if (eles[i].name === "t")
  1264. {
  1265. removeElement(eles[i]);
  1266. continue;
  1267. }
  1268. }
  1269. var isEdit = false;
  1270. val = eles[i].getAttribute(attr);
  1271. if (pattUrlTimestamp.type1.test(val))
  1272. {
  1273. eles[i].setAttribute(attr, val.replace(pattUrlTimestamp.type1, "?"));
  1274. isEdit = true;
  1275. }
  1276. else if (pattUrlTimestamp.type2.test(val))
  1277. {
  1278. eles[i].setAttribute(attr, val.replace(pattUrlTimestamp.type2, ""));
  1279. isEdit = true;
  1280. }
  1281. else if (pattUrlTimestamp.type3.test(val))
  1282. {
  1283. eles[i].setAttribute(attr, val.replace(pattUrlTimestamp.type3, ""));
  1284. isEdit = true;
  1285. }
  1286. if (isEdit)
  1287. {
  1288. val = eles[i].getAttribute(attr);
  1289. }
  1290. if (pattUrlTimestamp.type4.test(val))
  1291. {
  1292. eles[i].setAttribute(attr, val.replace(pattUrlTimestamp.type4, "&"));
  1293. }
  1294. if (pattUrlTimestamp.type5.test(val))
  1295. {
  1296. eles[i].setAttribute(attr, val.replace(pattUrlTimestamp.type5, ""));
  1297. }
  1298. }
  1299. }
  1300.  
  1301. var timeoutList = [];
  1302. var intervalList = [];
  1303.  
  1304. function setTimeoutCustom(func, tm, params)
  1305. {
  1306. var id = setTimeout(func, tm, params);
  1307. timeoutList.push(id);
  1308. return id;
  1309. }
  1310.  
  1311. function clearTimeoutAll()
  1312. {
  1313. for (var i = 0; i < timeoutList.length; i++)
  1314. {
  1315. clearTimeout(timeoutList[i]);
  1316. }
  1317. }
  1318.  
  1319. function setIntervalCustom(func, tm, params)
  1320. {
  1321. var id = setInterval(func, tm, params);
  1322. intervalList.push(id);
  1323. return id;
  1324. }
  1325.  
  1326. function clearIntervalAll()
  1327. {
  1328. for (var i = 0; i < intervalList.length; i++)
  1329. {
  1330. clearInterval(intervalList[i]);
  1331. }
  1332. }
  1333.  
  1334. function main()
  1335. {
  1336. var perfStart = 0;
  1337. if (performance && performance.now)
  1338. {
  1339. perfStart = performance.now();
  1340. }
  1341. var url = document.documentURI;
  1342. var lang = getCookie("Language");
  1343. var userId = "";
  1344. var userName = "";
  1345. if (document.body)
  1346. {
  1347. document.body.classList.add("stsh");
  1348. }
  1349. else
  1350. {
  1351. setTimeoutCustom(function()
  1352. {
  1353. if (document.body)
  1354. {
  1355. document.body.classList.add("stsh");
  1356. }
  1357. }, timingInit.initNameSpace);
  1358. }
  1359. // Auto refresh when error
  1360. {
  1361. var h1 = document.querySelector("#leftAreaContainer > h1, body > h1");
  1362. if (h1)
  1363. {
  1364. var text = h1.textContent.trim();
  1365. if (text === "Steam Translation Server - Maintenance Warning"
  1366. || text === "Forbidden")
  1367. {
  1368. console.log("stsh: refresh");
  1369. setTimeoutCustom(reload, timingInit.refreshError);
  1370. return;
  1371. }
  1372. }
  1373. }
  1374.  
  1375. // Clean links
  1376. {
  1377. setTimeoutCustom(function()
  1378. {
  1379. var eles = document.querySelectorAll("a, form[action], input");
  1380. cleanUrlTimestamp(eles);
  1381. }, timingInit.cleanLinks);
  1382. }
  1383. // Fix STS URL paths
  1384. {
  1385. var arrQuery = ["img"];
  1386. var arrAttr = ["src"];
  1387. for (var j = 0; j < arrQuery.length; j++)
  1388. {
  1389. var eles = document.querySelectorAll(arrQuery[j]);
  1390. for (var i = 0; i < eles.length; i++)
  1391. {
  1392. var attr = eles[i].getAttribute(arrAttr[j]);
  1393. if (attr)
  1394. {
  1395. var attrNew = attr.replace(/<\?=BASE_URL_CURRENT\?>/g, "/");
  1396. if (attrNew !== attr)
  1397. {
  1398. console.log("STS URL path is missing: " + eles[i].outerHTML);
  1399. eles[i].setAttribute(arrAttr[j], attrNew);
  1400. }
  1401. }
  1402. }
  1403. }
  1404. }
  1405. // Set current user
  1406. {
  1407. userId = GM_getValue("user", "");
  1408. userName = GM_getValue("name", "");
  1409. if (url.indexOf("/home.php") > -1)
  1410. {
  1411. var eleUser = document.querySelector("#leftAreaContainer > b > a[href^='user_activity.php?user=']");
  1412. if (eleUser)
  1413. {
  1414. var user = getQueryByName("user", eleUser.href);
  1415. if (user && userId !== user)
  1416. {
  1417. userId = user;
  1418. GM_setValue("user", userId);
  1419. }
  1420. var name = eleUser.textContent.trim();
  1421. if (name && userName !== name)
  1422. {
  1423. userName = name;
  1424. GM_setValue("name", userName);
  1425. }
  1426. }
  1427. }
  1428. }
  1429.  
  1430. var eleLogout = document.querySelector("#logout");
  1431. if (eleLogout)
  1432. {
  1433. var logoutHtml =
  1434. ' \
  1435. <a class="stsh_a_button stsh_btn_myProfile stsh_border_left" target="_blank" \
  1436. href="%PROFILE%" title="%NAME%">My Profile</a>\
  1437. <input name="login_button" class="stsh_border_right" value="Logout?" \
  1438. type="submit" onclick="return confirm(\'Logout?\');" /> \
  1439. ';
  1440. logoutHtml = logoutHtml
  1441. .replace("%PROFILE%", "/user_activity.php" + (userId ? "?user=" + userId : ""))
  1442. .replace("%NAME%", userName);
  1443. eleLogout.innerHTML = logoutHtml;
  1444. // Special event button
  1445. {
  1446. if (isRally())
  1447. {
  1448. var divSpecial = document.createElement("div");
  1449. divSpecial.id = "stsh_specialEvent";
  1450. divSpecial.innerHTML =
  1451. ' \
  1452. <a class="stsh_a_button" target="_blank" href="/rally.php">Year-End Rally</a> \
  1453. ';
  1454. eleLogout.parentElement.appendChild(divSpecial);
  1455. }
  1456. }
  1457. }
  1458. // Declare functions
  1459. var removeStsHtmlTags = null;
  1460. var displayHtmlTags = null;
  1461. {
  1462. removeStsHtmlTags = function(ele, isRemovedBrowserGenerated)
  1463. {
  1464. isRemovedBrowserGenerated = (typeof isRemovedBrowserGenerated === "undefined")
  1465. ? true : !!isRemovedBrowserGenerated;
  1466. var html = "";
  1467. if (ele)
  1468. {
  1469. html = (typeof ele.dataset.stshHtml === "undefined")
  1470. ? trimTab(ele.innerHTML) : ele.dataset.stshHtml;
  1471. if (ele.classList.contains("stsh_text_org"))
  1472. {
  1473. html = html.replace(/<span style="color:#ff0000;">(.*?)<\/span>/ig, "$1")
  1474. .replace(/<span style="color:#ffffff;">(.*?)<\/span>/ig, "$1")
  1475. .replace(/<font style="BACKGROUND-COLOR: blue">(.+?)<\/font>/ig, "$1")
  1476. .replace(/<font face="Times New Roman">(.+?)<\/font>/ig, "$1");
  1477. }
  1478. else if (ele.classList.contains("stsh_text_trn"))
  1479. {
  1480. html = html.replace(/<span style="color:#ff0000;">(.*?)<\/span>/ig, "$1")
  1481. .replace(/<span style="color:#ffffff;">(.*?)<\/span>/ig, "$1")
  1482. .replace(/<font face="Times New Roman">(.+?)<\/font>/ig, "$1");
  1483. }
  1484. else if (ele.classList.contains("suggestion_text"))
  1485. {
  1486. html = html.replace(/<span style="color:red;">(.*?)<\/span>/ig, "$1")
  1487. .replace(/<font face="Times New Roman">(.+?)<\/font>/ig, "$1");
  1488. }
  1489. if (isRemovedBrowserGenerated)
  1490. {
  1491. // Remove browser generated attributes and ending tags
  1492. // Regex .+? is "reluctant" that means "as few characters as it can"
  1493. html = html.replace(/="">/g, ">")
  1494. .replace(/([^\t])\t\t\t\t<\/[^\t ]+>$/, "$1")
  1495. .replace(/<script data-pagespeed-no-defer[\s\S]+?\/script>/ig, "")
  1496. .replace(/ data-pagespeed-url-hash=".+?"/ig, "")
  1497. .replace(/ onload="pagespeed.+?"/ig, "");
  1498. }
  1499. }
  1500. return html;
  1501. }
  1502. displayHtmlTags = function(ele)
  1503. {
  1504. if (ele)
  1505. {
  1506. ele.innerHTML = (typeof ele.dataset.stshHtml === "undefined")
  1507. ? trimTab(ele.innerHTML).replace(/\<span[^\>]+class=\"stsh_[\s\S]+?\/span\>/ig, "")
  1508. : ele.dataset.stshHtml;
  1509. var isSkip = false;
  1510. var isBb = (ele.textContent.indexOf("[/") > -1);
  1511. var isUsThem = false;
  1512. var isReplaceNewline = true;
  1513. var isReplaceScript = true;
  1514. var isDisplayBr = true;
  1515. ele.innerHTML = removeStsHtmlTags(ele, false);
  1516. if (ele.classList.contains("stsh_text_trn"))
  1517. {
  1518. if (ele.classList.contains("stsh_text_trn_empty"))
  1519. {
  1520. isSkip = true;
  1521. }
  1522. }
  1523. else if (ele.classList.contains("stsh_usThem_translation"))
  1524. {
  1525. isUsThem = true;
  1526. isReplaceNewline = false;
  1527. isReplaceScript = false;
  1528. isDisplayBr = false;
  1529. if (ele.innerHTML === "<i>--- Not Yet Translated ---</i>")
  1530. {
  1531. isSkip = true;
  1532. }
  1533. }
  1534. //isReplaceScript = false;
  1535. if (!isSkip)
  1536. {
  1537. ele.textContent = trimTab(ele.innerHTML);
  1538. var newHtml = ele.innerHTML;
  1539. if (!isBb)
  1540. {
  1541. if (isReplaceScript)
  1542. {
  1543. newHtml = newHtml
  1544. .replace(/&lt;script([^&]+)[\s\S]+?\/script&gt;/ig,
  1545. "<br>&lt;script$1&gt;...&lt;/script&gt;<br>")
  1546. .replace(/&lt;style([^&]+)[\s\S]+?\/style&gt;/ig,
  1547. "<br>&lt;style$1&gt;...&lt;/style&gt;<br>");
  1548. }
  1549. if (isReplaceNewline)
  1550. {
  1551. newHtml = newHtml
  1552. .replace(/\n/ig, "\n<br>");
  1553. }
  1554. newHtml = newHtml
  1555. // Remove browser generated attributes
  1556. .replace(/=""&gt;/ig, "&gt;")
  1557. // Remove browser generated ending tags
  1558. .replace(/([^\t])\t\t\t\t&lt;\/[^\t ]+&gt;$/i, "$1")
  1559. .replace(/&lt;/ig, '<span class="stsh_marker">&lt;')
  1560. .replace(/&gt;/ig, "&gt;</span>")
  1561. .replace(/&lt;li/ig, "<br>&lt;li")
  1562. .replace(/&amp;/ig, "&");
  1563. if (isDisplayBr)
  1564. {
  1565. newHtml = newHtml
  1566. .replace(/br([ \/]*)&gt;<\/span>/ig, "br$1&gt;</span><br>");
  1567. }
  1568. else
  1569. {
  1570. newHtml = newHtml
  1571. .replace(/<span class="stsh_marker">&lt;br([ \/]*)&gt;<\/span>/ig, "<br>");
  1572. }
  1573. }
  1574. else
  1575. {
  1576. if (isReplaceNewline)
  1577. {
  1578. newHtml = newHtml
  1579. .replace(/\n/ig, "\n<br>");
  1580. }
  1581. newHtml = newHtml
  1582. .replace(/\[/ig, '<span class="stsh_marker">[')
  1583. .replace(/\]/ig, "]</span>")
  1584. .replace(/&lt;font face="Times New Roman"&gt;-&lt;\/font&gt;/ig, "-")
  1585. .replace(/&amp;nbsp;/ig, " ");
  1586. }
  1587. if (isUsThem)
  1588. {
  1589. var status = newHtml.substr(67, 8);
  1590. //console.log(status);
  1591. if (status === "pending)")
  1592. {
  1593. newHtml = '<font style="color:CF8B37">(pending)</font>' + newHtml.substr(121);
  1594. }
  1595. else if (status === "approved")
  1596. {
  1597. newHtml = '<font style="color:A4B23C">(approved)</font>' + newHtml.substr(122);
  1598. }
  1599. else if (status === "outdated")
  1600. {
  1601. newHtml = '<font style="color:FF0000">(outdated)</font>' + newHtml.substr(122);
  1602. }
  1603. }
  1604. ele.innerHTML = newHtml;
  1605. }
  1606. }
  1607. }
  1608. }
  1609. // End Declare functions
  1610. if (url.indexOf("Us_And_Them.php") > -1)
  1611. {
  1612. document.body && document.body.classList.add("stsh_page_usAndThem");
  1613. var h1 = document.querySelector("#leftAreaContainer > h1:nth-child(2)");
  1614. if (h1)
  1615. {
  1616. var header = h1.textContent.trim();
  1617. var key = header.split(" ")[0];
  1618. h1.innerHTML = header.replace(key, "<a href='/translate.php?keyonly=1&search_input="
  1619. + encodeURIComponent(key) + "' >" + key + "</a>");
  1620. document.title = key + " - " + document.title;
  1621. }
  1622. // Hilight cur lang
  1623. {
  1624. var eleTable = document.querySelector("#leftAreaContainer > table");
  1625. if (eleTable)
  1626. {
  1627. eleTable.classList.add("stsh_usThem");
  1628. var eleLangCur = null;
  1629. var elesLang = eleTable.querySelectorAll("tr > td:nth-child(1) > a");
  1630. for (var i = 1; i < elesLang.length; i++)
  1631. {
  1632. if (lang === elesLang[i].textContent.trim().toLowerCase())
  1633. {
  1634. eleLangCur = elesLang[i].parentElement.parentElement;
  1635. break;
  1636. }
  1637. }
  1638. if (eleLangCur)
  1639. {
  1640. eleLangCur.classList.add("stsh_usThem_langCur");
  1641. }
  1642. if (elesLang.length > 1)
  1643. {
  1644. elesLang[0].parentElement.parentElement.classList.add("stsh_usThem_langEng")
  1645. }
  1646. }
  1647. }
  1648. // Normalize
  1649. // Add start/end marker to English text
  1650. {
  1651. var elesTranslation = document.querySelectorAll(
  1652. ".stsh_usThem > tbody:nth-child(1) > tr > td:nth-child(2)");
  1653. for (var i = 0; i < elesTranslation.length; i++)
  1654. {
  1655. elesTranslation[i].classList.add("stsh_usThem_translation");
  1656. var eleFirst = elesTranslation[i].firstElementChild;
  1657. if (eleFirst && eleFirst.textContent === "(outdated)")
  1658. {
  1659. // Fix STS inconsistent space
  1660. insertAfterElement(document.createTextNode(" "), eleFirst);
  1661. }
  1662. }
  1663. var container = "\"";
  1664. var tdEng = elesTranslation.length > 1 ? elesTranslation[0] : null;
  1665. if (tdEng)
  1666. {
  1667. //tdEng.innerHTML = container + tdEng.innerHTML + container;
  1668. }
  1669. }
  1670. // Add scroll to
  1671. // Add move up
  1672. {
  1673. var eleMenu = document.createElement("div");
  1674. document.body.appendChild(eleMenu);
  1675. eleMenu.innerHTML =
  1676. ' \
  1677. <div class="stsh_menu_group"> \
  1678. &nbsp; <span class="stsh_scroll_header">Scroll To</span>\
  1679. <br> &nbsp; <input value="English" \
  1680. class="stsh_btn_long" type="button" onclick="scrollToElement(\'.stsh_usThem_langEng\', -8); return false;" > \
  1681. <br> &nbsp; <input value="My lang" \
  1682. class="stsh_btn_long" type="button" onclick="scrollToElement(\'.stsh_usThem_langCur\', -30); return false;" > \
  1683. <div class="stsh_block_scrollToDiscussion stsh_inline"> \
  1684. <br> &nbsp; <input value="Discussion" \
  1685. class="stsh_btn_long" \
  1686. type="button" onclick="scrollToElement(\'a[name=\\\'tokendiscussion\\\']\'); return false;" > \
  1687. </div> \
  1688. <br> \
  1689. <br> &nbsp; <input value="Move up my lang" \
  1690. class="stsh_btn_long stsh_btn_moveLang" type="button" onclick="return false;" > \
  1691. <br> \
  1692. <div class="stsh_block_displayHtml stsh_inline"> \
  1693. <br> &nbsp; <input value="Display HTML tags" \
  1694. class="stsh_btn_long stsh_btn_displayHtmlTags" type="button" onclick="return false;" > \
  1695. <br> \
  1696. </div> \
  1697. <br> &nbsp; <input value="Refresh" \
  1698. class="stsh_btn_long" type="button" onclick="window.location = window.location.href; return false;" /> \
  1699. <br> \
  1700. </div> \
  1701. ';
  1702. if (!document.querySelector("a[name='tokendiscussion']"))
  1703. {
  1704. var eleBlock = document.querySelector(".stsh_block_scrollToDiscussion");
  1705. if (eleBlock)
  1706. {
  1707. eleBlock.classList.add("stsh_hidden");
  1708. }
  1709. }
  1710.  
  1711. var eleMove = eleMenu.querySelector(".stsh_btn_moveLang");
  1712. if (eleMove)
  1713. {
  1714. eleMove.addEventListener("click", function(ev)
  1715. {
  1716. var ele = ev.target;
  1717. ele.disabled = true;
  1718. var eleLangEng = document.querySelector(".stsh_usThem_langEng");
  1719. var eleLangCur = document.querySelector(".stsh_usThem_langCur");
  1720. if (eleLangEng && eleLangCur)
  1721. {
  1722. insertAfterElement(eleLangCur, eleLangEng);
  1723. }
  1724. });
  1725. }
  1726. // Sample: https://translation.steampowered.com/Us_And_Them.php?token_key_ID=21476726000412883
  1727. var eleHtml = eleMenu.querySelector(".stsh_btn_displayHtmlTags");
  1728. if (eleHtml)
  1729. {
  1730. var eleEng = document.querySelector(".stsh_usThem_langEng > .stsh_usThem_translation");
  1731. if (eleEng.firstElementChild)
  1732. {
  1733. eleHtml.addEventListener("click", function(ev)
  1734. {
  1735. var ele = ev.target;
  1736. ele.disabled = true;
  1737. var elesTranslation = document.querySelectorAll(".stsh_usThem_translation");
  1738. for (var i = 0; i < elesTranslation.length; i++)
  1739. {
  1740. displayHtmlTags(elesTranslation[i]);
  1741. }
  1742. });
  1743. }
  1744. else
  1745. {
  1746. var eleBlock = document.querySelector(".stsh_block_displayHtml");
  1747. if (eleBlock)
  1748. {
  1749. eleBlock.classList.add("stsh_hidden");
  1750. }
  1751. }
  1752. }
  1753. }
  1754. } // End Us_And_Them.php
  1755.  
  1756. if (url.indexOf("suggestions.php") > -1)
  1757. {
  1758. document.body && document.body.classList.add("stsh_page_suggestions");
  1759. var eleTextOrg = null;
  1760. var eleTextTrn = null;
  1761. var eleTextNew = null;
  1762. var elesTextSug = null;
  1763. var eleTextSubmit = null;
  1764. var eleTextSubmitNext = null;
  1765. var elesTextRemoveComment = null;
  1766. var eleHeaderOrg = null;
  1767. var eleHeaderTrn = null;
  1768. // Normalize
  1769. {
  1770. eleTextOrg = document.querySelector(".progress > tbody > tr:last-child > td:nth-child(1)");
  1771. if (eleTextOrg)
  1772. {
  1773. eleTextOrg.classList.add("stsh_text_org");
  1774. trimElement(eleTextOrg);
  1775. eleTextOrg.dataset.stshHtml = eleTextOrg.innerHTML;
  1776. }
  1777. eleTextTrn = document.querySelector(".progress > tbody > tr:last-child > td:nth-child(3)");
  1778. if (eleTextTrn)
  1779. {
  1780. eleTextTrn.classList.add("stsh_text_trn");
  1781. trimElement(eleTextTrn);
  1782. if (eleTextTrn.textContent === "")
  1783. {
  1784. eleTextTrn.classList.add("stsh_text_trn_empty");
  1785. }
  1786. eleTextTrn.dataset.stshHtml = eleTextTrn.innerHTML;
  1787. }
  1788. eleTextNew = document.querySelector("#suggestion_value_new");
  1789. elesTextSug = document.querySelectorAll(".suggestion_text");
  1790. for (var i = 0; i < elesTextSug.length; i++)
  1791. {
  1792. elesTextSug[i].classList.add("stsh_text_sug");
  1793. elesTextSug[i].dataset.stshHtml = elesTextSug[i].innerHTML;
  1794. }
  1795. eleTextSubmit = document.querySelector(".lbAction[name='suggestion_temp'] input[accesskey='s']");
  1796. if (eleTextSubmit)
  1797. {
  1798. eleTextSubmit.classList.add("stsh_text_submit");
  1799. if (eleTextSubmit.value.indexOf("RESUBMIT") > -1)
  1800. {
  1801. eleTextSubmit.classList.add("stsh_text_resubmit");
  1802. }
  1803. }
  1804. eleTextSubmitNext = document.querySelector(".lbAction input[type='submit'][accesskey='a']");
  1805. if (eleTextSubmitNext)
  1806. {
  1807. eleTextSubmitNext.value = "Next";
  1808. eleTextSubmitNext.classList.add("stsh_text_submit_right");
  1809. }
  1810. elesTextRemoveComment = document.querySelectorAll(".suggestion_signature .lbAction[name^='mymodcomment'] a");
  1811. for (var i = 0; i < elesTextRemoveComment.length; i++)
  1812. {
  1813. elesTextRemoveComment[i].removeAttribute("href");
  1814. elesTextRemoveComment[i].classList.add("stsh_text_removeComment");
  1815. }
  1816. var elesTextComment = document.querySelectorAll("textarea[name='suggestion_comment']");
  1817. for (var i = 0; i < elesTextComment.length; i++)
  1818. {
  1819. elesTextComment[i].nextElementSibling.classList.add("stsh_submit_comment");
  1820. elesTextComment[i].classList.add("stsh_text_addComment");
  1821. }
  1822. var eleInputPrev = document.querySelector("#suggestions_nav > input[value^='Prev']");
  1823. if (eleInputPrev)
  1824. {
  1825. eleInputPrev.classList.add("stsh_nav_prev");
  1826. }
  1827. var eleInputNext = document.querySelector("#suggestions_nav > input[value~='Next']");
  1828. if (eleInputNext)
  1829. {
  1830. eleInputNext.classList.add("stsh_nav_next");
  1831. }
  1832. var elesApprove = document.querySelectorAll(".suggestion_signature input[value~='APPROVE']");
  1833. for (var i = 0; i < elesApprove.length; i++)
  1834. {
  1835. elesApprove[i].classList.add("stsh_action_approve");
  1836. }
  1837. var elesDecline = document.querySelectorAll(".suggestion_signature input[value~='DECLINE']");
  1838. for (var i = 0; i < elesDecline.length; i++)
  1839. {
  1840. elesDecline[i].classList.add("stsh_action_decline");
  1841. }
  1842.  
  1843. var elesApply = document.querySelectorAll(".suggestion_signature input[value~='APPLY']");
  1844. for (var i = 0; i < elesApprove.length; i++)
  1845. {
  1846. elesApply[i].classList.add("stsh_action_apply");
  1847. }
  1848. var elesNext = document.querySelectorAll(".suggestion_signature input[value~='Next']");
  1849. for (var i = 0; i < elesNext.length; i++)
  1850. {
  1851. elesNext[i].value = "Next";
  1852. var elePrev = elesNext[i].previousElementSibling;
  1853. if (elePrev)
  1854. {
  1855. if (elePrev.classList.contains("stsh_action_approve"))
  1856. {
  1857. elesNext[i].classList.add("stsh_action_approve_next");
  1858. }
  1859. else if (elePrev.classList.contains("stsh_action_decline"))
  1860. {
  1861. elesNext[i].classList.add("stsh_action_decline_next");
  1862. }
  1863. else if (elePrev.classList.contains("stsh_action_apply"))
  1864. {
  1865. elesNext[i].classList.add("stsh_action_apply_next");
  1866. }
  1867. }
  1868. }
  1869. var elesRemove = document.querySelectorAll(".suggestion_signature input[value='REMOVE']");
  1870. for (var i = 0; i < elesRemove.length; i++)
  1871. {
  1872. elesRemove[i].classList.add("stsh_action_remove");
  1873. elesRemove[i].classList.add("stsh_yellow_light");
  1874. }
  1875. var elesEdit = document.querySelectorAll("input[value='Edit']");
  1876. for (var i = 0; i < elesEdit.length; i++)
  1877. {
  1878. elesEdit[i].classList.add("stsh_action_edit");
  1879. elesEdit[i].classList.add("stsh_blue_light");
  1880. }
  1881. var elesRemoveMyComment = document.querySelectorAll(
  1882. ".suggestion_signature .lbAction[name^='myFrm'] a[onclick*='.submit()']");
  1883. for (var i = 0; i < elesRemoveMyComment.length; i++)
  1884. {
  1885. elesRemoveMyComment[i].removeAttribute("href");
  1886. elesRemoveMyComment[i].classList.add("stsh_text_removeMyComment");
  1887. }
  1888. var elesFriendDiscuss = document.querySelectorAll(".friend_block_discussions");
  1889. for (var i = 0; i < elesFriendDiscuss.length; i++)
  1890. {
  1891. var eleDiscuss = elesFriendDiscuss[i].parentElement.nextElementSibling;
  1892. if (eleDiscuss)
  1893. {
  1894. eleDiscuss.classList.add("stsh_discussion");
  1895. }
  1896. }
  1897. var eleSugList = document.querySelector(".suggestions_list:nth-child(2)");
  1898. if (eleSugList)
  1899. {
  1900. if (eleSugList.childElementCount === 0)
  1901. {
  1902. eleSugList.classList.add("stsh_suggestion_list_empty");
  1903. }
  1904. else
  1905. {
  1906. for (var i = 0; i < eleSugList.children.length; i++)
  1907. {
  1908. if (eleSugList.children[i].querySelector(".suggestion_status_approved"))
  1909. {
  1910. eleSugList.children[i].classList.add("stsh_suggestion_border_approved");
  1911. }
  1912. else if (eleSugList.children[i].querySelector(".suggestion_status_declined"))
  1913. {
  1914. eleSugList.children[i].classList.add("stsh_suggestion_border_declined");
  1915. }
  1916. else
  1917. {
  1918. eleSugList.children[i].classList.add("stsh_suggestion_border_pending");
  1919. }
  1920. }
  1921. }
  1922. }
  1923. var eleSugHistory = document.querySelector(".suggestions_list:nth-child(5)");
  1924. if (eleSugHistory)
  1925. {
  1926. eleSugHistory.classList.add("stsh_suggestion_list_history");
  1927. }
  1928. var elesH1 = document.querySelectorAll(".progress > tbody:nth-child(2) > tr:nth-child(1) > td > h1:nth-child(1)");
  1929. if (elesH1.length >= 2)
  1930. {
  1931. eleHeaderOrg = elesH1[0].parentElement;
  1932. eleHeaderOrg.classList.add("stsh_header_org");
  1933. eleHeaderTrn = elesH1[1].parentElement;
  1934. eleHeaderTrn.classList.add("stsh_header_trn");
  1935. }
  1936. var eleSugListHeader = document.querySelector("#suggestionmain > div > h2");
  1937. if (eleSugListHeader)
  1938. {
  1939. eleSugListHeader.classList.add("stsh_suggestion_list_header");
  1940. }
  1941. }
  1942. // Remove horizon scroll
  1943. {
  1944. setTimeoutCustom(function()
  1945. {
  1946. var eleMain = document.querySelector("#suggestionmain");
  1947. if (eleMain)
  1948. {
  1949. if (eleMain.scrollWidth < 1000)
  1950. {
  1951. eleMain.classList.add("stsh_body_crop");
  1952. }
  1953. }
  1954. }, timingInit.removeHorizonScroll);
  1955. }
  1956. // Move region
  1957. {
  1958. if (eleTextTrn && eleTextTrn.classList.contains("stsh_text_trn_empty"))
  1959. {
  1960. var moveSuggestionBox = function()
  1961. {
  1962. var eleTextTrn = document.querySelector(".stsh_text_trn.stsh_text_trn_empty");
  1963. if (eleTextTrn)
  1964. {
  1965. eleTextTrn.innerHTML = "";
  1966. var eleTarget = document.querySelector("#suggestionmain > div:nth-child(4) > .lbAction");
  1967. if (eleTarget)
  1968. {
  1969. eleTextTrn.appendChild(eleTarget);
  1970. eleTextTrn.style.padding = "0px";
  1971. var textarea = document.querySelector("#suggestion_value_new");
  1972. if (textarea)
  1973. {
  1974. textarea.style.width = "98%";
  1975. textarea.style.marginLeft = "0px";
  1976. if (textarea.scrollHeight < 500)
  1977. {
  1978. textarea.style.height = (textarea.scrollHeight + 20) + "px";
  1979. }
  1980. else
  1981. {
  1982. textarea.style.height = "500px";
  1983. }
  1984. textarea.focus();
  1985. }
  1986. var eleTextOrg = document.querySelector(".stsh_text_org");
  1987. if (eleTextOrg)
  1988. {
  1989. eleTextOrg.style.display = "table-cell";
  1990. eleTextOrg.style.paddingTop = "6px";
  1991. }
  1992. }
  1993. }
  1994. }
  1995. var moveSuggestionList = function()
  1996. {
  1997. var eleTextTrn = document.querySelector(".stsh_text_trn.stsh_text_trn_empty");
  1998. if (eleTextTrn && eleTextTrn.textContent.trim() === "")
  1999. {
  2000. eleTextTrn.innerHTML = "";
  2001. var eleTarget = document.querySelector(".suggestion");
  2002. if (eleTarget)
  2003. {
  2004. eleTextTrn.appendChild(eleTarget);
  2005. eleTextTrn.style.padding = "0px";
  2006. }
  2007. }
  2008. }
  2009. var eleDiv = document.createElement("div");
  2010. eleDiv.classList.add("stsh_moveSuggestionContainer");
  2011. eleTextTrn.appendChild(eleDiv);
  2012. var eleMoveBox = document.createElement("input");
  2013. eleMoveBox.id = "stsh_moveSuggestionBox";
  2014. eleMoveBox.setAttribute("value", "Move Box Here");
  2015. eleMoveBox.setAttribute("type", "button");
  2016. eleDiv.appendChild(eleMoveBox);
  2017. eleMoveBox.addEventListener("click", function(e)
  2018. {
  2019. moveSuggestionBox();
  2020. });
  2021. if (document.querySelector(".suggestion"))
  2022. {
  2023. var eleMoveList = document.createElement("input");
  2024. eleMoveList.id = "stsh_moveSuggestionList";
  2025. eleMoveList.setAttribute("value", "Move Suggestion Here");
  2026. eleMoveList.setAttribute("type", "button");
  2027. eleDiv.appendChild(eleMoveList);
  2028. eleMoveList.addEventListener("click", function(e)
  2029. {
  2030. moveSuggestionList();
  2031. });
  2032. }
  2033. }
  2034. }
  2035. // Resize suggestion textarea
  2036. if (eleTextNew)
  2037. {
  2038. eleTextNew.style.width = "960px";
  2039. eleTextNew.style.height = "64px";
  2040. eleTextNew.style.marginLeft = "3px";
  2041. var resizeTextNew = function(eleTextNew)
  2042. {
  2043. eleTextNew.focus();
  2044. if (eleTextNew.scrollHeight < 500)
  2045. {
  2046. eleTextNew.style.height = (eleTextNew.scrollHeight + 20) + "px";
  2047. }
  2048. else
  2049. {
  2050. eleTextNew.style.height = "500px";
  2051. }
  2052. if (eleTextNew.scrollHeight > 200 && document.querySelector(".suggestion"))
  2053. {
  2054. eleTextNew.scrollIntoView();
  2055. }
  2056. };
  2057. if (isVisible())
  2058. {
  2059. resizeTextNew(eleTextNew);
  2060. }
  2061. else
  2062. {
  2063. // Fix size error when inactive
  2064. setTimeoutCustom(resizeTextNew, timingInit.resizeTextNew, eleTextNew);
  2065. }
  2066. }
  2067. // Add nav menu
  2068. {
  2069. /* // Unknown reason
  2070. var br = document.querySelector("form.lbAction:nth-child(2) > div:nth-child(2) > br:nth-child(1)");
  2071. if (br)
  2072. {
  2073. removeElement(br);
  2074. }
  2075. */
  2076. var key = "";
  2077. var eleNav = document.querySelector("div#suggestions_nav");
  2078. if (!eleNav)
  2079. {
  2080. // Add when error occured
  2081. eleNav = document.createElement("div");
  2082. eleNav.id = "suggestions_nav";
  2083. document.body && document.body.appendChild(eleNav);
  2084. }
  2085. if (eleNav)
  2086. {
  2087. var insert = "";
  2088. var insertSearch = "";
  2089. var insertView = "";
  2090. var spliter = "_";
  2091. var regApp = /[0-9]{4,}/;
  2092. var aKey = document.querySelector(".smallcopy > font:nth-child(2) > a:nth-child(1)");
  2093. if (aKey)
  2094. {
  2095. key = encodeURIComponent(aKey.textContent.trim());
  2096. if (key === "token-key")
  2097. {
  2098. aKey = document.querySelector(".smallcopy > a:nth-child(3)");
  2099. if (aKey)
  2100. {
  2101. key = encodeURIComponent(aKey.textContent.trim());
  2102. }
  2103. }
  2104. if (key !== "")
  2105. {
  2106. document.title = key + " - " + document.title;
  2107. if (key.split(spliter).length > 1)
  2108. {
  2109. if (key.indexOf("%23") === 0)
  2110. {
  2111. var firstSpliter = key.indexOf(spliter);
  2112. var keySharp = key.substring(0, firstSpliter);
  2113. insertSearch += '<a class="stsh_a_button" target="_blank" '
  2114. + ' href="/translate.php?keyonly=1&paginationrows=1000&search_input='
  2115. + keySharp + '">Hashtag</a>';
  2116. }
  2117. var lastSpliter = key.lastIndexOf(spliter);
  2118. var keyGroup = key.substring(0, lastSpliter);
  2119. insertSearch += '<a class="stsh_a_button" target="_blank" '
  2120. + ' href="/translate.php?keyonly=1&paginationrows=1000&search_input='
  2121. + keyGroup + '">Group</a>';
  2122. }
  2123. insertSearch += '<a class="stsh_a_button" target="_blank" '
  2124. + ' href="/translate.php?keyonly=1&search_input='
  2125. + key + '">Key</a>';
  2126. }
  2127. }
  2128. if (eleTextOrg)
  2129. {
  2130. var text = encodeURIComponent(eleTextOrg.textContent.trim())
  2131. .replace(/(%20|%09)/g,"+")
  2132. .replace(/'/g,"\\'")
  2133. .replace("%0A", "+")
  2134. .replace(/\++/g, "+")
  2135. .substr(0, 80);
  2136. if (text.length >= 80)
  2137. {
  2138. // Find last space
  2139. var last = text.lastIndexOf("+");
  2140. last = last < 0 ? 80 : last;
  2141. text = text.substr(0, last);
  2142. }
  2143. if (text.indexOf(". ") > 20)
  2144. {
  2145. // Find first .
  2146. text = text.substr(0, text.indexOf(". ") + 1);
  2147. }
  2148. if (text.indexOf("%5C") > 10)
  2149. {
  2150. // Find first \
  2151. text = text.substr(0, text.indexOf("%5C"));
  2152. }
  2153. /* // Unknown reason
  2154. if (eleTextSubmit)
  2155. {
  2156. var elePrev = eleTextSubmit.previousElementSibling;
  2157. if (!elePrev || elePrev.tagName !== "BR")
  2158. {
  2159. var eleNew = document.createElement("br");
  2160. insertBeforeElement(eleNew, eleTextSubmit);
  2161. }
  2162. }
  2163. */
  2164. if (text !== "")
  2165. {
  2166. insertSearch += '<a class="stsh_a_button" target="_blank" '
  2167. + ' href="/translate.php?keyonly=2&paginationrows=1000&search_input='
  2168. + text + '">String</a>';
  2169. if (eleTextSubmitNext)
  2170. {
  2171. var eleForm = eleTextSubmitNext.parentElement.parentElement;
  2172. if (eleForm.tagName === "FORM")
  2173. {
  2174. addKeyCtrlShiftEnter(eleForm, eleTextSubmitNext);
  2175. }
  2176. }
  2177. else
  2178. {
  2179. if (eleTextSubmit)
  2180. {
  2181. eleTextSubmitNext = document.createElement("input");
  2182. eleTextSubmitNext.id = "stsh_text_submit_next";
  2183. eleTextSubmitNext.classList.add("stsh_text_submit_right");
  2184. eleTextSubmitNext.setAttribute("type", "submit");
  2185. eleTextSubmitNext.setAttribute("value", "Next");
  2186. eleTextSubmitNext.setAttribute("name", "submitandnext");
  2187. insertAfterElement(eleTextSubmitNext, eleTextSubmit);
  2188. eleTextSubmitNext.addEventListener("click", function(ev)
  2189. {
  2190. var textOrg = "";
  2191. var textTrn = "";
  2192. var textCur = "";
  2193. var eleTextOrg = document.querySelector(".stsh_text_org");
  2194. if (eleTextOrg)
  2195. {
  2196. textOrg = trimSpace(eleTextOrg.textContent);
  2197. }
  2198. var eleTextTrn = document.querySelector(".stsh_text_trn:not(.stsh_text_trn_empty)");
  2199. if (eleTextTrn)
  2200. {
  2201. textTrn = trimSpace(eleTextTrn.textContent);
  2202. }
  2203. var eleTextCur = document.querySelector("#suggestion_value_new");
  2204. if (eleTextCur)
  2205. {
  2206. textCur = trimSpace(eleTextCur.value);
  2207. }
  2208. if (textCur === "" || textOrg === textCur || textTrn === textCur)
  2209. {
  2210. ev.preventDefault();
  2211. var eleTextSubmit = document.querySelector(".stsh_text_submit");
  2212. if (eleTextSubmit)
  2213. {
  2214. eleTextSubmit.click();
  2215. }
  2216. }
  2217. });
  2218. var eleForm = eleTextSubmit.parentElement.parentElement;
  2219. if (eleForm.tagName === "FORM")
  2220. {
  2221. addKeyCtrlShiftEnter(eleForm, eleTextSubmitNext);
  2222. }
  2223. }
  2224. }
  2225. if (eleTextSubmitNext)
  2226. {
  2227. var canNext = !!(document.querySelector(".stsh_nav_next:not(:disabled)"));
  2228. if (!canNext)
  2229. {
  2230. // Display as disabled
  2231. eleTextSubmitNext.classList.add("stsh_grey");
  2232. eleTextSubmitNext.classList.add("stsh_cursor_default");
  2233. }
  2234. }
  2235. }
  2236. else
  2237. {
  2238. // (text === "")
  2239. if (eleTextNew && eleTextSubmit && !eleTextSubmit.classList.contains("stsh_text_resubmit"))
  2240. {
  2241. var eleNew = document.createElement("input");
  2242. eleNew.id = "stsh_text_submit_space";
  2243. eleNew.classList.add("stsh_text_submit_right");
  2244. eleNew.setAttribute("type", "button");
  2245. //eleNew.setAttribute("value", "Submit Space (Alt+0160)");
  2246. eleNew.setAttribute("value", "Submit Empty (2 Newlines)");
  2247. insertAfterElement(eleNew, eleTextSubmit);
  2248. eleNew.addEventListener("click", function(ev)
  2249. {
  2250. var eleTextNew = document.querySelector("#suggestion_value_new");
  2251. if (eleTextNew)
  2252. {
  2253. // Space char
  2254. //eleTextNew.value = String.fromCharCode(160);
  2255. // Two newlines result in one newline when export
  2256. eleTextNew.value = "\n\n";
  2257. eleTextNew.focus();
  2258. ev.preventDefault();
  2259. var eleTextSubmit = document.querySelector(".stsh_text_submit");
  2260. if (eleTextSubmit)
  2261. {
  2262. eleTextSubmit.click();
  2263. }
  2264. }
  2265. });
  2266. }
  2267. }
  2268. }
  2269. var qBranch = getQueryByName("branch");
  2270. if (qBranch.indexOf("games") !== 0)
  2271. {
  2272. var app = regApp.exec(key.replace("%23", ""));
  2273. if (app && key.indexOf("faq") < 0 && key.indexOf("glossary") < 0)
  2274. {
  2275. if (key.indexOf("SharedFiles_App_") === 0)
  2276. {
  2277. insertView += '<a class="stsh_a_button" target="_blank" '
  2278. + ' href="https://steamcommunity.com/workshop/browse?appid='
  2279. + app + '">Workshop</a>';
  2280. }
  2281. insertView += '<a class="stsh_a_button" target="_blank" '
  2282. + ' href="https://steamcommunity.com/app/'
  2283. + app + '">Community</a>'
  2284. insertView += '<a class="stsh_a_button" target="_blank" '
  2285. + ' href="https://store.steampowered.com/app/'
  2286. + app + '">App</a>';
  2287. }
  2288. }
  2289. if (insertSearch)
  2290. {
  2291. insert += ' <br> &nbsp; Search: <div class="stsh_nav_group"> ' + insertSearch + " </div>";
  2292. }
  2293. if (insertView)
  2294. {
  2295. insert += ' <br> &nbsp; View: <div class="stsh_nav_group"> ' + insertView + " </div>";
  2296. }
  2297. var insertBefore =
  2298. ' \
  2299. <input id="stsh_refresh" value="Refresh" onclick="return false;" type="button"> \
  2300. <a class="stsh_a_button" target="_blank" href="' + url + '">Frame</a> \
  2301. ';
  2302.  
  2303. var innerNew = eleNav.innerHTML
  2304. .replace('<input value="Previous', '&nbsp;&nbsp;<input value="Prev')
  2305. .replace('<input value="Close X', '&nbsp;&nbsp;<input value="Close (ESC)');
  2306. eleNav.innerHTML = insertBefore + innerNew + insert + " <br> ";
  2307. var eleRefresh = document.querySelector("#stsh_refresh");
  2308. if (eleRefresh)
  2309. {
  2310. eleRefresh.addEventListener("click", function()
  2311. {
  2312. reload();
  2313. });
  2314. }
  2315. }
  2316. }
  2317. // Regroup glossary
  2318. // Auto replace matched string
  2319. {
  2320. setTimeoutCustom(function()
  2321. {
  2322. var br = "<br>";
  2323. var brSpace = " <br> ";
  2324. var tag = "<a";
  2325. var colon = ">: ";
  2326. var comma = ",";
  2327. var bracket = " (";
  2328. var isEdit = false;
  2329. var p = null;
  2330. var aGls = document.querySelectorAll("a[href='glossary.php']");
  2331. for (var i = 0; i < aGls.length; i++)
  2332. {
  2333. if (aGls[i].textContent.trim() === "GLOSSARY FEATURE")
  2334. {
  2335. p = aGls[i].parentElement;
  2336. break;
  2337. }
  2338. }
  2339. if (p)
  2340. {
  2341. var glosOuters = [];
  2342. var glosInnerStart = 0;
  2343. var countGl = 0;
  2344. var glossaries = p.innerHTML.split(br);
  2345. if (glossaries.length > 2)
  2346. {
  2347. glosOuters = [p];
  2348. glosInnerStart = 2;
  2349. }
  2350. else
  2351. {
  2352. glosOuters = p.nextSibling.querySelectorAll("td");
  2353. glosInnerStart = 0;
  2354. }
  2355. var rgxKey = />[^><]+</;
  2356. var rgxKeyClean = /[><]+/g;
  2357. var rgxKeyPunct = /[\(\)\[\]\:\!]/g;
  2358. var rgxContentClean = /<[^<]*>/g;
  2359. var textNew = "";
  2360. var textEng = "";
  2361. var textNewFull = "";
  2362. var textEngFull = "";
  2363. var isTextReplaced = false;
  2364. var isOutdated = false;
  2365.  
  2366. var eleBtnResummit = document.querySelector(".stsh_text_submit[value^='RESUBMIT']");
  2367. if (eleBtnResummit)
  2368. {
  2369. isTextReplaced = true;
  2370. }
  2371. else
  2372. {
  2373. if (eleTextNew)
  2374. {
  2375. textNewFull = trimTab(eleTextNew.value.toLowerCase());
  2376. textNew = textNewFull.trim();
  2377. }
  2378. if (textNew === "" || textNew.length > 300)
  2379. {
  2380. // Not replace on empty and long strings
  2381. isTextReplaced = true;
  2382. }
  2383. }
  2384. if (!isTextReplaced)
  2385. {
  2386. var eleTrs = document.querySelectorAll(".progress tr");
  2387. isOutdated = (eleTrs.length >= 3);
  2388. if (isOutdated)
  2389. {
  2390. textEngFull = trimTab(eleTrs[eleTrs.length - 1].firstElementChild.textContent.toLowerCase());
  2391. textEng = textEngFull.trim();
  2392. }
  2393. }
  2394. for (var i = 0; i < glosOuters.length; i++)
  2395. {
  2396. var glosOuter = glosOuters[i];
  2397. var glosInners = glosOuter.innerHTML.split(br);
  2398. isEdit = false;
  2399. for (var j = glosInnerStart; j < glosInners.length; j++)
  2400. {
  2401. var glossary = glosInners[j].trim();
  2402. if (glossary.length > 0 && glossary.indexOf(tag) === 0)
  2403. {
  2404. var colonIndex = glossary.indexOf(colon);
  2405. var contentHead = glossary.substr(0, colonIndex + 3);
  2406. var contentAll = glossary.substr(colonIndex + 3);
  2407. var contentWords = contentAll.split(comma);
  2408. var contentFirst = contentWords[0].trim();
  2409. for (var k = 0; k < contentWords.length; k++)
  2410. {
  2411. var contentNew = contentWords[k].trim();
  2412. var contentSub = null;
  2413. var bracketPos = contentNew.indexOf(" (");
  2414. if (bracketPos > -1)
  2415. {
  2416. contentSub = contentNew.substr(bracketPos);
  2417. contentNew = contentNew.substr(0, bracketPos);
  2418. }
  2419. contentNew = " <span id='stsh_gls_" + countGl
  2420. + "' onclick='clickToSelect(this)'>"
  2421. + contentNew + "</span>";
  2422. //+ "<span style='color: white; cursor: pointer;'>^</span>";
  2423. if (contentSub)
  2424. {
  2425. contentNew += "<span "
  2426. + "onclick='clickToSelect(this.previousElementSibling)'>"
  2427. + contentSub + "</span>";
  2428. }
  2429. contentWords[k] = contentNew;
  2430. countGl++;
  2431. }
  2432. if (!isTextReplaced)
  2433. {
  2434. var keys = contentHead.match(rgxKey);
  2435. if (keys && keys.length > 0)
  2436. {
  2437. var key = keys[0].replace(rgxKeyClean, "").trim().toLowerCase();
  2438. var contentClean = contentFirst.replace(rgxContentClean, "");
  2439. var contentLower = contentClean.toLowerCase();
  2440. var textCur = "";
  2441. if (key === textNew.replace(rgxKeyPunct, ""))
  2442. {
  2443. textCur = textNewFull;
  2444. }
  2445. else if (key === textEng.replace(rgxKeyPunct, ""))
  2446. {
  2447. textCur = textEngFull;
  2448. }
  2449. if (textCur !== "" && key !== contentLower)
  2450. {
  2451. if (eleTextNew)
  2452. {
  2453. var rgxReplace = new RegExp(key, "i");
  2454. eleTextNew.value = textCur.replace(rgxReplace, contentClean);
  2455. isTextReplaced = true;
  2456. }
  2457. }
  2458. }
  2459. }
  2460. glosInners[j] = contentHead + contentWords.join(comma);
  2461. isEdit = true;
  2462. }
  2463. }
  2464. if (isEdit && false)
  2465. {
  2466. // old feature
  2467. glosOuter.innerHTML = glosInners.join(brSpace);
  2468. }
  2469. }
  2470. }
  2471. }, timingInit.improveGlossary);
  2472. }
  2473. // Insert clicked word in last textarea
  2474. {
  2475. var eleTextLast = null;
  2476. setTimeoutCustom(function()
  2477. {
  2478. if (document.activeElement && document.activeElement.tagName === "TEXTAREA")
  2479. {
  2480. eleTextLast = document.activeElement;
  2481. }
  2482. var elesText = document.querySelectorAll
  2483. (" \
  2484. #suggestion_value_new \
  2485. , .stsh_text_addComment \
  2486. , #add_to_discussion \
  2487. , textarea[name^='autoreplace'] \
  2488. , .stsh_autoReplace_text \
  2489. ");
  2490. for (var i = 0; i < elesText.length; i++)
  2491. {
  2492. elesText[i].addEventListener('focus', function(ev)
  2493. {
  2494. eleTextLast = ev.target;
  2495. });
  2496. }
  2497. }, timingInit.bindLastText);
  2498. setTimeoutCustom(function()
  2499. {
  2500. var elesInsert = document.querySelectorAll(".insertword");
  2501. for (var i = 0; i < elesInsert.length; i++)
  2502. {
  2503. removeAllEventListeners(elesInsert[i]);
  2504. }
  2505. var insertAtCaret = function(txtarea, text)
  2506. {
  2507. // Edit from STS
  2508. var scrollPos = txtarea.scrollTop;
  2509. var strPos = 0;
  2510. var strLength = 0;
  2511. var br = ((txtarea.selectionStart || txtarea.selectionStart === 0) ? "ff" : (document.selection ? "ie" : false));
  2512. if (br === "ie")
  2513. {
  2514. txtarea.focus();
  2515. var range = document.selection.createRange();
  2516. range.moveStart('character', -txtarea.value.length);
  2517. strPos = range.text.length;
  2518. }
  2519. else if (br === "ff")
  2520. {
  2521. strPos = txtarea.selectionStart;
  2522. strLength = txtarea.selectionEnd - txtarea.selectionStart;
  2523. }
  2524. var front = (txtarea.value).substring(0, strPos);
  2525. var back = (txtarea.value).substring(strPos + strLength, txtarea.value.length);
  2526. txtarea.value = front + text + back;
  2527. strPos = strPos + text.length;
  2528. if (br === "ie")
  2529. {
  2530. txtarea.focus();
  2531. var range = document.selection.createRange();
  2532. range.moveStart('character', -txtarea.value.length);
  2533. range.moveStart('character', strPos);
  2534. range.moveEnd('character', 0);
  2535. range.select();
  2536. }
  2537. else if (br === "ff")
  2538. {
  2539. txtarea.selectionStart = strPos;
  2540. txtarea.selectionEnd = strPos;
  2541. txtarea.focus();
  2542. }
  2543. txtarea.scrollTop = scrollPos;
  2544. }
  2545. elesInsert = document.querySelectorAll(".insertword");
  2546. for (var i = 0; i < elesInsert.length; i++)
  2547. {
  2548. //elesInsert[i].classList.add("stsh_unselectable");
  2549. elesInsert[i].addEventListener("click", function(ev)
  2550. {
  2551. if (eleTextLast)
  2552. {
  2553. insertAtCaret(eleTextLast , ev.target.textContent.trim());
  2554. }
  2555. });
  2556. }
  2557. }, timingInit.insertAtCaret);
  2558. }
  2559. // Restyle glossary
  2560. {
  2561. var eleP = null;
  2562. var elesA = document.querySelectorAll("a[href='glossary.php']");
  2563. for (var i = 0; i < elesA.length; i++)
  2564. {
  2565. if (elesA[i].textContent.trim() === "GLOSSARY FEATURE")
  2566. {
  2567. eleP = elesA[i].parentElement;
  2568. break;
  2569. }
  2570. }
  2571. if (eleP)
  2572. {
  2573. var nodeText = eleP.firstElementChild.nextSibling;
  2574. if (nodeText.nodeType === document.TEXT_NODE)
  2575. {
  2576. var ele = document.createElement("span");
  2577. ele.textContent = nodeText.textContent;
  2578. removeElement(nodeText);
  2579. insertAfterElement(ele, eleP.firstElementChild);
  2580. }
  2581. var eleHead;
  2582. if (eleP.nextElementSibling.tagName === "TABLE")
  2583. {
  2584. eleHead = eleP.nextElementSibling;
  2585. }
  2586. else
  2587. {
  2588. eleHead = eleP;
  2589. }
  2590. eleHead.classList.add("stsh_glossary_header");
  2591. var elesTerm = eleHead.querySelectorAll(
  2592. "a[href*='//translation.steampowered.com/translate.php?search_input=']");
  2593. for (var i = 0; i < elesTerm.length; i++)
  2594. {
  2595. elesTerm[i].classList.add("stsh_glossary_term");
  2596. // Clean glossary links
  2597. {
  2598. var href = elesTerm[i].href;
  2599. var hrefNew = href.replace("http://", "//")
  2600. .replace(/\?search_input=([^"])([^&]+)&keyonly=0&listfilter=0&listsort=0&liststatus=0&paginationrows=50/i
  2601. , '\?keyonly=2&paginationrows=1000&search_input="$1$2"');
  2602. elesTerm[i].href = hrefNew;
  2603. }
  2604. }
  2605. {
  2606. var eleSpan = null;
  2607. if (eleHead.tagName === "TABLE")
  2608. {
  2609. eleSpan = eleHead.previousElementSibling.querySelector("span");
  2610. }
  2611. else
  2612. {
  2613. eleSpan = eleHead.querySelector("span");
  2614. }
  2615. eleSpan.textContent = eleSpan.textContent
  2616. .replace(" (click to copy to top)", "");
  2617. eleSpan.title = "Click to copy to suggestion or comment";
  2618. eleSpan.classList.add("stsh_cursor_help");
  2619. eleSpan.classList.add("stsh_glossary_help");
  2620. }
  2621. }
  2622. var eleTd = document.querySelector(".stsh_glossary_header \
  2623. > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(4)");
  2624. if (eleTd)
  2625. {
  2626. if (eleTd.childElementCount === 0)
  2627. {
  2628. removeElement(eleTd);
  2629. }
  2630. }
  2631. }
  2632. // Restyle same token
  2633. {
  2634. /* // Unknown reason
  2635. var p = document.querySelector("#suggestionmain > div:nth-child(5) > p:nth-child(4)");
  2636. if (p)
  2637. {
  2638. for (var i = 0; i < p.childNodes.length; i++)
  2639. {
  2640. var child = p.childNodes[i];
  2641. if (child.nodeName === "#text")
  2642. {
  2643. child.nodeValue = child.nodeValue.trim();
  2644. }
  2645. }
  2646. }
  2647. */
  2648. var widthMax = 0;
  2649. var elesFile = document.querySelectorAll(
  2650. "#suggestionmain > div > p > a[href*='/translate.php?keyonly=1&search_input=']");
  2651. for (var i = 0; i < elesFile.length; i++)
  2652. {
  2653. elesFile[i].classList.add("stsh_sametoken_file");
  2654. var width = elesFile[i].offsetWidth;
  2655. if (width > widthMax)
  2656. {
  2657. widthMax = width;
  2658. }
  2659. }
  2660. for (var i = 0; i < elesFile.length; i++)
  2661. {
  2662. elesFile[i].style.minWidth = (widthMax + 4) + "px";
  2663. }
  2664. var eleHeader = null;
  2665. if (elesFile.length > 0)
  2666. {
  2667. eleHeader = elesFile[0].parentElement;
  2668. }
  2669. if (eleHeader)
  2670. {
  2671. eleHeader.classList.add("stsh_sametoken_header");
  2672. eleHeader.innerHTML = eleHeader.innerHTML.replace(
  2673. "&lt;--- currently in view above",
  2674. '<span class="stsh_blue_light stsh_sametoken_current">&lt;--- currently in view above</span>');
  2675. }
  2676. }
  2677. // Auto link http
  2678. // Format comment
  2679. // Show images
  2680. {
  2681. var countSugStatus = document.querySelectorAll(
  2682. ".suggestions_list span[class^='suggestion_status_']").length;
  2683. var rgxUrl = /https?:[^ "]+/ig;
  2684. var rgxHostUrl = /^https?:\/\/translation\.steampowered\.com\//i;
  2685. var hostReplace = "/";
  2686. var eleComments = document.querySelectorAll
  2687. (" \
  2688. .suggestion_signature > i:nth-child(3) \
  2689. , .suggestion_signature div:nth-child(1) > i:nth-child(4) \
  2690. , .suggestion_signature div:nth-child(1) > i:nth-child(6) \
  2691. , *[class^='row'] > td:nth-child(2) \
  2692. ");
  2693. for (var i = 0; i < eleComments.length; i++)
  2694. {
  2695. var comment = eleComments[i].innerHTML + " ";
  2696. if (comment.indexOf("<a") === -1)
  2697. {
  2698. var commentUrls = comment.match(rgxUrl) || [];
  2699. for (var j = 0; j < commentUrls.length; j++)
  2700. {
  2701. var urlDecode = commentUrls[j];
  2702. try
  2703. {
  2704. urlDecode = decodeURIComponent(commentUrls[j])
  2705. .replace(/#/g, "%23").replace(/&amp;/g, "&");
  2706. //console.log(urlDecode);
  2707. if (countSugStatus === 0 && rgxHostUrl.test(urlDecode))
  2708. {
  2709. var query = getQueryByName("search_input", urlDecode);
  2710. if (query !== "")
  2711. {
  2712. urlDecode = query;
  2713. }
  2714. else
  2715. {
  2716. urlDecode = urlDecode.replace(rgxHostUrl, hostReplace);
  2717. }
  2718. }
  2719. }
  2720. catch (ex)
  2721. {
  2722. console.error("FormatComment", ex.message);
  2723. }
  2724. var commentUrl = commentUrls[j] + " ";
  2725. comment = comment.replace(commentUrl, "<a target='_blank' href='"
  2726. + commentUrls[j] + "' >" + urlDecode + "</a> ");
  2727. }
  2728. }
  2729. comment = comment.trim();
  2730. var commentHead = "";
  2731. var commentFoot = "";
  2732. if (comment.indexOf("Comment:") === 0)
  2733. {
  2734. eleComments[i].classList.add("stsh_text_comment_header");
  2735. comment = comment.substr(9);
  2736. commentHead = "Comment: <span class='stsh_text_comment'>";
  2737. commentFoot = "</span>";
  2738. }
  2739. else
  2740. {
  2741. var indexHead = comment.indexOf(":</font>");
  2742. if (indexHead > -1)
  2743. {
  2744. commentHead = comment.substr(0, indexHead + 8);
  2745. comment = comment.substr(indexHead + 8);
  2746. }
  2747. }
  2748. comment = comment
  2749. .replace(/([ \n])([\/~]{1,})([ \n])/g, "$1<span class='stsh_white stsh_pad'>$2</span>$3")
  2750. //.replace(/\/ /g, "<span class='stsh_white stsh_pad'>/</span> ")
  2751. //.replace(/ \//g, " <span class='stsh_white stsh_pad'>/</span>")
  2752. .replace(/(\-+)\&gt\;/g, "<span class='stsh_white stsh_pad'>$1&gt;</span>")
  2753. .replace(/ &gt; /g, " <span class='stsh_white stsh_pad'>&gt;</span> ")
  2754. .replace(/(\-{2,})([^\&])/g, "<span class='stsh_white stsh_pad'>$1</span>$2")
  2755. //.replace(/([^<>,]+)(\, +)([^<>,]+)/g, "$1<span class='stsh_white stsh_pad'>$2</span>$3")
  2756. //.replace(/([^<>,]+)(\, +)([^<>,]+)/g, "$1<span class='stsh_white stsh_pad'>$2</span>$3")
  2757. .replace(/\| /g, "<span class='stsh_white stsh_pad'>| </span>")
  2758. .replace(/ \* /g, " <span class='stsh_white stsh_pad'>*</span> ")
  2759. .replace(/ \.\.\.([ \n])/g, " <span class='stsh_white stsh_pad'>...</span>$1")
  2760. .replace(/\n/g, "<br>")
  2761. .replace(/Past application on (.{20})/g,
  2762. "<span class='stsh_white stsh_pad'><br>Past application on $1</span>");
  2763. eleComments[i].innerHTML = commentHead + comment + commentFoot;
  2764. var eleAs = eleComments[i].querySelectorAll("a");
  2765. for (var j = 0; j < eleAs.length; j++)
  2766. {
  2767. var href = eleAs[j].getAttribute("href");
  2768. if (href.indexOf("#") > -1)
  2769. {
  2770. eleAs[j].setAttribute("href", href.replace(/\#/g,"%23"));
  2771. }
  2772. }
  2773. //if (comment.indexOf("Comment:") !== 0)
  2774. {
  2775. // Discussion comment
  2776. var rgxImg = /(\.(jpg|png|gif)|\/ugc\/)/i;
  2777. var rgxImgur = /^https?:\/\/imgur\.com\/([a-z0-9]+)\/?$/i;
  2778. var rgxLongUrl = /^https?\:\/\/translation\.steampowered\.com\/translate\.php\?search_input\=/i;
  2779. var elesA = eleComments[i].querySelectorAll("a");
  2780. for (var j = 0; j < elesA.length; j++)
  2781. {
  2782. var href = elesA[j].getAttribute("href");
  2783. if (rgxImgur.test(href))
  2784. {
  2785. href = href.replace(rgxImgur, "https://i.imgur.com/$1.png");
  2786. }
  2787. if (rgxImg.test(href))
  2788. {
  2789. if (elesA[j].querySelectorAll("img").length === 0)
  2790. {
  2791. var ele = document.createElement("img");
  2792. ele.classList.add("stsh_comment_img");
  2793. ele.setAttribute("src", href);
  2794. ele.setAttribute("title", href);
  2795. ele.dataset.modeNext = "unmin";
  2796. insertAfterElement(ele, elesA[j]);
  2797. if (ele.naturalWidth === 0 || ele.naturalWidth > 400 || ele.naturalHeight > 225)
  2798. {
  2799. ele.classList.add("stsh_comment_img_zoom");
  2800. ele.addEventListener("click", function(ev)
  2801. {
  2802. var eleTarget = ev.target;
  2803. var mode = "min";
  2804. if (eleTarget.dataset.modeNext === "min")
  2805. {
  2806. mode = "min";
  2807. eleTarget.dataset.modeNext = "unmin";
  2808. }
  2809. else
  2810. {
  2811. mode = "unmin";
  2812. eleTarget.dataset.modeNext = "min";
  2813. }
  2814. if (eleTarget.naturalWidth < 400 && eleTarget.naturalHeight < 225)
  2815. {
  2816. eleTarget.classList.remove("stsh_comment_img_zoom");
  2817. }
  2818. var isHorizontal = eleTarget.naturalWidth > eleTarget.naturalHeight;
  2819. if (isHorizontal)
  2820. {
  2821. eleTarget.style.maxHeight = "none";
  2822. if (mode === "unmin")
  2823. {
  2824. eleTarget.style.minWidth = eleTarget.naturalWidth < 850
  2825. ? eleTarget.naturalWidth + "px" : "850px";
  2826. }
  2827. else
  2828. {
  2829. eleTarget.style.minWidth = eleTarget.naturalWidth < 400
  2830. ? eleTarget.naturalWidth + "px" : "400px";
  2831. }
  2832. }
  2833. else
  2834. {
  2835. eleTarget.style.maxWidth = "none";
  2836. if (mode === "unmin")
  2837. {
  2838. eleTarget.style.minHeight = eleTarget.naturalHeight < 850
  2839. ? eleTarget.naturalHeight + "px" : "850px";
  2840. }
  2841. else
  2842. {
  2843. eleTarget.style.minHeight = eleTarget.naturalHeight < 225
  2844. ? eleTarget.naturalHeight + "px" : "225px";
  2845. }
  2846. }
  2847. });
  2848. }
  2849. }
  2850. }
  2851. else
  2852. {
  2853. var content = elesA[j].textContent;
  2854. if (rgxLongUrl.test(content))
  2855. {
  2856. //console.log(elesA[j]);
  2857. if (!elesA[j].parentElement.parentElement.parentElement
  2858. .querySelector(".suggestion_signature .lbAction[name^='mymodcomment']"))
  2859. {
  2860. elesA[j].textContent = content.replace(rgxLongUrl, "").replace(/\+/g, " ");
  2861. }
  2862. }
  2863. }
  2864. }
  2865. }
  2866. }
  2867. }
  2868. // Add space between comment and button
  2869. {
  2870. var elesAction = document.querySelectorAll(".stsh_action_remove, .stsh_action_edit");
  2871. for (var i = 0; i < elesAction.length; i++)
  2872. {
  2873. if (elesAction[i].previousElementSibling
  2874. && elesAction[i].previousElementSibling.previousElementSibling
  2875. && elesAction[i].previousElementSibling.previousElementSibling
  2876. .classList.contains("stsh_text_comment_header"))
  2877. {
  2878. insertBeforeElement(document.createElement("br"), elesAction[i]);
  2879. }
  2880. }
  2881. }
  2882. // Restyle token info
  2883. {
  2884. var divIntro = document.querySelector("#suggestionmain > div.smallcopy");
  2885. if (divIntro)
  2886. {
  2887. var qBranch = getQueryByName("branch");
  2888. var htmlEdit = "You are editing";
  2889. var htmlEditReplace = "";
  2890. var htmlToken = "Token <";
  2891. var htmlTokenReplace = "Token: <";
  2892. var htmlToken2 = "token-key";
  2893. var htmlToken2Replace = "Token";
  2894. var htmlLiveLinkMoved =
  2895. '\
  2896. <font style="color:red;">This FAQ likely does not exist anymore!</font>\
  2897. The generated <a href="https://support.steampowered.com/kb_article.php?ref="\
  2898. target="_blank">live link</a> seems dead or is redirecting.\
  2899. ';
  2900. var htmlLiveLinkMovedReplace =
  2901. '\
  2902. <font class="stsh_red stsh_cursor_help"\
  2903. title="The generated live link seems dead or is redirecting.">\
  2904. This FAQ likely does not exist anymore!</font>\
  2905. ';
  2906. var htmlLiveLinkMovedWithLiveLink =
  2907. '\
  2908. <font style="color:red;">This FAQ likely does not exist anymore!</font> The generated \
  2909. <a href="https://support.steampowered.com/kb_article.php?ref=\
  2910. ';
  2911. var htmlLiveLinkMovedWithLiveLinkReplace =
  2912. '<a href="https://support.steampowered.com/kb_article.php?ref=';
  2913. var htmlLiveLinkMovedWithLiveLink2 =
  2914. '" target="_blank">live link</a> seems dead or is redirecting.';
  2915. var htmlLiveLinkMovedWithLiveLink2Replace =
  2916. '\
  2917. " target="_blank">Live link</a> - \
  2918. <font class="stsh_red stsh_cursor_help"\
  2919. title="The generated live link seems dead or is redirecting.">\
  2920. This FAQ likely does not exist anymore!</font>';
  2921. var htmlLiveLink = 'target="_blank">Live link';
  2922. var htmlLiveLinkReplace = 'target="_blank">Live link'; // Change in condition
  2923. var htmlFile = " of <";
  2924. var htmlFileReplace =
  2925. ' <br>File: <font class="stsh_info_file stsh_blue" onclick="clickToSelect(this)">' + qBranch + '</font> >> <';
  2926. var htmlFrom = "<br>Added on <";
  2927. var htmlFromReplace = " &nbsp;&nbsp;Added: <";
  2928. var htmlUpdated = ">. Updated on <";
  2929. var htmlUpdatedReplace = "> &nbsp;&nbsp;Updated: <";
  2930. var htmlUpdated2 = "<br> Updated on <";
  2931. var htmlUpdated2Replace = " &nbsp;&nbsp;Updated: <";
  2932. var htmlSugg = 'You have <font style="';
  2933. var htmlSuggReplace =
  2934. 'You have <font title="Enter and submit new suggestions below. Do not alter HTML tags or variables." class="stsh_cursor_help" style="';
  2935. var htmlIntro =
  2936. "Enter and submit new suggestions below. Do not alter HTML tags or variables.";
  2937. var htmlIntroReplace =
  2938. ' \
  2939. &nbsp;&nbsp;\
  2940. <a href="mailto:translationserver@valvesoftware.com" \
  2941. title="Please report token issues by posting a TOKEN DISCUSSION \r\nor email to translationserver@valvesoftware.com" \
  2942. class="stsh_cursor_help">\
  2943. <font class="stsh_white">Report Tokens</font></a>\
  2944. ';
  2945. var htmlContact =
  2946. '\
  2947. <br>Please report token issues by posting a <font style="color:#a4b23c;">TOKEN DISCUSSION</font> tagged\
  2948. <input style="border:none; color:#FFFFFF; background-color:#111111; cursor:pointer;"\
  2949. onclick="tosts(\'truncated\')" value="[sts_admin][truncated]" type="button">or\
  2950. <input style="border:none; color:#FFFFFF; background-color:#111111; cursor:pointer;"\
  2951. onclick="tosts(\'typo\');" value="[sts_admin][typo]" type="button">or\
  2952. <input style="border:none; color:#FFFFFF; background-color:#111111; cursor:pointer;"\
  2953. onclick="tosts(\'unlockpls\')" value="[sts_admin][unlockpls]" type="button">or by \
  2954. <a href="mailto:translationserver@valvesoftware.com">email</a>.\
  2955. ';
  2956. var htmlContactReplace = '';
  2957. var htmlContact2 =
  2958. '\
  2959. <br>Please report token issues by posting a <font style="color:#a4b23c;">TOKEN DISCUSSION</font> tagged\
  2960. <input style="border:none; color:#FFFFFF; background-color:#111111; cursor:pointer;" type="button"\
  2961. onclick="tosts(\'truncated\')" value="[sts_admin][truncated]">or\
  2962. <input style="border:none; color:#FFFFFF; background-color:#111111; cursor:pointer;" type="button"\
  2963. onclick="tosts(\'typo\');" value="[sts_admin][typo]">or\
  2964. <input style="border:none; color:#FFFFFF; background-color:#111111; cursor:pointer;" type="button"\
  2965. onclick="tosts(\'unlockpls\')" value="[sts_admin][unlockpls]">or by \
  2966. <a href="mailto:translationserver@valvesoftware.com">email</a>.\
  2967. ';
  2968. var htmlContact2Replace = '';
  2969. var rgxTestEmail =
  2970. /<br><font style="color:#a4b23c;">This is part of email message .+ - you can test it by following this link:<\/font> /i;
  2971. var htmlTestEmailReplace = '';
  2972. var rgxTestEmail2 =
  2973. /<a href="test_email\.php\?filename=.+\&amp;lang=[a-z]+" target="_blank">Test<\/a>/i;
  2974. var htmlTestEmail2Replace = '';
  2975. var htmlsTestEmail = rgxTestEmail.exec(divIntro.innerHTML);
  2976. if (htmlsTestEmail)
  2977. {
  2978. var htmlTestEmail = htmlsTestEmail[0]
  2979. .replace('<br><font style="color:#a4b23c;">This is part of email message ', "")
  2980. .replace(' - you can test it by following this link:</font> ', "");
  2981. var htmlTestEmail2 = "";
  2982. var htmlsTestEmail2 = rgxTestEmail2.exec(divIntro.innerHTML);
  2983. if (htmlsTestEmail2)
  2984. {
  2985. htmlTestEmail2 = htmlsTestEmail2[0].replace('<a href="', "")
  2986. .replace('" target="_blank">Test</a>', "");
  2987. }
  2988. htmlIntroReplace += ' &nbsp;&nbsp;Test: <a href="' + htmlTestEmail2
  2989. + '" title="You can test email by following this link." target="_blank">'
  2990. + htmlTestEmail + '</a>';
  2991. }
  2992. if (key !== "")
  2993. {
  2994. htmlIntroReplace +=
  2995. ' \
  2996. <br>Share: \
  2997. <font class="stsh_token_share stsh_green stsh_truncate" onclick="clickToSelect(this)">\
  2998. https://translation.steampowered.com/translate.php?search_input=' + key + '\
  2999. </font> <br>\
  3000. ';
  3001. }
  3002. var urlLiveLink = "https://support.steampowered.com/kb_article.php?ref=";
  3003. var eleLiveLink = divIntro.querySelector("a[href^='" + urlLiveLink + "']");
  3004. if (eleLiveLink)
  3005. {
  3006. htmlLiveLinkReplace = 'target="_blank" title="Live link">'
  3007. + eleLiveLink.getAttribute("href").replace(urlLiveLink, "");
  3008. }
  3009. var isComplete = (divIntro.innerHTML.indexOf(htmlContact) > -1);
  3010. divIntro.innerHTML = divIntro.innerHTML
  3011. .replace(htmlEdit, htmlEditReplace)
  3012. .replace(htmlToken, htmlTokenReplace)
  3013. .replace(htmlToken2, htmlToken2Replace)
  3014. .replace(htmlLiveLinkMoved, htmlLiveLinkMovedReplace)
  3015. .replace(htmlLiveLinkMovedWithLiveLink, htmlLiveLinkMovedWithLiveLinkReplace)
  3016. .replace(htmlLiveLinkMovedWithLiveLink2, htmlLiveLinkMovedWithLiveLink2Replace)
  3017. .replace(htmlLiveLink, htmlLiveLinkReplace)
  3018. .replace(htmlFile, htmlFileReplace)
  3019. .replace(htmlFrom, htmlFromReplace)
  3020. .replace(htmlUpdated, htmlUpdatedReplace)
  3021. .replace(htmlUpdated2, htmlUpdated2Replace)
  3022. .replace(htmlSugg, htmlSuggReplace)
  3023. .replace(htmlIntro, htmlIntroReplace)
  3024. .replace(htmlContact, htmlContactReplace)
  3025. .replace(htmlContact2, htmlContact2Replace)
  3026. .replace(rgxTestEmail, htmlTestEmailReplace)
  3027. .replace(rgxTestEmail2, htmlTestEmail2Replace)
  3028. .trim();
  3029. var eleToken = document.querySelector("a[href^='Us_And_Them.php?']");
  3030. if (eleToken)
  3031. {
  3032. if (eleToken.textContent !== "Token")
  3033. {
  3034. eleToken.classList.add("stsh_token_name");
  3035. eleToken.classList.add("stsh_truncate");
  3036. }
  3037. }
  3038. if (!isComplete)
  3039. {
  3040. var stsh_introReplace_start = getTimeMs();
  3041. var stsh_introReplace_itv = setIntervalCustom(function(params)
  3042. {
  3043. var divIntro = params[0];
  3044. var htmlContact = params[1];
  3045. var htmlContactReplace = params[2];
  3046. var stsh_introReplace_isEnd = false;
  3047. var stsh_introReplace_cur = getTimeMs();
  3048. if (divIntro.innerHTML.indexOf(htmlContact) > -1)
  3049. {
  3050. divIntro.innerHTML = divIntro.innerHTML
  3051. .replace(htmlContact, htmlContactReplace);
  3052. stsh_introReplace_isEnd = true;
  3053. }
  3054. if (stsh_introReplace_isEnd || stsh_introReplace_cur - stsh_introReplace_start > 10000)
  3055. {
  3056. clearInterval(stsh_introReplace_itv);
  3057. }
  3058. }, 100, [divIntro, htmlContact, htmlContactReplace]);
  3059. }
  3060. }
  3061. }
  3062. // Restyle token discussion
  3063. {
  3064. var eleDiscuss = document.querySelector("a[name='tokendiscussion']");
  3065. if (eleDiscuss)
  3066. {
  3067. var htmlHeader = "TOKEN DISCUSSION (keep global comments English please!):";
  3068. var htmlHeaderReplace = "TOKEN DISCUSSION:";
  3069. var eleHeader = eleDiscuss.nextElementSibling;
  3070. if (eleHeader)
  3071. {
  3072. eleHeader.setAttribute("title", "Keep global comments English please!");
  3073. eleHeader.classList.add("stsh_cursor_help");
  3074. eleHeader.textContent = eleHeader.textContent.replace(htmlHeader, htmlHeaderReplace);
  3075. }
  3076. var eleParent = eleDiscuss.parentElement;
  3077. eleParent.classList.add("stsh_discussion_header");
  3078. if (eleParent.nextElementSibling)
  3079. {
  3080. eleParent.nextElementSibling.classList.add("stsh_discussion_section");
  3081. }
  3082. var elesInput = document.querySelectorAll("input[value='[stsadmin]']");
  3083. if (elesInput.length === 2)
  3084. {
  3085. removeElement(elesInput[1]);
  3086. }
  3087. var eleSpan = document.createElement("span");
  3088. eleSpan.innerHTML =
  3089. '\
  3090. <input style="border:none; color:#888888; background-color:#111111; cursor:pointer;"\
  3091. onclick="tosts(\'truncated\')" value="[sts_admin][truncated]" type="button">\
  3092. <input style="border:none; color:#888888; background-color:#111111; cursor:pointer;"\
  3093. onclick="tosts(\'typo\');" value="[sts_admin][typo]" type="button">\
  3094. <input style="border:none; color:#888888; background-color:#111111; cursor:pointer;"\
  3095. onclick="tosts(\'unlockpls\')" value="[sts_admin][unlockpls]" type="button">\
  3096. ';
  3097. eleParent.appendChild(eleSpan);
  3098. }
  3099. var eleAutoCopy = document.querySelector("#autocopy");
  3100. if (eleAutoCopy)
  3101. {
  3102. var eleAutoCopyHeader = eleAutoCopy.previousElementSibling;
  3103. eleAutoCopyHeader.classList.add("stsh_autoCopy_header");
  3104. eleAutoCopyHeader.firstElementChild.firstElementChild.textContent = "AUTO-REPLACEMENT";
  3105. eleAutoCopy.appendChild(document.createElement("br"));
  3106. }
  3107. var eleTableDiscuss = null;
  3108. var eleFriendDiscuss = document.querySelector(".friend_block_discussions");
  3109. if (eleFriendDiscuss)
  3110. {
  3111. if (eleAutoCopy)
  3112. {
  3113. insertBeforeElement(document.createElement("br"), eleAutoCopy.previousElementSibling);
  3114. }
  3115. eleTableDiscuss = eleFriendDiscuss.parentElement.parentElement.parentElement.parentElement;
  3116. if (eleTableDiscuss.tagName === "TABLE")
  3117. {
  3118. eleTableDiscuss.classList.add("stsh_discussion_table");
  3119. }
  3120. }
  3121. var elesDiscuss = document.querySelectorAll(".stsh_discussion");
  3122. for (var i = 0; i < elesDiscuss.length; i++)
  3123. {
  3124. var nodesChild = elesDiscuss[i].childNodes;
  3125. if (nodesChild.length > 2)
  3126. {
  3127. var arrNode = [];
  3128. for (var j = 3; j < nodesChild.length; j++)
  3129. {
  3130. arrNode.push(nodesChild[j]);
  3131. }
  3132. var eleDiv = document.createElement("div");
  3133. eleDiv.classList.add("stsh_discussion_text");
  3134. for (var j = 0; j < arrNode.length; j++)
  3135. {
  3136. eleDiv.appendChild(arrNode[j]);
  3137. }
  3138. elesDiscuss[i].appendChild(eleDiv);
  3139. eleDiv.classList.add("stsh_discussion_text_long");
  3140. }
  3141. }
  3142. }
  3143. // Decode URI in discussion
  3144. {
  3145. var elesA = document.querySelectorAll(".stsh_discussion_text > a[href*='%']");
  3146. for (var i = 0; i < elesA.length; i++)
  3147. {
  3148. if (elesA[i].childElementCount === 0)
  3149. {
  3150. try
  3151. {
  3152. elesA[i].textContent = decodeURIComponent(elesA[i].textContent);
  3153. }
  3154. catch (ex)
  3155. {
  3156. console.error("DecodeUriDiscussion", ex.message);
  3157. }
  3158. }
  3159. }
  3160. }
  3161. // Move up glossary
  3162. {
  3163. var moveUpGlossary = function()
  3164. {
  3165. var eleDiscuss = document.querySelector(".stsh_discussion_header");
  3166. if (eleDiscuss)
  3167. {
  3168. var eleGlosGroup = document.createElement("div");
  3169. eleGlosGroup.classList.add("stsh_glossary_group");
  3170. insertBeforeElement(eleGlosGroup, eleDiscuss);
  3171. var eleHead = document.querySelector(".stsh_glossary_header");
  3172. if (eleHead)
  3173. {
  3174. if (!(eleHead.childNodes.length === 5
  3175. && eleHead.childNodes[4].nodeType === document.TEXT_NODE
  3176. && eleHead.childNodes[4].nodeValue === "No results"))
  3177. {
  3178. eleGlosGroup.appendChild(document.createElement("br"));
  3179. if (eleHead.tagName === "TABLE")
  3180. {
  3181. eleGlosGroup.appendChild(eleHead.previousElementSibling);
  3182. }
  3183. eleGlosGroup.appendChild(eleHead);
  3184. }
  3185. }
  3186. }
  3187. }
  3188. var eleAutoCopy = document.querySelector(".stsh_autoCopy_header");
  3189. if (eleAutoCopy)
  3190. {
  3191. var eleHead = document.querySelector(".stsh_glossary_header");
  3192. if (eleHead)
  3193. {
  3194. insertAfterElement(eleAutoCopy.nextElementSibling, eleHead);
  3195. insertAfterElement(eleAutoCopy, eleHead);
  3196. insertAfterElement(document.createElement("br"), eleHead);
  3197. insertAfterElement(document.createElement("br"), eleAutoCopy.nextElementSibling);
  3198. }
  3199. }
  3200. var eleFriendDiscuss = document.querySelector(".friend_block_discussions");
  3201. if (!eleFriendDiscuss)
  3202. {
  3203. moveUpGlossary();
  3204. }
  3205. else
  3206. {
  3207. var eleHelp = document.querySelector(".stsh_glossary_help");
  3208. if (eleHelp)
  3209. {
  3210. var eleBtn = document.createElement("input");
  3211. eleBtn.classList.add("stsh_glossary_move");
  3212. eleBtn.setAttribute("type", "button");
  3213. eleBtn.setAttribute("onclick", "return false;");
  3214. eleBtn.value = "Move up";
  3215. eleBtn.title = "Glossary is displayed below when discussion is active. "
  3216. + "\nClick here to move glossary up.";
  3217. insertAfterElement(eleBtn, eleHelp);
  3218. eleBtn.addEventListener("click", function(ev)
  3219. {
  3220. var eleTarget = ev.target;
  3221. eleTarget.classList.add("stsh_hidden");
  3222. moveUpGlossary();
  3223. });
  3224. }
  3225. }
  3226. }
  3227. // Add shortcut keys
  3228. {
  3229. var elesForm = document.querySelectorAll(".lbAction");
  3230. for (var i = 0; i < elesForm.length; i++)
  3231. {
  3232. var eleForm = elesForm[i];
  3233. var eleSubmit = eleForm.querySelector("input[type='submit']:not([name='admindecision'])");
  3234. if (eleSubmit)
  3235. {
  3236. addKeyCtrlEnter(eleForm, eleSubmit);
  3237. }
  3238. }
  3239.  
  3240. var elesInputApplyNext = document.querySelectorAll(".stsh_action_apply_next:not([disabled])");
  3241. if (elesInputApplyNext.length > 0)
  3242. {
  3243. var eleBind = elesInputApplyNext[0];
  3244. eleBind.title = "Should remove all other suggestions then APPROVE and APPLY."
  3245.  
  3246. if (document.querySelectorAll(".stsh_action_remove").length === 1)
  3247. {
  3248. addKeyAlt(document, eleBind, ["KeyI", 73, "KeyD", 68], "I", 1); // I D
  3249. disableAfterClick(eleBind);
  3250. }
  3251. }
  3252. var elesInputApprove = document.querySelectorAll(".stsh_action_approve");
  3253. if (elesInputApprove.length > 0)
  3254. {
  3255. var eleBind = elesInputApprove[0];
  3256. addKeyAlt(document, eleBind, ["BracketLeft", 219, "KeyO", 79, "KeyA", 65], "O", 2); // [ O A
  3257. disableAfterClick(eleBind);
  3258. }
  3259. var eleInputApproveNext = document.querySelector(".stsh_action_approve_next");
  3260. if (eleInputApproveNext)
  3261. {
  3262. var eleBind = null;
  3263. if (!eleInputApproveNext.disabled)
  3264. {
  3265. // Can go next
  3266. if (elesInputApprove.length === 1)
  3267. {
  3268. // Go next if only 1 suggestion
  3269. if (document.querySelector(".suggestion_status_approved"))
  3270. {
  3271. // Don't go next if 1 or more approved suggestion
  3272. eleBind = elesInputApprove[0];
  3273. }
  3274. else
  3275. {
  3276. eleBind = eleInputApproveNext;
  3277. }
  3278. }
  3279. else if (elesInputApprove.length > 1)
  3280. {
  3281. // Only approve if more than 1 suggestion
  3282. eleBind = elesInputApprove[0];
  3283. }
  3284. }
  3285. else
  3286. {
  3287. // Can't go next
  3288. if (elesInputApprove.length > 0)
  3289. {
  3290. eleBind = elesInputApprove[0];
  3291. }
  3292. }
  3293. if (eleBind)
  3294. {
  3295. addKeyAlt(document, eleBind, ["BracketRight", 221, 171, "KeyP", 80, "KeyS", 83]); // ] P S
  3296. addKeyCtrl(document, eleBind, ["Backslash", 220, "Insert", 45], "Ins", 1|2); // Backslash, INS
  3297. disableAfterClick(eleBind);
  3298. }
  3299. }
  3300. var eleInputDecline = document.querySelector(".stsh_action_decline");
  3301. if (eleInputDecline)
  3302. {
  3303. var eleBind = eleInputDecline;
  3304. var titleMode = 1|2;
  3305. if (eleInputDecline.name === "admindecision")
  3306. {
  3307. titleMode = 2;
  3308. }
  3309. addKeyCtrl(document, eleBind, ["Delete", 46], "Del", titleMode); // DEL
  3310. disableAfterClick(eleBind);
  3311. var eleInputDeclineNext = eleInputDecline.nextElementSibling;
  3312. if (eleInputDeclineNext && eleInputDeclineNext.value.indexOf("Next") > -1
  3313. && !eleInputDeclineNext.disabled)
  3314. {
  3315. var eleBind = eleInputDeclineNext;
  3316. addKeyCtrlShift(document, eleBind, ["Delete", 46], "Del", 2); // DEL
  3317. disableAfterClick(eleBind);
  3318. }
  3319. }
  3320. else
  3321. {
  3322. var eleReconsider = document.querySelector(".suggestion_status_approved > a, .suggestion_status_declined > a");
  3323. if (eleReconsider)
  3324. {
  3325. if (eleReconsider.parentElement.classList.contains("suggestion_status_approved"))
  3326. {
  3327. var elesReconsiderApprove = document.querySelectorAll(".suggestion_status_approved > a");
  3328. if (elesReconsiderApprove.length > 0)
  3329. {
  3330. // Bind to last approve
  3331. var eleBind = elesReconsiderApprove[elesReconsiderApprove.length - 1];
  3332. addKeyCtrl(document, eleBind, ["Delete", 46], "Del", 2|16); // DEL
  3333. }
  3334. }
  3335. else
  3336. {
  3337. if (!eleReconsider.parentElement.parentElement
  3338. .querySelector(".suggestion_signature .lbAction[name^='mymodcomment']"))
  3339. {
  3340. var eleBind = eleReconsider;
  3341. addKeyAlt(document, eleBind, ["BracketRight", 221, 171, "KeyP", 80, "KeyS", 83]); // ] P S
  3342. addKeyCtrl(document, eleBind, ["Backslash", 220, "Insert", 45], "Ins", 2|16); // Backslash INS
  3343. }
  3344. }
  3345. }
  3346. }
  3347. if (elesTextRemoveComment.length > 0)
  3348. {
  3349. // Remove last comment
  3350. var i = elesTextRemoveComment.length - 1;
  3351.  
  3352. var eleBind = elesTextRemoveComment[i];
  3353. addKeyCtrl(document, eleBind, ["Backspace", 8], "Bksp", 2|16); // Backspace
  3354. }
  3355. var eleInputPrev = document.querySelector(".stsh_nav_prev");
  3356. if (eleInputPrev)
  3357. {
  3358. var eleBind = eleInputPrev;
  3359. addKeyCtrl(document, eleBind, ["BracketLeft", 219], "[", 1|2); // [
  3360. disableAfterClick(eleBind);
  3361. // Remove space
  3362. removeElement(eleBind.nextSibling);
  3363. }
  3364. var eleInputNext = document.querySelector(".stsh_nav_next");
  3365. if (eleInputNext)
  3366. {
  3367. var eleBind = eleInputNext;
  3368. addKeyCtrl(document, eleBind, ["BracketRight", 221, 171], "]", 1|2); // ]
  3369. disableAfterClick(eleBind);
  3370. }
  3371. }
  3372. // Check special chars
  3373. // Check combining diacritical marks
  3374. // Check HTML elements count
  3375. {
  3376. if (eleHeaderOrg && eleHeaderTrn)
  3377. {
  3378. if (eleTextOrg && eleTextTrn)
  3379. {
  3380. var strOrg = trimTab(eleTextOrg.textContent);
  3381. var strTrn = "";
  3382. if (!eleTextTrn.classList.contains("stsh_text_trn_empty"))
  3383. {
  3384. strTrn = trimTab(eleTextTrn.textContent);
  3385. }
  3386. var elesSug = elesTextSug;
  3387. // Check special chars
  3388. {
  3389. var statusTrnArr = checkSpecialCharMatched(strOrg, strTrn);
  3390. var statusTrnMatched = statusTrnArr[0];
  3391. var spOrg = statusTrnArr[1];
  3392. var spTrn = statusTrnArr[2];
  3393. if (spOrg > 0 || spTrn > 0)
  3394. {
  3395. var spTitle = "Please check special chars by pressing Display special chars button.";
  3396. var spanSpOrg = document.createElement("span");
  3397. spanSpOrg.id = "stsh_spanSpOrg";
  3398. spanSpOrg.classList.add("stsh_spanStatusOrg");
  3399. spanSpOrg.classList.add("stsh_blue");
  3400. spanSpOrg.classList.add("stsh_cursor_help");
  3401. spanSpOrg.title = spTitle;
  3402. spanSpOrg.innerHTML = " SpecialChar: " + spOrg;
  3403. eleHeaderOrg.appendChild(spanSpOrg);
  3404. // Translated
  3405. if (strTrn !== "")
  3406. {
  3407. var spanSpTrn = document.createElement("span");
  3408. spanSpTrn.id = "stsh_spanSpTrn";
  3409. spanSpTrn.classList.add("stsh_spanStatusTrn");
  3410. spanSpTrn.classList.add("stsh_cursor_help");
  3411. spanSpTrn.title = spTitle;
  3412. if (statusTrnMatched === 0)
  3413. {
  3414. spanSpTrn.classList.add("stsh_green");
  3415. }
  3416. else
  3417. {
  3418. spanSpTrn.classList.add("stsh_red");
  3419. spanSpTrn.classList.add("stsh_status_unmatched");
  3420. }
  3421. var outputTrn = " SpecialChar: " + spTrn;
  3422. if (statusTrnMatched === 0)
  3423. {
  3424. outputTrn += " (Matched)";
  3425. }
  3426. else if (statusTrnMatched === 1)
  3427. {
  3428. outputTrn += " (Order not matched)";
  3429. }
  3430. else
  3431. {
  3432. outputTrn += " (Not matched)";
  3433. }
  3434. spanSpTrn.innerHTML = outputTrn;
  3435. eleHeaderTrn.appendChild(spanSpTrn);
  3436. }
  3437. // Suggested
  3438. for (var i = 0; i < elesSug.length; i++)
  3439. {
  3440. var eleSug = elesSug[i];
  3441. var strSug = trimSpace(eleSug.textContent);
  3442. var statusSugArr = checkSpecialCharMatched(strOrg, strSug);
  3443. var statusSugMatched = statusSugArr[0];
  3444. var spSug = statusSugArr[2];
  3445. var spanSpSug = document.createElement("span");
  3446. spanSpSug.classList.add("stsh_spanSpSug");
  3447. spanSpSug.classList.add("stsh_spanStatusSug");
  3448. spanSpSug.classList.add("stsh_cursor_help");
  3449. spanSpSug.title = spTitle;
  3450. if (statusSugMatched === 0)
  3451. {
  3452. spanSpSug.classList.add("stsh_green");
  3453. spanSpSug.classList.add("stsh_status_matched");
  3454. }
  3455. else
  3456. {
  3457. spanSpSug.classList.add("stsh_red");
  3458. spanSpSug.classList.add("stsh_status_unmatched");
  3459. }
  3460. var outputSug = " SpecialChar: " + spSug;
  3461. if (statusSugMatched === 0)
  3462. {
  3463. outputSug += " (Matched)";
  3464. }
  3465. else if (statusSugMatched === 1)
  3466. {
  3467. outputSug += " (Order not matched)";
  3468. }
  3469. else
  3470. {
  3471. outputSug += " (Not matched)";
  3472. }
  3473. spanSpSug.innerHTML = outputSug;
  3474. insertBeforeElement(spanSpSug, eleSug);
  3475. }
  3476. }
  3477. }
  3478. // Check diacritical marks
  3479. {
  3480. var hasDct = false;
  3481. // Translated
  3482. var dctTrn = countDiacriticalMark(strTrn);
  3483. if (dctTrn > 0)
  3484. {
  3485. hasDct = true;
  3486. }
  3487. var countsSug = [];
  3488. // Suggested
  3489. for (var i = 0; i < elesSug.length; i++)
  3490. {
  3491. var eleSug = elesSug[i];
  3492. var strSug = trimSpace(eleSug.textContent);
  3493. var dctSug = countDiacriticalMark(strSug);
  3494. if (dctSug > 0)
  3495. {
  3496. hasDct = true;
  3497. }
  3498. countsSug.push(dctSug);
  3499. }
  3500. if (hasDct)
  3501. {
  3502. var dctTitleGood = "Combining Diacritical Marks not found. \nThis is good typing method.";
  3503. var dctTitleBad = "Combining Diacritical Marks found. \nPlease change typing method.";
  3504. var spanDctTrn = document.createElement("span");
  3505. spanDctTrn.id = "stsh_spanDctTrn";
  3506. spanDctTrn.classList.add("stsh_spanStatusTrn");
  3507. spanDctTrn.classList.add("stsh_cursor_help");
  3508. if (dctTrn > 0)
  3509. {
  3510. spanDctTrn.classList.add("stsh_red");
  3511. spanDctTrn.classList.add("stsh_status_unmatched");
  3512. spanDctTrn.title = dctTitleBad;
  3513. }
  3514. else
  3515. {
  3516. spanDctTrn.classList.add("stsh_green");
  3517. spanDctTrn.title = dctTitleGood;
  3518. }
  3519. var outputDctTrn = " DiacriticalMark: " + dctTrn;
  3520. spanDctTrn.innerHTML = outputDctTrn;
  3521. eleHeaderTrn.appendChild(spanDctTrn);
  3522. for (var i = 0; i < elesSug.length; i++)
  3523. {
  3524. var eleSug = elesSug[i];
  3525. var dctSug = countsSug[i];
  3526. var spanDctSug = document.createElement("span");
  3527. spanDctSug.classList.add("stsh_spanDctSug");
  3528. spanDctSug.classList.add("stsh_spanStatusSug");
  3529. spanDctSug.classList.add("stsh_cursor_help");
  3530. if (dctSug > 0)
  3531. {
  3532. spanDctSug.classList.add("stsh_red");
  3533. spanDctSug.classList.add("stsh_status_unmatched");
  3534. spanDctSug.title = dctTitleBad;
  3535. }
  3536. else
  3537. {
  3538. spanDctSug.classList.add("stsh_green");
  3539. spanDctSug.title = dctTitleGood;
  3540. }
  3541. var outputDctSug = " DiacriticalMark: " + dctSug;
  3542. spanDctSug.innerHTML = outputDctSug;
  3543. insertBeforeElement(spanDctSug, eleSug);
  3544. }
  3545. }
  3546. }
  3547. // Check HTML elements count
  3548. // Sample: https://translation.steampowered.com/translate.php?search_input=%23Email_Partner_KeyRequest_Doc_Instructions
  3549. // Sample: https://translation.steampowered.com/translate.php?search_input=turret.sp_sabotage_factory_defect
  3550. {
  3551. var hasElement = false;
  3552. var queryCount = ':not([style="color:red;"])'
  3553. + ':not([style="color:#ff0000;"])'
  3554. + ':not([style="color:#ffffff;"])'
  3555. + ':not([style="BACKGROUND-COLOR: blue"])'
  3556. + ':not([face="Times New Roman"])'
  3557. + ':not([data-pagespeed-no-defer])';
  3558. var countEleOrg = eleTextOrg.querySelectorAll(queryCount).length;
  3559. var countEleTrn = -1; // -1 means Not Translated
  3560. if (!eleTextTrn.classList.contains("stsh_text_trn_empty"))
  3561. {
  3562. countEleTrn = eleTextTrn.querySelectorAll(queryCount).length;
  3563. }
  3564. var countsSug = [];
  3565. // Suggested
  3566. var elesSug = elesTextSug;
  3567. for (var i = 0; i < elesSug.length; i++)
  3568. {
  3569. var eleSug = elesSug[i];
  3570. var countEle = eleSug.querySelectorAll(queryCount).length;;
  3571. if (countEle > 0)
  3572. {
  3573. hasElement = true;
  3574. }
  3575. countsSug.push(countEle);
  3576. }
  3577. hasElement = hasElement || countEleOrg > 0 || countEleTrn > 0;
  3578. if (hasElement)
  3579. {
  3580. var countTitleGood = "You can check HTML elements by pressing Display HTML tags button. "
  3581. + "\nSome tags and attributes were generated or removed by STS "
  3582. + "\n(such as <script>, <br> and <img> tags). "
  3583. + "\nIf you can submit, then it's OK.";
  3584. var countTitleBad = "HTML elements count not matched. \n" + countTitleGood;
  3585. var spanCountOrg = document.createElement("span");
  3586. spanCountOrg.id = "stsh_spanCountEleOrg";
  3587. spanCountOrg.classList.add("stsh_spanStatusOrg");
  3588. spanCountOrg.classList.add("stsh_blue");
  3589. spanCountOrg.classList.add("stsh_cursor_help");
  3590. spanCountOrg.title = countTitleGood;
  3591. spanCountOrg.innerHTML = " HtmlElementCount: " + countEleOrg;
  3592. eleHeaderOrg.appendChild(spanCountOrg);
  3593. // Translated
  3594. if (countEleTrn > -1)
  3595. {
  3596. var spanCountTrn = document.createElement("span");
  3597. spanCountTrn.id = "stsh_spanCountEleTrn";
  3598. spanCountTrn.classList.add("stsh_spanStatusTrn");
  3599. spanCountTrn.classList.add("stsh_cursor_help");
  3600. var outputTrn = " HtmlElementCount: " + countEleTrn;
  3601. if (countEleOrg === countEleTrn)
  3602. {
  3603. spanCountTrn.classList.add("stsh_green");
  3604. spanCountTrn.title = countTitleGood;
  3605. outputTrn += (countEleOrg > 0) ? " (Matched)" : "";
  3606. }
  3607. else
  3608. {
  3609. spanCountTrn.classList.add("stsh_blue");
  3610. spanCountTrn.classList.add("stsh_status_unmatched");
  3611. spanCountTrn.title = countTitleBad;
  3612. outputTrn += (countEleOrg > 0) ? " (Not matched)" : "";
  3613. }
  3614. spanCountTrn.innerHTML = outputTrn;
  3615. eleHeaderTrn.appendChild(spanCountTrn);
  3616. }
  3617. // Suggested
  3618. for (var i = 0; i < elesSug.length; i++)
  3619. {
  3620. var eleSug = elesSug[i];
  3621. var countEleSug = countsSug[i];
  3622. var spanCountSug = document.createElement("span");
  3623. spanCountSug.classList.add("stsh_spanCountEleSug");
  3624. spanCountSug.classList.add("stsh_spanStatusSug");
  3625. spanCountSug.classList.add("stsh_cursor_help");
  3626. var outputSug = " HtmlElementCount: " + countEleSug;
  3627. if (countEleOrg === countEleSug)
  3628. {
  3629. spanCountSug.classList.add("stsh_green");
  3630. spanCountSug.title = countTitleGood;
  3631. outputSug += (countEleOrg > 0) ? " (Matched)" : "";
  3632. }
  3633. else
  3634. {
  3635. spanCountSug.classList.add("stsh_blue");
  3636. spanCountSug.classList.add("stsh_status_unmatched");
  3637. spanCountSug.title = countTitleBad;
  3638. outputSug += (countEleOrg > 0) ? "/" + countEleOrg + " (Not matched)" : "";
  3639. }
  3640. spanCountSug.innerHTML = outputSug;
  3641. insertBeforeElement(spanCountSug, eleSug);
  3642. }
  3643. }
  3644. }
  3645. }
  3646. }
  3647. }
  3648. // Display newlines
  3649. // Display spaces
  3650. // Display specialChars
  3651. // Display HTML tags
  3652. // Display hidden contents
  3653. // Minimize images
  3654. {
  3655. var eleSugListHeader = document.querySelector(".stsh_suggestion_list_header");
  3656. if (eleSugListHeader && eleTextOrg && eleTextTrn)
  3657. {
  3658. var htmlOrg = eleTextOrg.dataset.stshHtml;
  3659. var htmlTrn = eleTextTrn.classList.contains("stsh_text_trn_empty") ? "" : eleTextTrn.dataset.stshHtml;
  3660. var elesSug = elesTextSug;
  3661. var eleGroup = null;
  3662. var elesBtn = [null, null, null, null, null, null, null, null]
  3663. var enableDisplay = false;
  3664. var enableNewline = false;
  3665. var enableSpace = false;
  3666. var enableSpecialChar = false;
  3667. var enableHtmlTag = false;
  3668. var enableHidden = false;
  3669. var enableMinImg = false;
  3670. var rgxSpaceTagOpen = /(<[^\/][^>]+>)( +)([^< \r\n])/g;
  3671. var rgxSpaceTagClose = /([^> \r\n])( +)(<\/[^>]+>)/g;
  3672. var hasNewline = function(html)
  3673. {
  3674. return html.indexOf("\n") > -1 || html.indexOf("\\n") > -1;
  3675. }
  3676. var hasSpace = function(html)
  3677. {
  3678. return html.indexOf(" ") === 0 || isLastIndex(html, " ")
  3679. || rgxSpaceTagOpen.test(html) || rgxSpaceTagClose.test(html);
  3680. }
  3681. var hasHtmlTag = function(html)
  3682. {
  3683. return html.indexOf("<") > -1 || html.indexOf("[/") > -1;
  3684. }
  3685. var hasHidden = function(eleTextOrg, eleTextTrn, elesSug)
  3686. {
  3687. var returnValue = false;
  3688. returnValue = !!(eleTextOrg.querySelector("*[style='display: none;']")
  3689. || eleTextTrn.querySelector("*[style='display: none;']"));
  3690. if (!returnValue)
  3691. {
  3692. if (elesSug.length > 0)
  3693. {
  3694. returnValue = !!(elesSug[0].querySelector("*[style='display: none;']"));
  3695. }
  3696. }
  3697. if (returnValue)
  3698. {
  3699. var countHidden = 0;
  3700. var elesHidden = eleTextOrg.querySelectorAll("*[style='display: none;']");
  3701. for (var i = 0; i < elesHidden.length; i++)
  3702. {
  3703. if (elesHidden[i].childElementCount > 1
  3704. || (elesHidden[i].firstElementChild
  3705. && elesHidden[i].firstElementChild.tagName !== "STYLE"))
  3706. {
  3707. countHidden++;
  3708. break;
  3709. }
  3710. }
  3711. returnValue = countHidden > 0;
  3712. }
  3713. if (!returnValue)
  3714. {
  3715. returnValue = !!(eleTextOrg.querySelector(".collapse, .dropdown-before")
  3716. || eleTextTrn.querySelector(".collapse, .dropdown-before"));
  3717. }
  3718. return returnValue;
  3719. }
  3720. var hasImage = function(eleTextOrg, eleTextTrn)
  3721. {
  3722. return !!(eleTextOrg.querySelector("img") || eleTextTrn.querySelector("img"));
  3723. }
  3724. enableNewline = hasNewline(htmlOrg) || hasNewline(htmlTrn);
  3725. enableSpace = hasSpace(htmlOrg) || hasSpace(htmlTrn);
  3726. enableSpecialChar = hasSpecialChar(htmlOrg) || hasSpecialChar(htmlTrn);
  3727. enableHtmlTag = hasHtmlTag(htmlOrg) || hasHtmlTag(htmlTrn);
  3728. enableHidden = hasHidden(eleTextOrg, eleTextTrn, elesSug);
  3729. enableMinImg = hasImage(eleTextOrg, eleTextTrn);
  3730. for (var i = 0; i < elesSug.length; i++)
  3731. {
  3732. var htmlSug = elesSug[i].dataset.stshHtml;
  3733. enableNewline = enableNewline || hasNewline(htmlSug);
  3734. enableSpace = enableSpace || hasSpace(htmlSug);
  3735. enableSpecialChar = enableSpecialChar || hasSpecialChar(htmlSug);
  3736. }
  3737. enableDisplay = enableNewline || enableSpace || enableSpecialChar
  3738. || enableHtmlTag || enableHidden || enableMinImg;
  3739. if (enableDisplay)
  3740. {
  3741. elesBtn[0] = document.createElement("input");
  3742. elesBtn[0].id = "stsh_btn_restoreContents";
  3743. elesBtn[0].classList.add("stsh_btn_right");
  3744. elesBtn[0].classList.add("stsh_margin_left");
  3745. elesBtn[0].setAttribute("type", "button");
  3746. elesBtn[0].setAttribute("value", "Restore contents");
  3747. elesBtn[0].setAttribute("title", "Restore original contents");
  3748. elesBtn[0].disabled = true;
  3749. eleSugListHeader.appendChild(elesBtn[0]);
  3750. var restoreContents = function(ele)
  3751. {
  3752. if (ele)
  3753. {
  3754. ele.innerHTML = ele.dataset.stshHtml;
  3755. }
  3756. };
  3757. elesBtn[0].addEventListener("click", function(ev)
  3758. {
  3759. var eleTarget = ev.target;
  3760. eleTarget.disabled = true;
  3761. for (var i = 1; i < elesBtn.length; i++)
  3762. {
  3763. if (elesBtn[i])
  3764. {
  3765. elesBtn[i].disabled = false;
  3766. elesBtn[i].focus();
  3767. }
  3768. }
  3769. var topOld = Math.floor(eleTarget.getBoundingClientRect().top) || 0;
  3770. var eleTextOrg = document.querySelector(".stsh_text_org");
  3771. var eleTextTrn = document.querySelector(".stsh_text_trn:not(.stsh_text_trn_empty)");
  3772. restoreContents(eleTextOrg);
  3773. restoreContents(eleTextTrn);
  3774. var elesSug = document.querySelectorAll(".suggestion_text");
  3775. for (var i = 0; i < elesSug.length; i++)
  3776. {
  3777. var eleSug = elesSug[i];
  3778. restoreContents(eleSug);
  3779. }
  3780. var topNew = Math.floor(eleTarget.getBoundingClientRect().top) || 0;
  3781. if (topOld !== topNew)
  3782. {
  3783. window.scrollBy(0, topNew - topOld);
  3784. }
  3785. });
  3786. eleGroup = document.createElement("div");
  3787. eleGroup.classList.add("stsh_group_display");
  3788. eleGroup.classList.add("stsh_btn_right");
  3789. eleSugListHeader.appendChild(eleGroup);
  3790. }
  3791. // Display newlines
  3792. if (enableNewline)
  3793. {
  3794. elesBtn[1] = document.createElement("input");
  3795. elesBtn[1].id = "stsh_btn_displayNewlines";
  3796. elesBtn[1].classList.add("stsh_btn_right");
  3797. elesBtn[1].classList.add("stsh_btn_display");
  3798. elesBtn[1].setAttribute("type", "button");
  3799. elesBtn[1].setAttribute("value", "Newlines");
  3800. elesBtn[1].setAttribute("title", "Display newlines (\\n and <br>)");
  3801. eleGroup.appendChild(elesBtn[1]);
  3802. var displayNewlines = function(ele)
  3803. {
  3804. if (ele)
  3805. {
  3806. ele.innerHTML = ele.dataset.stshHtml
  3807. .replace(/\<span[^\>]+class=\"stsh_[\s\S]+?\/span\>/ig, "")
  3808. .replace(/\n/g, "\n<br>")
  3809. .replace(/(\\r)? *\\n/g, ' <span class="stsh_marker">$&</span><br>')
  3810. .replace(/\<br\>[\s]+/g, "<br>&nbsp;");
  3811. }
  3812. };
  3813. elesBtn[1].addEventListener("click", function(ev)
  3814. {
  3815. var eleTarget = ev.target;
  3816. eleTarget.disabled = true;
  3817. for (var i = 0; i < elesBtn.length; i++)
  3818. {
  3819. if (elesBtn[i] && elesBtn[i] !== eleTarget)
  3820. {
  3821. elesBtn[i].disabled = false;
  3822. }
  3823. }
  3824. elesBtn[0].focus();
  3825. var topOld = Math.floor(eleTarget.getBoundingClientRect().top) || 0;
  3826. var eleTextOrg = document.querySelector(".stsh_text_org");
  3827. var eleTextTrn = document.querySelector(".stsh_text_trn:not(.stsh_text_trn_empty)");
  3828. displayNewlines(eleTextOrg);
  3829. displayNewlines(eleTextTrn);
  3830. var elesSug = document.querySelectorAll(".suggestion_text");
  3831. for (var i = 0; i < elesSug.length; i++)
  3832. {
  3833. var eleSug = elesSug[i];
  3834. displayNewlines(eleSug);
  3835. }
  3836. var topNew = Math.floor(eleTarget.getBoundingClientRect().top) || 0;
  3837. if (topOld !== topNew)
  3838. {
  3839. window.scrollBy(0, topNew - topOld);
  3840. }
  3841. });
  3842. }
  3843. // Display spaces
  3844. // Sample: Use regexp ^[ ]+[^/W]|[^/W][ ]+$ to search
  3845. // Sample: https://translation.steampowered.com/translate.php?search_input=portal_lyrics_17
  3846. // Sample: https://translation.steampowered.com/translate.php?search_input=portal_lyrics_23
  3847. if (enableSpace)
  3848. {
  3849. elesBtn[2] = document.createElement("input");
  3850. elesBtn[2].id = "stsh_btn_displaySpaces";
  3851. elesBtn[2].classList.add("stsh_btn_right");
  3852. elesBtn[2].classList.add("stsh_btn_display");
  3853. elesBtn[2].setAttribute("type", "button");
  3854. elesBtn[2].setAttribute("value", "Spaces");
  3855. elesBtn[2].setAttribute("title", "Strings may have leading or trailing spaces.");
  3856. eleGroup.appendChild(elesBtn[2]);
  3857. var displaySpaces = function(ele)
  3858. {
  3859. if (ele)
  3860. {
  3861. ele.innerHTML = ele.dataset.stshHtml
  3862. .replace(/(^ +| +$)/g, function(match, p1)
  3863. {
  3864. return '<span class="stsh_marker">' + p1.replace(/ /g,"_") + '</span>';
  3865. })
  3866. .replace(rgxSpaceTagOpen, function(match, p1, p2, p3)
  3867. {
  3868. return p1 + '<span class="stsh_marker">' + p2.replace(/ /g,"_") + '</span>' + p3;
  3869. })
  3870. .replace(rgxSpaceTagClose, function(match, p1, p2, p3)
  3871. {
  3872. return p1 + '<span class="stsh_marker">' + p2.replace(/ /g,"_") + '</span>' + p3;
  3873. });
  3874. }
  3875. }
  3876. elesBtn[2].addEventListener("click", function(ev)
  3877. {
  3878. var eleTarget = ev.target;
  3879. eleTarget.disabled = true;
  3880. for (var i = 0; i < elesBtn.length; i++)
  3881. {
  3882. if (elesBtn[i] && elesBtn[i] !== eleTarget)
  3883. {
  3884. elesBtn[i].disabled = false;
  3885. }
  3886. }
  3887. elesBtn[0].focus();
  3888. var topOld = Math.floor(eleTarget.getBoundingClientRect().top) || 0;
  3889. var eleTextOrg = document.querySelector(".stsh_text_org");
  3890. var eleTextTrn = document.querySelector(".stsh_text_trn:not(.stsh_text_trn_empty)");
  3891. displaySpaces(eleTextOrg);
  3892. displaySpaces(eleTextTrn);
  3893. var elesSug = document.querySelectorAll(".suggestion_text");
  3894. for (var i = 0; i < elesSug.length; i++)
  3895. {
  3896. var eleSug = elesSug[i];
  3897. displaySpaces(eleSug);
  3898. }
  3899. var topNew = Math.floor(eleTarget.getBoundingClientRect().top) || 0;
  3900. if (topOld !== topNew)
  3901. {
  3902. window.scrollBy(0, topNew - topOld);
  3903. }
  3904. });
  3905. }
  3906. // Display specialChars
  3907. // Sample: https://translation.steampowered.com/translate.php?search_input=Item_Traded
  3908. if (enableSpecialChar)
  3909. {
  3910. elesBtn[3] = document.createElement("input");
  3911. elesBtn[3].id = "stsh_btn_displaySpecialChars";
  3912. elesBtn[3].classList.add("stsh_btn_right");
  3913. elesBtn[3].classList.add("stsh_btn_display");
  3914. elesBtn[3].setAttribute("type", "button");
  3915. elesBtn[3].setAttribute("value", "Special chars");
  3916. elesBtn[3].setAttribute("title", "Special chars usually use in Valve games as color symbols.");
  3917. eleGroup.appendChild(elesBtn[3]);
  3918. var replaceSpecialChars = function(str, unicodeNumber)
  3919. {
  3920. var rgx = new RegExp("\\u" + padZeroHex(unicodeNumber, 4), "g");
  3921. return str.replace(rgx, '<span class="stsh_marker">[' + padZeroHex(unicodeNumber, 2) + ']</span>');
  3922. }
  3923. var displaySpecialChars = function(ele)
  3924. {
  3925. if (ele)
  3926. {
  3927. var strInner = (typeof ele.dataset.stshHtml === "undefined")
  3928. ? trimTab(ele.innerHTML) : ele.dataset.stshHtml;
  3929. for (var i = 0; i < 32; i++)
  3930. {
  3931. if (hasSpecialChar(strInner))
  3932. {
  3933. if (isSpecialChar(i))
  3934. {
  3935. strInner = replaceSpecialChars(strInner, i);
  3936. }
  3937. }
  3938. else
  3939. {
  3940. break;
  3941. }
  3942. }
  3943. ele.innerHTML = strInner;
  3944. }
  3945. }
  3946. elesBtn[3].addEventListener("click", function(ev)
  3947. {
  3948. var eleTarget = ev.target;
  3949. eleTarget.disabled = true;
  3950. for (var i = 0; i < elesBtn.length; i++)
  3951. {
  3952. if (elesBtn[i] && elesBtn[i] !== eleTarget)
  3953. {
  3954. elesBtn[i].disabled = false;
  3955. }
  3956. }
  3957. elesBtn[0].focus();
  3958. var topOld = Math.floor(eleTarget.getBoundingClientRect().top) || 0;
  3959. var eleTextOrg = document.querySelector(".stsh_text_org");
  3960. var eleTextTrn = document.querySelector(".stsh_text_trn:not(.stsh_text_trn_empty)");
  3961. displaySpecialChars(eleTextOrg);
  3962. displaySpecialChars(eleTextTrn);
  3963. var elesSug = document.querySelectorAll(
  3964. ".suggestion_text, .stsh_sametoken_header .insertword, .stsh_text_comment");
  3965. for (var i = 0; i < elesSug.length; i++)
  3966. {
  3967. var eleSug = elesSug[i];
  3968. displaySpecialChars(eleSug);
  3969. }
  3970. var topNew = Math.floor(eleTarget.getBoundingClientRect().top) || 0;
  3971. if (topOld !== topNew)
  3972. {
  3973. window.scrollBy(0, topNew - topOld);
  3974. }
  3975. });
  3976. }
  3977. // Display HTML tags
  3978. if (enableHtmlTag)
  3979. {
  3980. elesBtn[4] = document.createElement("input");
  3981. elesBtn[4].id = "stsh_btn_displayHtmlTags";
  3982. elesBtn[4].classList.add("stsh_btn_right");
  3983. elesBtn[4].classList.add("stsh_btn_display");
  3984. elesBtn[4].setAttribute("type", "button");
  3985. elesBtn[4].setAttribute("value", "HTML tags");
  3986. elesBtn[4].setAttribute("title"
  3987. , "Some closing tags and attributes were autogenerated by web browser.");
  3988. eleGroup.appendChild(elesBtn[4]);
  3989. elesBtn[4].addEventListener("click", function(ev)
  3990. {
  3991. var eleTarget = ev.target;
  3992. eleTarget.disabled = true;
  3993. for (var i = 0; i < elesBtn.length; i++)
  3994. {
  3995. if (elesBtn[i] && elesBtn[i] !== eleTarget)
  3996. {
  3997. elesBtn[i].disabled = false;
  3998. }
  3999. }
  4000. elesBtn[0].focus();
  4001. var topOld = Math.floor(eleTarget.getBoundingClientRect().top) || 0;
  4002. var eleTextOrg = document.querySelector(".stsh_text_org");
  4003. var eleTextTrn = document.querySelector(".stsh_text_trn:not(.stsh_text_trn_empty)");
  4004. displayHtmlTags(eleTextOrg);
  4005. displayHtmlTags(eleTextTrn);
  4006. var elesSug = document.querySelectorAll(".suggestion_text");
  4007. for (var i = 0; i < elesSug.length; i++)
  4008. {
  4009. var eleSug = elesSug[i];
  4010. displayHtmlTags(eleSug);
  4011. }
  4012. var topNew = Math.floor(eleTarget.getBoundingClientRect().top) || 0;
  4013. if (topOld !== topNew)
  4014. {
  4015. window.scrollBy(0, topNew - topOld);
  4016. }
  4017. });
  4018. }
  4019. // Display hidden contents
  4020. // Sample: https://translation.steampowered.com/translate.php?search_input=faq_4181_answer
  4021. if (enableHidden)
  4022. {
  4023. elesBtn[5] = document.createElement("input");
  4024. elesBtn[5].id = "stsh_btn_displayHidden";
  4025. elesBtn[5].classList.add("stsh_btn_right");
  4026. elesBtn[5].classList.add("stsh_btn_display");
  4027. elesBtn[5].setAttribute("type", "button");
  4028. elesBtn[5].setAttribute("value", "Hidden contents");
  4029. elesBtn[5].setAttribute("title", "Toggle show/hide contents that hidden by CSS."
  4030. + " \nHidden contents shown in gray boxes.");
  4031. elesBtn[5].dataset.modeNext = "show";
  4032. eleGroup.appendChild(elesBtn[5]);
  4033. var showHidden = function(ele, mode)
  4034. {
  4035. if (ele)
  4036. {
  4037. if (mode === "show")
  4038. {
  4039. var elesHidden = ele.querySelectorAll(
  4040. "*[style='display: none;'], .collapse, .dropdown-before");
  4041. for (var i = 0; i < elesHidden.length; i++)
  4042. {
  4043. elesHidden[i].classList.add("stsh_showHidden");
  4044. }
  4045. }
  4046. else
  4047. {
  4048. var elesHidden = ele.querySelectorAll(".stsh_showHidden");
  4049. for (var i = 0; i < elesHidden.length; i++)
  4050. {
  4051. elesHidden[i].classList.remove("stsh_showHidden");
  4052. }
  4053. }
  4054. }
  4055. }
  4056. elesBtn[5].addEventListener("click", function(ev)
  4057. {
  4058. var eleTarget = ev.target;
  4059. var mode = "show";
  4060. if (eleTarget.dataset.modeNext === "show")
  4061. {
  4062. mode = "show";
  4063. eleTarget.dataset.modeNext = "hide";
  4064. }
  4065. else
  4066. {
  4067. mode = "hide";
  4068. eleTarget.dataset.modeNext = "show";
  4069. }
  4070. var topOld = Math.floor(eleTarget.getBoundingClientRect().top) || 0;
  4071. var eleTextOrg = document.querySelector(".stsh_text_org");
  4072. var eleTextTrn = document.querySelector(".stsh_text_trn:not(.stsh_text_trn_empty)");
  4073. showHidden(eleTextOrg, mode);
  4074. showHidden(eleTextTrn, mode);
  4075. var elesSug = document.querySelectorAll(".suggestion_text");
  4076. for (var i = 0; i < elesSug.length; i++)
  4077. {
  4078. var eleSug = elesSug[i];
  4079. showHidden(eleSug, mode);
  4080. }
  4081. var topNew = Math.floor(eleTarget.getBoundingClientRect().top) || 0;
  4082. if (topOld !== topNew)
  4083. {
  4084. window.scrollBy(0, topNew - topOld);
  4085. }
  4086. });
  4087. }
  4088. // Minimize images
  4089. // Sample: https://translation.steampowered.com/translate.php?search_input=faq_4192_answer
  4090. if (enableMinImg)
  4091. {
  4092. elesBtn[6] = document.createElement("input");
  4093. elesBtn[6].id = "stsh_btn_minimizeImages";
  4094. elesBtn[6].classList.add("stsh_btn_right");
  4095. elesBtn[6].classList.add("stsh_btn_display");
  4096. elesBtn[6].setAttribute("type", "button");
  4097. elesBtn[6].setAttribute("value", "Minimize images");
  4098. elesBtn[6].setAttribute("title", "Toggle reduced/normal image sizes");
  4099. elesBtn[6].dataset.modeNext = "min";
  4100. eleGroup.appendChild(elesBtn[6]);
  4101. var minimizeImages = function(ele, mode)
  4102. {
  4103. if (ele)
  4104. {
  4105. if (mode === "min")
  4106. {
  4107. var elesImg = ele.querySelectorAll("img:not(.stsh_img_min)");
  4108. for (var i = 0; i < elesImg.length; i++)
  4109. {
  4110. elesImg[i].classList.add("stsh_img_min");
  4111. }
  4112. }
  4113. else
  4114. {
  4115. var elesImg = ele.querySelectorAll("img.stsh_img_min");
  4116. for (var i = 0; i < elesImg.length; i++)
  4117. {
  4118. elesImg[i].classList.remove("stsh_img_min");
  4119. }
  4120. }
  4121. }
  4122. }
  4123. elesBtn[6].addEventListener("click", function(ev)
  4124. {
  4125. var eleTarget = ev.target;
  4126. var mode = "min";
  4127. if (eleTarget.dataset.modeNext === "min")
  4128. {
  4129. mode = "min";
  4130. eleTarget.dataset.modeNext = "unmin";
  4131. }
  4132. else
  4133. {
  4134. mode = "unmin";
  4135. eleTarget.dataset.modeNext = "min";
  4136. }
  4137. var topOld = Math.floor(eleTarget.getBoundingClientRect().top) || 0;
  4138. var eleTextOrg = document.querySelector(".stsh_text_org");
  4139. var eleTextTrn = document.querySelector(".stsh_text_trn:not(.stsh_text_trn_empty)");
  4140. minimizeImages(eleTextOrg, mode);
  4141. minimizeImages(eleTextTrn, mode);
  4142. var elesSug = document.querySelectorAll(".suggestion_text");
  4143. for (var i = 0; i < elesSug.length; i++)
  4144. {
  4145. var eleSug = elesSug[i];
  4146. minimizeImages(eleSug, mode);
  4147. }
  4148. var topNew = Math.floor(eleTarget.getBoundingClientRect().top) || 0;
  4149. if (topOld !== topNew)
  4150. {
  4151. window.scrollBy(0, topNew - topOld);
  4152. }
  4153. });
  4154. }
  4155. if (enableDisplay)
  4156. {
  4157. var eleDiv = document.createElement("div");
  4158. eleDiv.classList.add("stsh_text_right");
  4159. eleDiv.classList.add("stsh_margin_right");
  4160. eleDiv.textContent = "Display:";
  4161. eleSugListHeader.appendChild(eleDiv);
  4162. }
  4163. }
  4164. }
  4165. // Open comment when decline
  4166. // Paste last comment
  4167. {
  4168. var countComment = 0;
  4169. var elesComment = [];
  4170. var countSug = document.querySelectorAll(".suggestions_list .suggestion").length;
  4171. if (countSug > 0)
  4172. {
  4173. var textOrg = "";
  4174. if (eleTextOrg)
  4175. {
  4176. textOrg = eleTextOrg.dataset.stshHtml.substr(0, 3000).toLowerCase();
  4177. }
  4178. var isSameTextOrg = textOrg === GM_getValue("textLastOrg_Comment", "");
  4179. var textLastCur = GM_getValue("textLastCur_Comment", "");
  4180. var isSetComment = false;
  4181. var countSugDeclined = document.querySelectorAll(
  4182. ".suggestions_list span[class='suggestion_status_declined']").length;
  4183. if (countSug !== countSugDeclined)
  4184. {
  4185. var elesSugCheck = document.querySelectorAll(".suggestions_list span[class^='suggestion_status_']");
  4186. if (countSug === elesSugCheck.length)
  4187. {
  4188. var eleSugDeclined = document.querySelector(".suggestions_list span[class='suggestion_status_declined']");
  4189. if (eleSugDeclined && eleSugDeclined === elesSugCheck[0] && eleSugDeclined.querySelector("a"))
  4190. {
  4191. countSugDeclined = countSug;
  4192. }
  4193. }
  4194. }
  4195. if (countSug === countSugDeclined)
  4196. {
  4197. var elesSugA = document.querySelectorAll(".suggestions_list span[class^='suggestion_status_'] a");
  4198. for (var i = 0; i < elesSugA.length; i++)
  4199. {
  4200. var eleComment = elesSugA[i].parentElement.parentElement.nextSibling;
  4201. if (eleComment.nodeName === "DIV" && eleComment.classList.contains("copy"))
  4202. {
  4203. if (elesSugA[i].parentElement.classList.contains("suggestion_status_declined"))
  4204. {
  4205. countComment++;
  4206. elesComment.push(eleComment);
  4207. }
  4208. }
  4209. }
  4210. if (countComment === elesSugA.length)
  4211. {
  4212. var isFocus = false;
  4213. for (var i = 0; i < elesComment.length; i++)
  4214. {
  4215. elesComment[i].style.display = "block";
  4216. if (!isFocus)
  4217. {
  4218. var eleTxt = elesComment[i].querySelector(".stsh_text_addComment");
  4219. if (eleTxt)
  4220. {
  4221. eleTxt.focus();
  4222. // Auto paste last comment
  4223. {
  4224. if (isSameTextOrg)
  4225. {
  4226. if (textLastCur !== "")
  4227. {
  4228. eleTxt.value = textLastCur;
  4229. isSetComment = true;
  4230. }
  4231. setTimeoutCustom(function(ele)
  4232. {
  4233. // paste again after script ran
  4234. if (ele)
  4235. {
  4236. var textLastCur = GM_getValue("textLastCur_Comment", "");
  4237. if (textLastCur !== "")
  4238. {
  4239. ele.value = textLastCur;
  4240. //ele.selectionStart = 0;
  4241. //ele.selectionEnd = ele.value.length;
  4242. }
  4243. }
  4244. }, timingInit.pasteLastComment, eleTxt);
  4245. }
  4246. }
  4247. /*
  4248. // Typonion
  4249. var eleSugOuter = elesComment[i].parentElement.parentElement.parentElement.parentElement;
  4250. if (eleSugOuter.classList.contains("suggestion"))
  4251. {
  4252. var eleOnion = eleSugOuter.querySelector(".suggestion_text font[style='color:#01ec00;']");
  4253. if (eleOnion)
  4254. {
  4255. eleTxt.value = "onion";
  4256. }
  4257. }
  4258. */
  4259. var eleSugComment = elesComment[i].parentElement
  4260. .parentElement.parentElement.querySelector(".stsh_text_comment font");
  4261. if (eleSugComment && eleSugComment.textContent.trim() ==
  4262. "ATTENTION - English string was updated. This suggestion might be outdated.")
  4263. {
  4264. eleTxt.value = "outdated";
  4265. isSetComment = true;
  4266. }
  4267. isFocus = true;
  4268. }
  4269. }
  4270. }
  4271. }
  4272. }
  4273. if (isSameTextOrg && !isSetComment && textLastCur !== "")
  4274. {
  4275. // paste last comment to all hidden comment inputs
  4276. var elesTxt = document.querySelectorAll(".stsh_text_addComment");
  4277. for (var i = 0; i < elesTxt.length; i++)
  4278. {
  4279. elesTxt[i].value = textLastCur;
  4280. isSetComment = true;
  4281. }
  4282. }
  4283. }
  4284. }
  4285. // Convert time
  4286. {
  4287. var rgxTime = /\d{2}-\d{2}-\d{4}, \d{2}:\d{2} [AP]M/;
  4288. var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
  4289. var eleFriends = document.querySelectorAll(".friend_block_avatar, .stsh_discussion, .suggestions_list");
  4290. for (var i = 0; i < eleFriends.length; i++)
  4291. {
  4292. var nodes = [];
  4293. if (eleFriends[i].classList.contains("friend_block_avatar"))
  4294. {
  4295. nodes = eleFriends[i].childNodes;
  4296. if (nodes.length === 1)
  4297. {
  4298. // Correct HTML tags that auto generated
  4299. nodes = eleFriends[i].childNodes[0].childNodes;
  4300. }
  4301. }
  4302. else if (eleFriends[i].classList.contains("stsh_discussion"))
  4303. {
  4304. nodes = eleFriends[i].childNodes[2].childNodes;
  4305. }
  4306. else if (eleFriends[i].classList.contains("suggestions_list"))
  4307. {
  4308. if (!eleFriends[i].querySelector(".suggestion"))
  4309. {
  4310. nodes = eleFriends[i].childNodes;
  4311. }
  4312. }
  4313. for (var j = 0; j < nodes.length; j++)
  4314. {
  4315. var nodeVal = nodes[j].nodeValue;
  4316. if (nodeVal)
  4317. {
  4318. var dateTimes = rgxTime.exec(nodeVal);
  4319. if (dateTimes)
  4320. {
  4321. var dateTime = dateTimes[0];
  4322. var month = dateTime.substr(0, 2);
  4323. var day = dateTime.substr(3, 2);
  4324. var year = dateTime.substr(6, 4);
  4325. var hour = dateTime.substr(12, 2);
  4326. var minute = dateTime.substr(15, 2);
  4327. var period = dateTime.substr(18, 2);
  4328. if (period === "AM")
  4329. {
  4330. if (hour === "12")
  4331. {
  4332. hour = "00"
  4333. }
  4334. }
  4335. else if (period === "PM")
  4336. {
  4337. hour = parseInt(hour) + 12;
  4338. if (hour === 24)
  4339. {
  4340. hour = 12;
  4341. }
  4342. }
  4343. var dateTimeStd = year + "-" + month + "-" + day;
  4344. if (isDstUs(year, month, day, hour))
  4345. {
  4346. dateTimeStd += "T" + hour + ":" + minute + ":00-0700";
  4347. }
  4348. else
  4349. {
  4350. dateTimeStd += "T" + hour + ":" + minute + ":00-0800";
  4351. }
  4352. var dateStd = new Date(dateTimeStd);
  4353. if (dateStd.toLocaleString() !== "Invalid Date")
  4354. {
  4355. var gmt = dateStd.getTimezoneOffset() / 60 * -1;
  4356. var gmtStr = " GMT";
  4357. if (gmt > 0)
  4358. {
  4359. gmtStr += "+" + gmt;
  4360. }
  4361. else if (gmt < 0)
  4362. {
  4363. gmtStr += "-" + gmt;
  4364. }
  4365. var dateNew = dateStd.getDate()
  4366. + " " + months[dateStd.getMonth()]
  4367. + " " + dateStd.getFullYear()
  4368. + ", " + padZero(dateStd.getHours(), 2)
  4369. + ":" + padZero(dateStd.getMinutes(), 2)
  4370. + gmtStr;
  4371. //console.log("Time: " + dateTimeStd);
  4372. //console.log("Time: " + dateTime + " -> " + dateNew);
  4373. //var dateNew2 = dateStd.toLocaleString() + gmtStr;
  4374. //console.log("Time: " + dateTime + " -> " + dateNew2);
  4375. var nodeValBegin = nodeVal.substr(0, nodeVal.indexOf(dateTime));
  4376. var nodeValEnd = nodeVal.substr(nodeVal.indexOf(dateTime) + dateTime.length);
  4377. nodes[j].nodeValue = nodeValBegin;
  4378. var ele = document.createElement("span");
  4379. ele.classList.add("stsh_time_convert");
  4380. ele.classList.add("stsh_cursor_help");
  4381. ele.setAttribute("title", dateTime);
  4382. ele.textContent = dateNew;
  4383. insertAfterElement(ele, nodes[j]);
  4384. if (nodeValEnd !== "")
  4385. {
  4386. insertAfterElement(document.createTextNode(nodeValEnd), ele);
  4387. }
  4388. }
  4389. else
  4390. {
  4391. console.log("Invalid Date: " + dateTimeStd);
  4392. }
  4393. }
  4394. }
  4395. }
  4396. }
  4397. }
  4398. // Fix STS PM functions
  4399. {
  4400. var elesSpan = document.querySelectorAll(".friend_block_avatar > span[onclick^='totranslator']");
  4401. for (var i = 0; i < elesSpan.length; i++)
  4402. {
  4403. var eleUser = elesSpan[i].parentElement.firstElementChild;
  4404. if (eleUser.tagName === "A")
  4405. {
  4406. var execUser = /user=([0-9]+)/i.exec(eleUser.getAttribute("href"));
  4407. if (execUser && execUser.length === 2)
  4408. {
  4409. var attrClick = elesSpan[i].getAttribute("onclick");
  4410. var execTranslator = /totranslator\('([0-9]+)'\)/i.exec(attrClick);
  4411. if (execTranslator && execTranslator.length === 2)
  4412. {
  4413. if (execUser[1] !== execTranslator[1])
  4414. {
  4415. elesSpan[i].setAttribute("onclick", "totranslator('" + execUser[1] + "')");
  4416. }
  4417. }
  4418. }
  4419. }
  4420. }
  4421. }
  4422. // Add Steam profile links
  4423. {
  4424. var elesSpan = document.querySelectorAll("span[title='Send this user a private message']");
  4425. for (var i = 0; i < elesSpan.length; i++)
  4426. {
  4427. var attrClick = elesSpan[i].getAttribute("onclick");
  4428. var execTranslator = /totranslator\('([0-9]+)'\)/i.exec(attrClick);
  4429. if (execTranslator && execTranslator.length === 2)
  4430. {
  4431. var ele = document.createElement("a");
  4432. ele.classList.add("stsh_steamProfile");
  4433. ele.setAttribute("target", "_blank");
  4434. ele.setAttribute("title", "View Steam profile");
  4435. ele.setAttribute("href", "https://steamcommunity.com/profiles/" + execTranslator[1]);
  4436. var name = "Steam";
  4437. var eleParent = elesSpan[i].parentElement;
  4438. if (eleParent.classList.contains("friend_block_avatar"))
  4439. {
  4440. var eleImg = eleParent.querySelector("a[href^='user_activity.php'] > img");
  4441. if (eleImg && eleImg.title && eleImg.title.trim())
  4442. {
  4443. name = eleImg.title.trim();
  4444. }
  4445. }
  4446. else if (eleParent.tagName === "TD")
  4447. {
  4448. var eleImg = eleParent.parentElement.querySelector(
  4449. "td > .friend_block_discussions > a[href^='user_activity.php'] > img");
  4450. if (eleImg && eleImg.title && eleImg.title.trim())
  4451. {
  4452. name = eleImg.title.trim();
  4453. }
  4454. }
  4455. ele.textContent = " " + name + " ";
  4456. var eleNext = elesSpan[i].nextSibling;
  4457. if (eleNext && eleNext.textContent.trim() === "")
  4458. {
  4459. eleNext.textContent = " | ";
  4460. }
  4461. insertAfterElement(ele, elesSpan[i]);
  4462. }
  4463. }
  4464. }
  4465. // Add auto approve
  4466. {
  4467. if (elesInputApprove.length > 0 && document.querySelector(".stsh_action_approve_next"))
  4468. {
  4469. var eleInput = document.createElement("input");
  4470. eleInput.id = "stsh_autoApprove";
  4471. eleInput.setAttribute("type", "checkbox");
  4472. eleInput.setAttribute("value", "auto");
  4473. var eleLabel = document.createElement("label");
  4474. eleLabel.classList.add("stsh_autoApprove_label");
  4475. eleLabel.classList.add("stsh_unselectable");
  4476. eleLabel.setAttribute("for", "stsh_autoApprove");
  4477. eleLabel.setAttribute("title", "Please use with care!");
  4478. eleLabel.textContent = " Auto Approve Next ";
  4479. elesInputApprove[0].parentElement.appendChild(eleInput);
  4480. elesInputApprove[0].parentElement.appendChild(eleLabel);
  4481. var autoApprove = function()
  4482. {
  4483. console.log("AutoApprove: Next in " + timingInit.autoApprove + "ms");
  4484. setTimeoutCustom(function ()
  4485. {
  4486. var eleCheck = document.querySelector("#stsh_autoApprove");
  4487. if (eleCheck && eleCheck.checked)
  4488. {
  4489. var isClicked = false;
  4490. var ele = document.querySelector(".stsh_action_approve_next");
  4491. if (ele && !ele.disabled && isVisible())
  4492. {
  4493. var isSkip = false;
  4494. var eleSugComment = ele.parentElement
  4495. .parentElement.parentElement.querySelector(".stsh_text_comment font");
  4496. if (eleSugComment && eleSugComment.textContent.trim() ==
  4497. "ATTENTION - English string was updated. This suggestion might be outdated.")
  4498. {
  4499. isSkip = true;
  4500. }
  4501. if (!isSkip)
  4502. {
  4503. var eleStatusUnmatched = document.querySelector(".stsh_spanSpSug.stsh_status_unmatched");
  4504. if (eleStatusUnmatched)
  4505. {
  4506. isSkip = true;
  4507. }
  4508. }
  4509. if (!isSkip)
  4510. {
  4511. isClicked = true;
  4512. GM_setValue("timeAutoApproveLast", getUnixTimestamp());
  4513. ele.click();
  4514. }
  4515. }
  4516. if (!isClicked)
  4517. {
  4518. eleCheck.checked = false;
  4519. GM_setValue("isAutoApprove", "false");
  4520. }
  4521. }
  4522. }, timingInit.autoApprove);
  4523. }
  4524. var tmDiff = getUnixTimestamp() - GM_getValue("timeAutoApproveLast", 0);
  4525. if (tmDiff > 120)
  4526. {
  4527. // > 120s
  4528. eleInput.checked = false;
  4529. GM_setValue("isAutoApprove", "false");
  4530. }
  4531. if (window !== window.parent)
  4532. {
  4533. var eleOuter = window.parent.document.querySelector("#suggestions_box_outer");
  4534. if (eleOuter)
  4535. {
  4536. if (eleOuter.style.display === "none")
  4537. {
  4538. // Closed iFrame
  4539. eleInput.checked = false;
  4540. GM_setValue("isAutoApprove", "false");
  4541. }
  4542. }
  4543. }
  4544. if (GM_getValue("isAutoApprove", 0) === "true")
  4545. {
  4546. eleInput.checked = true;
  4547. autoApprove();
  4548. var uncheckAutoApprove = function (ev)
  4549. {
  4550. var eleTarget = ev.target;
  4551. if (eleTarget.id !== "stsh_autoApprove"
  4552. && !eleTarget.classList.contains("stsh_autoApprove_label")
  4553. && !eleTarget.classList.contains("stsh_action_approve_next"))
  4554. {
  4555. // Skip auto click
  4556. var eleAuto = document.querySelector("#stsh_autoApprove");
  4557. if (eleAuto)
  4558. {
  4559. console.log("AutoApprove: Stop");
  4560. eleAuto.checked = false;
  4561. GM_setValue("isAutoApprove", "false");
  4562. document.removeEventListener("click", uncheckAutoApprove);
  4563. }
  4564. }
  4565. };
  4566. // Stop with any clicked
  4567. document.addEventListener("click", uncheckAutoApprove);
  4568. }
  4569.  
  4570. eleInput.addEventListener("click", function (e)
  4571. {
  4572. var ele = e.target;
  4573. if (ele.checked)
  4574. {
  4575. GM_setValue("isAutoApprove", "true");
  4576. autoApprove();
  4577. }
  4578. else
  4579. {
  4580. GM_setValue("isAutoApprove", "false");
  4581. }
  4582. });
  4583. }
  4584. }
  4585. // Warn when remove
  4586. // Suggest to remove
  4587. // Add remove & next
  4588. {
  4589. var canNext = !!(document.querySelector(".stsh_nav_next:not(:disabled)"));
  4590. var elesRemove = document.querySelectorAll(".stsh_action_remove");
  4591. for (var i = 0; i < elesRemove.length; i++)
  4592. {
  4593. var isDisabled = false;
  4594. var oldClick = elesRemove[i].getAttribute("onclick");
  4595. if (oldClick && oldClick.indexOf("location.href") === 0)
  4596. {
  4597. var eleSug = elesRemove[i].parentElement.parentElement.parentElement.parentElement;
  4598. if (eleSug.classList.contains("suggestion"))
  4599. {
  4600. /*
  4601. // Typonion
  4602. var eleOnion = eleSug.querySelector(".suggestion_text font[style='color:#01ec00;']");
  4603. if (eleOnion)
  4604. {
  4605. var newClick = "if (!confirm(\"Warning: You will delete your onion. Press Cancel to go back.\")) return false; "
  4606. + oldClick;
  4607. elesRemove[i].setAttribute("onclick", newClick);
  4608. elesRemove[i].setAttribute("title", "Do not remove your onion!");
  4609. elesRemove[i].classList.add("stsh_grey");
  4610. elesRemove[i].classList.add("stsh_cursor_notallowed");
  4611. }
  4612. else
  4613. */
  4614. {
  4615. var eleModComment = elesRemove[i].parentElement.querySelector(".stsh_text_comment_header");
  4616. if (eleModComment)
  4617. {
  4618. // Mod commented, suggest to do not remove
  4619. var newClick = "if (!confirm(\"Warning: You should not remove this suggestion."
  4620. + " Press OK if you really want.\")) return false; "
  4621. + oldClick;
  4622. elesRemove[i].setAttribute("onclick", newClick);
  4623. elesRemove[i].setAttribute("title",
  4624. "Your suggestion has a mod's comment! \nShould not remove this suggestion.");
  4625. elesRemove[i].classList.add("stsh_grey");
  4626. elesRemove[i].classList.add("stsh_cursor_notallowed");
  4627. isDisabled = true;
  4628. }
  4629. else
  4630. {
  4631. var eleUserComment = elesRemove[i].parentElement.parentElement.parentElement
  4632. .querySelector(".stsh_text_comment_header");
  4633. if (eleUserComment)
  4634. {
  4635. // User commented
  4636. var comment = eleUserComment.textContent.trim();
  4637. if (comment.indexOf("ATTENTION - English string was updated.") > -1)
  4638. {
  4639. // Outdated, suggest to edit and remove
  4640. elesRemove[i].setAttribute("title",
  4641. "Please edit and remove this outdated suggestion.");
  4642. elesRemove[i].classList.add("stsh_green");
  4643. elesRemove[i].classList.add("stsh_border_green");
  4644. isDisabled = true;
  4645. }
  4646. }
  4647. }
  4648. if (!isDisabled)
  4649. {
  4650. var eleDeclined = elesRemove[i].parentElement.querySelector(".suggestion_status_declined");
  4651. if (eleDeclined)
  4652. {
  4653. // Declined without comment, suggest to remove
  4654. elesRemove[i].setAttribute("title",
  4655. "Please remove this suggestion to save admin time.");
  4656. elesRemove[i].classList.add("stsh_green");
  4657. elesRemove[i].classList.add("stsh_border_green");
  4658. }
  4659. }
  4660. }
  4661. }
  4662. }
  4663. // Add remove & next
  4664. {
  4665. elesRemove[i].classList.add("stsh_border_left");
  4666.  
  4667. var eleNext = elesRemove[i].nextElementSibling;
  4668. if (!eleNext || eleNext.value !== "Next")
  4669. {
  4670. eleNext = document.createElement("input");
  4671. insertAfterElement(eleNext, elesRemove[i]);
  4672. }
  4673. eleNext.value = "Next";
  4674. eleNext.classList.add("stsh_action_remove_next");
  4675. eleNext.classList.add("stsh_border_right");
  4676. eleNext.setAttribute("type", "button");
  4677. if (canNext && !isDisabled)
  4678. {
  4679. eleNext.title = "Remove & Next";
  4680. eleNext.classList.add("stsh_yellow_light");
  4681. if (!eleNext.getAttribute("onclick"))
  4682. {
  4683. var onclick = elesRemove[i].getAttribute("onclick")
  4684. .replace("';", "&ynext=true';");
  4685. eleNext.setAttribute("onclick", onclick);
  4686. }
  4687. }
  4688. else
  4689. {
  4690. eleNext.disabled = true;
  4691. }
  4692. }
  4693. }
  4694. }
  4695. // Suggest to decline outdated
  4696. {
  4697. if (document.querySelector(".stsh_action_approve"))
  4698. {
  4699. var elesAttention = document.querySelectorAll(".stsh_text_comment > font > i > b");
  4700. for (var i = 0; i < elesAttention.length; i++)
  4701. {
  4702. if (elesAttention[i].textContent.trim()
  4703. === "ATTENTION - English string was updated. This suggestion might be outdated.")
  4704. {
  4705. var eleAction = elesAttention[i]
  4706. .parentElement.parentElement
  4707. .parentElement.parentElement
  4708. .nextElementSibling;
  4709. var eleApprove = eleAction.querySelector(".stsh_action_approve");
  4710. var eleApproveNext = null;
  4711. var eleDecline = null;
  4712. if (eleApprove)
  4713. {
  4714. eleApproveNext = eleApprove.nextElementSibling;
  4715. var oldClick = eleApprove.getAttribute("onclick");
  4716. if (oldClick && oldClick.indexOf("location.href") === 0)
  4717. {
  4718. var newClick = "if (!confirm(\"Warning: Please decline outdated suggestion."
  4719. + " Press OK if you really want to approve.\")) return false; "
  4720. + oldClick;
  4721. eleApprove.setAttribute("onclick", newClick);
  4722. eleApprove.setAttribute("title", "Please decline outdated suggestion.");
  4723. eleApprove.classList.add("stsh_grey");
  4724. eleApprove.classList.add("stsh_cursor_notallowed");
  4725. }
  4726. }
  4727. if (eleApproveNext)
  4728. {
  4729. eleDecline = eleApproveNext.nextElementSibling;
  4730. if (!eleApproveNext.disabled)
  4731. {
  4732. var oldClick = eleApproveNext.getAttribute("onclick");
  4733. if (oldClick && oldClick.indexOf("location.href") === 0)
  4734. {
  4735. var newClick = "if (!confirm(\"Warning: Please decline outdated suggestion."
  4736. + " Press OK if you really want to approve.\")) return false; "
  4737. + oldClick;
  4738. eleApproveNext.setAttribute("onclick", newClick);
  4739. eleApproveNext.setAttribute("title", "Please decline outdated suggestion.");
  4740. eleApproveNext.classList.add("stsh_grey");
  4741. eleApproveNext.classList.add("stsh_cursor_notallowed");
  4742. }
  4743. }
  4744. }
  4745. if (eleDecline)
  4746. {
  4747. eleDecline.setAttribute("title", "Please decline outdated suggestion.");
  4748. eleDecline.classList.add("stsh_green");
  4749. eleDecline.classList.add("stsh_border_green_left");
  4750. }
  4751. }
  4752. }
  4753. }
  4754. }
  4755. // Clean language markers that link to Steam
  4756. {
  4757. var rgxLang = /[\?&]l=[a-z]+$/i;
  4758. var elesDiscussText = document.querySelectorAll(".stsh_discussion_text");
  4759. for (var i = 0; i < elesDiscussText.length; i++)
  4760. {
  4761. var elesA = elesDiscussText[i].querySelectorAll("a[href*='steam']");
  4762. for (var j = 0; j < elesA.length; j++)
  4763. {
  4764. var href = elesA[j].getAttribute("href");
  4765. if (rgxLang.test(href))
  4766. {
  4767. elesA[j].setAttribute("href", href.replace(rgxLang, ""));
  4768. }
  4769. }
  4770. }
  4771. }
  4772. // Auto paste last suggestion
  4773. {
  4774. if (!/edit/i.test(getQueryByName("action")))
  4775. {
  4776. if (eleTextOrg)
  4777. {
  4778. var textOrg = eleTextOrg.dataset.stshHtml.toLowerCase();
  4779. var textLastCur = "";
  4780. if (textOrg === GM_getValue("textLastOrg", ""))
  4781. {
  4782. textLastCur = GM_getValue("textLastCur", "");
  4783. }
  4784. else if (textOrg === GM_getValue("textLastOrg_Comment", ""))
  4785. {
  4786. //textLastCur = GM_getValue("textLastCur_Comment", "");
  4787. }
  4788. var eleTextCur = document.querySelector("#suggestion_value_new");
  4789. if (eleTextCur)
  4790. {
  4791. if (textLastCur !== "")
  4792. {
  4793. eleTextCur.value = textLastCur;
  4794. }
  4795. }
  4796. if (textLastCur !== "")
  4797. {
  4798. setTimeoutCustom(function(textLastCur)
  4799. {
  4800. var eleTextCur = document.querySelector("#suggestion_value_new");
  4801. if (eleTextCur)
  4802. {
  4803. eleTextCur.value = textLastCur;
  4804. }
  4805. }, timingInit.pasteLastSuggestion, textLastCur);
  4806. }
  4807. }
  4808. }
  4809. var elesTextSubmit = document.querySelectorAll(".stsh_text_submit, #stsh_text_submit_next");
  4810. for (var i = 0; i < elesTextSubmit.length; i++)
  4811. {
  4812. elesTextSubmit[i].addEventListener("click", function()
  4813. {
  4814. var eleTextOrg = document.querySelector(".stsh_text_org");
  4815. if (eleTextOrg)
  4816. {
  4817. var textOrg = eleTextOrg.dataset.stshHtml;
  4818. if (textOrg.length < 3000)
  4819. {
  4820. var eleTextCur = document.querySelector("#suggestion_value_new");
  4821. if (eleTextCur)
  4822. {
  4823. var textCur = eleTextCur.value;
  4824. GM_setValue("textLastOrg", textOrg.toLowerCase());
  4825. GM_setValue("textLastCur", textCur);
  4826. //console.log("Store suggestion: " + textOrg.length);
  4827. }
  4828. }
  4829. }
  4830. });
  4831. }
  4832. }
  4833. // Auto store last comment
  4834. {
  4835. //console.log("textLastOrg_Comment: " + GM_getValue("textLastOrg_Comment", ""));
  4836. //console.log("textLastCur_Comment: " + GM_getValue("textLastCur_Comment", ""));
  4837. var storeLastComment = function(eleTextComment, isRemoved)
  4838. {
  4839. if (eleTextComment)
  4840. {
  4841. var eleTextOrg = document.querySelector(".stsh_text_org");
  4842. if (eleTextOrg)
  4843. {
  4844. var textOrg = eleTextOrg.dataset.stshHtml.substr(0, 3000).toLowerCase();
  4845. if (isRemoved)
  4846. {
  4847. if (textOrg === GM_getValue("textLastOrg_Comment", ""))
  4848. {
  4849. // When remove comment, don't store if original text is the same
  4850. return;
  4851. }
  4852. }
  4853. var textCur = trimSpace(eleTextComment.value || eleTextComment.textContent);
  4854. if (textCur !== "outdated")
  4855. {
  4856. GM_setValue("textLastOrg_Comment", textOrg);
  4857. GM_setValue("textLastCur_Comment", textCur);
  4858. }
  4859. }
  4860. }
  4861. }
  4862. for (var i = 0; i < elesTextRemoveComment.length; i++)
  4863. {
  4864. elesTextRemoveComment[i].addEventListener("click", function(ev)
  4865. {
  4866. var target = null;
  4867. if (ev.target.tagName === "FONT")
  4868. {
  4869. target = ev.target.parentElement;
  4870. }
  4871. else
  4872. {
  4873. target = ev.target;
  4874. }
  4875. var eleTextComment = target
  4876. .parentElement.parentElement.parentElement.parentElement
  4877. .querySelector(".stsh_text_comment");
  4878. storeLastComment(eleTextComment, true);
  4879. });
  4880. }
  4881. var elesSubmitComment = document.querySelectorAll(".stsh_submit_comment");
  4882. for (var i = 0; i < elesSubmitComment.length; i++)
  4883. {
  4884. elesSubmitComment[i].addEventListener("click", function(ev)
  4885. {
  4886. var eleTextComment = ev.target.previousElementSibling;
  4887. if (eleTextComment.tagName !== "TEXTAREA")
  4888. {
  4889. eleTextComment = eleTextComment.previousElementSibling;
  4890. }
  4891. storeLastComment(eleTextComment, false);
  4892. });
  4893. }
  4894. }
  4895. // Mark showing
  4896. {
  4897. var eleStatus = window.parent.document.querySelector("#stsh_showing_random");
  4898. if (eleStatus)
  4899. {
  4900. eleStatus.dataset.random = getTimeMs();
  4901. }
  4902. }
  4903. // Delta
  4904. {
  4905. var eleFile = document.querySelector(".stsh_info_file");
  4906. if (eleFile)
  4907. {
  4908. if (eleFile.textContent.trim() === "STEAM/DELTA")
  4909. {
  4910. document.body && document.body.classList.add("stsh_delta");
  4911. }
  4912. }
  4913. }
  4914. // Hide cursor when typing
  4915. // Expand textarea when typing
  4916. {
  4917. var tmTextChange = 0;
  4918. var autoHideCursor = function(ele)
  4919. {
  4920. if (ele)
  4921. {
  4922. ele.addEventListener("input", function(ev)
  4923. {
  4924. var ele = ev.target;
  4925. ele.style.setProperty("cursor", "none", "important");
  4926. clearTimeout(tmTextChange);
  4927. tmTextChange = setTimeoutCustom(function(ele)
  4928. {
  4929. ele.style.setProperty("cursor", "auto", "important");
  4930. }, timingInit.hideCursor, ele);
  4931. });
  4932. ele.addEventListener("mousemove", function(ev)
  4933. {
  4934. var ele = ev.target;
  4935. clearTimeout(tmTextChange);
  4936. ele.style.setProperty("cursor", "auto", "important");
  4937. });
  4938. }
  4939. }
  4940. var autoExpandEvent = function(ev)
  4941. {
  4942. var ele = ev.target;
  4943. var maxHeight = ele.param_MaxHeight;
  4944. var styleHeight = parseInt(ele.style.height)
  4945. || parseInt(window.getComputedStyle(ele).height)
  4946. || maxHeight;
  4947. var heightDiff = ele.scrollHeight - styleHeight;
  4948. //console.log("ele.scrollHeight:"+ele.scrollHeight+", styleHeight:"+styleHeight+", heightDiff:"+heightDiff);
  4949. // When press a button
  4950. // Chrome: heightDiff === 4
  4951. // Firefox: heightDiff === 0
  4952. if ((heightDiff > 0 && heightDiff !== 4) && ele.scrollHeight < maxHeight)
  4953. {
  4954. ele.style.height = (ele.scrollHeight + 2) + "px";
  4955. }
  4956. else if (ele.scrollHeight > maxHeight && ele.scrollHeight - maxHeight < 100)
  4957. {
  4958. ele.style.height = maxHeight + "px";
  4959. }
  4960. }
  4961. var autoExpandEventTextarea = function(ele, maxHeight)
  4962. {
  4963. if (ele)
  4964. {
  4965. ele.param_MaxHeight = maxHeight;
  4966. ele.addEventListener("input", autoExpandEvent);
  4967. ele.addEventListener("keyup", autoExpandEvent);
  4968. }
  4969. }
  4970. setTimeoutCustom(function()
  4971. {
  4972. var elesTextarea = document.querySelectorAll("textarea");
  4973. for (var i = 0; i < elesTextarea.length; i++)
  4974. {
  4975. autoExpandEventTextarea(elesTextarea[i], 500);
  4976. autoHideCursor(elesTextarea[i]);
  4977. }
  4978. }, timingInit.expandTextarea);
  4979. }
  4980. // Focus on mod action
  4981. {
  4982. var elesFormRemoveComment = document.querySelectorAll(".suggestion_signature .lbAction[name^='mymodcomment']");
  4983. for (var i = 0; i < elesFormRemoveComment.length; i++)
  4984. {
  4985. var action = elesFormRemoveComment[i].getAttribute("action");
  4986. if (action.indexOf("#stsh_modcomment") < 0)
  4987. {
  4988. elesFormRemoveComment[i].setAttribute("action", action + "#stsh_modcomment");
  4989. }
  4990. }
  4991. var elesSubmitComment = document.querySelectorAll(
  4992. ".suggestion_signature > div > div > .copy > form > div > .stsh_submit_comment");
  4993. for (var i = 0; i < elesSubmitComment.length; i++)
  4994. {
  4995. var eleForm = elesSubmitComment[i].parentElement.parentElement;
  4996. if (eleForm.tagName === "FORM")
  4997. {
  4998. var action = eleForm.getAttribute("action");
  4999. if (action.indexOf("#stsh_modcomment") < 0)
  5000. {
  5001. eleForm.setAttribute("action", action + "#stsh_modcomment");
  5002. }
  5003. }
  5004. }
  5005. if (/reconsider|approve|decline/i.test(getQueryByName("action")) || url.indexOf("#stsh_modcomment") > -1)
  5006. {
  5007. setTimeoutCustom(function()
  5008. {
  5009. if (eleTextNew && eleTextOrg)
  5010. {
  5011. if (eleTextNew.scrollHeight > 480 || eleTextOrg.scrollHeight > 480)
  5012. {
  5013. scrollToElement(".suggestions_list", -40);
  5014. }
  5015. else if (eleTextNew.scrollHeight > 120 || eleTextOrg.scrollHeight > 200)
  5016. {
  5017. var elesEdit = document.querySelectorAll(".stsh_action_edit");
  5018. if (elesEdit.length > 1)
  5019. {
  5020. scrollToElement(".suggestions_list", -40);
  5021. }
  5022. }
  5023. }
  5024. }, timingInit.focusModAction);
  5025. }
  5026. }
  5027. // Add char, word and byte count
  5028. {
  5029. var countCharWordByte = function(ele)
  5030. {
  5031. var countChar = 0;
  5032. var countWord = 0;
  5033. var countByte = 0;
  5034. if (ele)
  5035. {
  5036. var text = ele.value || (ele.value === "" ? "" : ele.textContent);
  5037. countChar = text.length;
  5038. var arrWord = trimSpace(text).split(/\s+/);
  5039. if (arrWord.length === 1)
  5040. {
  5041. if (trimSpace(arrWord[0]).length > 0)
  5042. {
  5043. countWord = 1;
  5044. }
  5045. }
  5046. else
  5047. {
  5048. countWord = arrWord.length;
  5049. }
  5050. countByte = getByteCount(text);
  5051. }
  5052. return "Char: " + countChar + " :: Word: " + countWord + " :: Byte: " + countByte;
  5053. }
  5054.  
  5055. var elesText = document.querySelectorAll("#suggestion_value_new, .stsh_text_addComment, #add_to_discussion");
  5056. for (var i = 0; i < elesText.length; i++)
  5057. {
  5058. var eleCounter = document.createElement("div");
  5059. eleCounter.classList.add("stsh_counter");
  5060. eleCounter.classList.add("stsh_blue_light");
  5061. eleCounter.classList.add("stsh_cursor_help");
  5062. eleCounter.dataset.counter = countCharWordByte(elesText[i]);
  5063. eleCounter.title = "Chars and words are approximate values. "
  5064. + "\nYou should add a comment or a discussion using less than 1020 bytes.";
  5065. insertAfterElement(eleCounter, elesText[i]);
  5066. elesText[i].addEventListener("input", function(ev)
  5067. {
  5068. var eleTarget = ev.target;
  5069. var eleCounter = eleTarget.nextElementSibling;
  5070. if (eleCounter && eleCounter.classList.contains("stsh_counter"))
  5071. {
  5072. eleCounter.dataset.counter = countCharWordByte(eleTarget);
  5073. }
  5074. });
  5075. }
  5076. /*elesText = document.querySelectorAll(".stsh_text_org, .stsh_text_trn:not(.stsh_text_trn_empty), .suggestion_text");
  5077. for (var i = 0; i < elesText.length; i++)
  5078. {
  5079. ////
  5080. }*/
  5081. }
  5082. // Warn before closing frame
  5083. {
  5084. if (window !== window.parent)
  5085. {
  5086. var eleOuter = window.parent.document.querySelector("#suggestions_box_outer");
  5087. if (eleOuter)
  5088. {
  5089. eleOuter.dataset.stshTextEdited = "false";
  5090. eleOuter.title = "";
  5091. var markEdited = function(ev)
  5092. {
  5093. if (!ev.ctrlKey && !ev.altKey)
  5094. {
  5095. if (eleOuter && eleOuter.dataset)
  5096. {
  5097. eleOuter.dataset.stshTextEdited = "true";
  5098. eleOuter.title = "When some texts were edited. \nYou must double click to close suggestion box.";
  5099. removeEventsMarkEdited();
  5100. }
  5101. }
  5102. };
  5103. var removeEventsMarkEdited = function()
  5104. {
  5105. var elesText = document.querySelectorAll("#suggestion_value_new, .stsh_text_addComment, #add_to_discussion");
  5106. for (var i = 0; i < elesText.length; i++)
  5107. {
  5108. elesText[i].removeEventListener("keydown", markEdited);
  5109. }
  5110. };
  5111. var elesText = document.querySelectorAll("#suggestion_value_new, .stsh_text_addComment, #add_to_discussion");
  5112. for (var i = 0; i < elesText.length; i++)
  5113. {
  5114. elesText[i].addEventListener("keydown", markEdited);
  5115. }
  5116. }
  5117. }
  5118. }
  5119. // Open auto replace form when applied
  5120. {
  5121. var eleStatus = document.querySelector("#replacementstatus");
  5122. if (eleStatus)
  5123. {
  5124. var eleAutoCopy = document.querySelector("#autocopy");
  5125. if (eleAutoCopy)
  5126. {
  5127. eleAutoCopy.style.display = "";
  5128. }
  5129. }
  5130. }
  5131. // Add auto-replacement for suggestion box
  5132. {
  5133. var eleAutoCopy = document.querySelector("#autocopy");
  5134. if (eleAutoCopy)
  5135. {
  5136. var eleBlock = null;
  5137. var eleHeader = null;
  5138. var eleForm = null;
  5139. var eleInstruction = null;
  5140. var eleMarker = null;
  5141. var eleDefine = null;
  5142. var eleMore = null;
  5143. var eleEnabled = null;
  5144. var eleEnabledLabel = null;
  5145. var eleEnabledContent = null;
  5146. var eleCase = null;
  5147. var eleCaseLabel = null;
  5148. var eleCaseContent = null;
  5149. var eleRgx = null;
  5150. var eleRgxLabel = null;
  5151. var eleRgxContent = null;
  5152. var addAutoReplaceText = function(eleMarker, textOrg, textDef)
  5153. {
  5154. textOrg = (typeof textOrg !== "undefined") ? textOrg : "";
  5155. textDef = (typeof textDef !== "undefined") ? textDef : "";
  5156. if (eleMarker)
  5157. {
  5158. var eleTextOrg = document.createElement("textarea");
  5159. eleTextOrg.classList.add("stsh_autoReplace_text");
  5160. eleTextOrg.classList.add("stsh_autoReplace_text_org");
  5161. eleTextOrg.setAttribute("rows", "1");
  5162. eleTextOrg.setAttribute("placeholder", "Your language or english text to be autoreplaced");
  5163. eleTextOrg.value = textOrg;
  5164. var eleTextDef = document.createElement("textarea");
  5165. eleTextDef.classList.add("stsh_autoReplace_text");
  5166. eleTextDef.classList.add("stsh_autoReplace_text_def");
  5167. eleTextDef.setAttribute("rows", "1");
  5168. eleTextDef.setAttribute("placeholder", "Translation");
  5169. eleTextDef.value = textDef;
  5170. insertBeforeElement(eleTextOrg, eleMarker);
  5171. insertBeforeElement(document.createTextNode(" "), eleMarker);
  5172. insertBeforeElement(eleTextDef, eleMarker);
  5173. insertBeforeElement(document.createElement("br"), eleMarker);
  5174. }
  5175. }
  5176. // Add elements
  5177. {
  5178. eleBlock = document.createElement("div");
  5179. eleBlock.classList.add("stsh_autoReplace_block");
  5180. insertAfterElement(eleBlock, eleAutoCopy);
  5181. eleHeader = document.createElement("div");
  5182. eleHeader.classList.add("stsh_autoReplace_header");
  5183. eleHeader.classList.add("stsh_green");
  5184. eleHeader.classList.add("stsh_cursor_pointer");
  5185. eleHeader.textContent = "AUTO-REPLACEMENT FOR SUGGESTION BOX";
  5186. eleHeader.setAttribute("onclick", "$('.stsh_autoReplace_form').toggle('blind', 300);");
  5187. eleBlock.appendChild(document.createElement("br"));
  5188. eleBlock.appendChild(eleHeader);
  5189. eleForm = document.createElement("form");
  5190. eleForm.classList.add("stsh_form");
  5191. eleForm.classList.add("stsh_autoReplace_form");
  5192. eleForm.style.display = "none";
  5193. eleBlock.appendChild(eleForm);
  5194. eleInstruction = document.createElement("div");
  5195. eleInstruction.classList.add("stsh_autoReplace_instruction");
  5196. eleInstruction.innerHTML =
  5197. " \
  5198. Auto-replacements for current text in suggestion box. These will replace anything in your current text in suggestion box. \
  5199. <br> You can use these to replace translated strings that you need to correct them. \
  5200. These will be processed after other replacements applied. \
  5201. <br> You can enable/disable replacements, case-sensitive mode and RegExp mode by using checkboxes below. \
  5202. ";
  5203. eleForm.appendChild(eleInstruction);
  5204. eleForm.appendChild(document.createElement("br"));
  5205. eleMarker = document.createElement("div");
  5206. eleMarker.classList.add("stsh_autoReplace_marker");
  5207. eleForm.appendChild(eleMarker);
  5208. eleDefine = document.createElement("input");
  5209. eleDefine.classList.add("stsh_autoReplace_define");
  5210. eleDefine.setAttribute("onclick", "return false;");
  5211. eleDefine.type = "submit";
  5212. eleDefine.value = "Define";
  5213. eleDefine.title = "Define auto-replacements and refresh this page";
  5214. eleMore = document.createElement("input");
  5215. eleMore.classList.add("stsh_autoReplace_more");
  5216. eleMore.setAttribute("onclick", "return false;");
  5217. eleMore.type = "button";
  5218. eleMore.value = "Add More";
  5219. eleMore.title = "Add a new auto-replacement";
  5220. // Checkbox enabled
  5221. {
  5222. eleEnabled = document.createElement("input");
  5223. eleEnabled.classList.add("stsh_autoReplace_enabled");
  5224. eleEnabled.setAttribute("type", "checkbox");
  5225. eleEnabled.setAttribute("value", "true");
  5226. eleEnabledLabel = document.createElement("label");
  5227. eleEnabledLabel.classList.add("stsh_checkbox_label");
  5228. eleEnabledLabel.classList.add("stsh_autoReplace_enabled_label");
  5229. eleEnabledLabel.classList.add("stsh_unselectable");
  5230. eleEnabledLabel.classList.add("stsh_cursor_pointer");
  5231. eleEnabledContent = document.createElement("span");
  5232. eleEnabledContent.textContent = " Enable Auto-replacements";
  5233. eleEnabledLabel.appendChild(eleEnabled);
  5234. eleEnabledLabel.appendChild(eleEnabledContent);
  5235. }
  5236. // Checkbox case
  5237. {
  5238. eleCase = document.createElement("input");
  5239. eleCase.classList.add("stsh_autoReplace_case");
  5240. eleCase.setAttribute("type", "checkbox");
  5241. eleCase.setAttribute("value", "true");
  5242. eleCaseLabel = document.createElement("label");
  5243. eleCaseLabel.classList.add("stsh_checkbox_label");
  5244. eleCaseLabel.classList.add("stsh_autoReplace_case_label");
  5245. eleCaseLabel.classList.add("stsh_unselectable");
  5246. eleCaseLabel.classList.add("stsh_cursor_pointer");
  5247. eleCaseContent = document.createElement("span");
  5248. eleCaseContent.textContent = " Case-sensitive";
  5249. eleCaseLabel.appendChild(eleCase);
  5250. eleCaseLabel.appendChild(eleCaseContent);
  5251. }
  5252. // Checkbox regexp
  5253. {
  5254. eleRgx = document.createElement("input");
  5255. eleRgx.classList.add("stsh_autoReplace_rgx");
  5256. eleRgx.setAttribute("type", "checkbox");
  5257. eleRgx.setAttribute("value", "true");
  5258. eleRgxLabel = document.createElement("label");
  5259. eleRgxLabel.classList.add("stsh_checkbox_label");
  5260. eleRgxLabel.classList.add("stsh_autoReplace_rgx_label");
  5261. eleRgxLabel.classList.add("stsh_unselectable");
  5262. eleRgxLabel.classList.add("stsh_cursor_pointer");
  5263. eleRgxContent = document.createElement("span");
  5264. eleRgxContent.textContent = " Use RegExp";
  5265. eleRgxLabel.appendChild(eleRgx);
  5266. eleRgxLabel.appendChild(eleRgxContent);
  5267. }
  5268. eleForm.appendChild(document.createElement("br"));
  5269. eleForm.appendChild(eleDefine);
  5270. eleForm.appendChild(document.createTextNode(" "));
  5271. eleForm.appendChild(eleMore);
  5272. eleForm.appendChild(document.createTextNode(" "));
  5273. eleForm.appendChild(eleEnabledLabel);
  5274. eleForm.appendChild(document.createTextNode(" "));
  5275. eleForm.appendChild(eleCaseLabel);
  5276. eleForm.appendChild(document.createTextNode(" "));
  5277. eleForm.appendChild(eleRgxLabel);
  5278. eleForm.appendChild(document.createElement("br"));
  5279. eleForm.appendChild(document.createElement("br"));
  5280. } // Add elements
  5281. // Bind events
  5282. {
  5283. var defineAutoReplaceText = function()
  5284. {
  5285. var objText = {};
  5286. var elesTextOrg = document.querySelectorAll(".stsh_autoReplace_text_org");
  5287. for (var i = 0; i < elesTextOrg.length; i++)
  5288. {
  5289. var eleTextOrg = elesTextOrg[i];
  5290. var eleTextDef = eleTextOrg.nextElementSibling;
  5291. var textOrg = eleTextOrg.value;
  5292. var textDef = eleTextDef.value;
  5293. var index = "text" + i;
  5294. objText[index] = {};
  5295. objText[index].textOrg = textOrg;
  5296. objText[index].textDef = textDef;
  5297. }
  5298. GM_setValue("autoReplace_text", objText);
  5299. reload();
  5300. };
  5301. eleDefine.addEventListener("click", defineAutoReplaceText);
  5302. eleMore.addEventListener("click", function()
  5303. {
  5304. var eleMarker = document.querySelector(".stsh_autoReplace_marker");
  5305. addAutoReplaceText(eleMarker);
  5306. });
  5307. eleEnabled.addEventListener("click", function (ev)
  5308. {
  5309. var ele = ev.target;
  5310. GM_setValue("autoReplace_enabled", ele.checked ? "true" : "false");
  5311. });
  5312. eleCase.addEventListener("click", function (ev)
  5313. {
  5314. var ele = ev.target;
  5315. GM_setValue("autoReplace_case", ele.checked ? "true" : "false");
  5316. });
  5317. eleRgx.addEventListener("click", function (ev)
  5318. {
  5319. var ele = ev.target;
  5320. GM_setValue("autoReplace_rgx", ele.checked ? "true" : "false");
  5321. });
  5322. addKeyCtrlEnter(eleForm, eleDefine);
  5323. } // Bind events
  5324. // User defined value
  5325. {
  5326. var valEnabled = GM_getValue("autoReplace_enabled", 0);
  5327. if (valEnabled === "true")
  5328. {
  5329. eleEnabled.checked = true;
  5330. }
  5331. var valCase = GM_getValue("autoReplace_case", 0);
  5332. if (valCase === "true")
  5333. {
  5334. eleCase.checked = true;
  5335. }
  5336. var valRgx = GM_getValue("autoReplace_rgx", 0);
  5337. if (valRgx === "true")
  5338. {
  5339. eleRgx.checked = true;
  5340. }
  5341. var autoReplaceTextCount = 4;
  5342. var objText = GM_getValue("autoReplace_text", 0);
  5343. if (!objText)
  5344. {
  5345. objText = {};
  5346. }
  5347. else
  5348. {
  5349. for (var i = Object.keys(objText).length - 1; i > autoReplaceTextCount - 1; i--)
  5350. {
  5351. var index = "text" + i;
  5352. if (objText[index].textOrg !== "" || objText[index].textDef !== "")
  5353. {
  5354. autoReplaceTextCount = i + 1;
  5355. break;
  5356. }
  5357. }
  5358. // Auto replace text
  5359. if (valEnabled === "true")
  5360. {
  5361. var isTextReplaced = false;
  5362. // Skip this
  5363. /*
  5364. if (document.referrer === document.documentURI)
  5365. {
  5366. isTextReplaced = true;
  5367. }
  5368. */
  5369. if (!isTextReplaced && getQueryByName("action"))
  5370. {
  5371. isTextReplaced = true;
  5372. }
  5373. if (!isTextReplaced)
  5374. {
  5375. var eleError = document.querySelector(".suggestion_error");
  5376. if (eleError && eleError.textContent.trim() !== "")
  5377. {
  5378. isTextReplaced = true;
  5379. }
  5380. }
  5381. if (!isTextReplaced)
  5382. {
  5383. var eleBtnResummit = document.querySelector(".stsh_text_submit[value^='RESUBMIT']");
  5384. if (eleBtnResummit)
  5385. {
  5386. isTextReplaced = true;
  5387. }
  5388. }
  5389. if (!isTextReplaced)
  5390. {
  5391. setTimeoutCustom(function(objText)
  5392. {
  5393. var isTextReplaced = false;
  5394. var isRgx = (GM_getValue("autoReplace_rgx") === "true");
  5395. var isCase = (GM_getValue("autoReplace_case") === "true");
  5396. var keysText = Object.keys(objText);
  5397. for (var i = 0; i < keysText.length; i++)
  5398. {
  5399. var textOrg = objText[keysText[i]].textOrg;
  5400. if (textOrg !== "")
  5401. {
  5402. var textDef = objText[keysText[i]].textDef;
  5403. var eleTextNew = document.querySelector("#suggestion_value_new");
  5404. if (eleTextNew)
  5405. {
  5406. var textOld = eleTextNew.value;
  5407. var textNew = "";
  5408. var rgxOrg = null;
  5409. var rgxFlag = isCase ? "g" : "ig";
  5410. if (isRgx)
  5411. {
  5412. rgxOrg = new RegExp(textOrg, rgxFlag);
  5413. }
  5414. else
  5415. {
  5416. rgxOrg = new RegExp(escapeRegExp(textOrg), rgxFlag);
  5417. }
  5418. textNew = textOld.replace(rgxOrg, textDef);
  5419. if (textOld !== textNew)
  5420. {
  5421. isTextReplaced = true;
  5422. eleTextNew.value = textNew;
  5423. }
  5424. }
  5425. }
  5426. }
  5427. if (isTextReplaced)
  5428. {
  5429. var eleForm = document.querySelector(".stsh_autoReplace_form");
  5430. if (eleForm)
  5431. {
  5432. eleForm.style.display = "";
  5433. }
  5434. if (eleTextSubmit)
  5435. {
  5436. var eleDiv = document.createElement("div");
  5437. eleDiv.classList.add("stsh_autoReplace_notice");
  5438. eleDiv.classList.add("stsh_orange_light3");
  5439. eleDiv.textContent = "Auto-replacement for suggestion applied!";
  5440. eleTextSubmit.parentElement.appendChild(eleDiv);
  5441. }
  5442. }
  5443. }, timingInit.autoReplaceText, objText);
  5444. }
  5445. }
  5446. }
  5447. for (var i = 0; i < autoReplaceTextCount; i++)
  5448. {
  5449. var textOrg = "";
  5450. var textDef = "";
  5451. var index = "text" + i;
  5452. if (typeof objText[index] !== "undefined")
  5453. {
  5454. textOrg = objText[index].textOrg;
  5455. textDef = objText[index].textDef;
  5456. }
  5457. addAutoReplaceText(eleMarker, textOrg, textDef);
  5458. }
  5459. // Add one more empty row
  5460. addAutoReplaceText(eleMarker);
  5461. } // User defined value
  5462. }
  5463. } // Add auto-replacement for suggestion box
  5464. // Add scroll to top
  5465. // Find next unmatched
  5466. {
  5467. var eleInvert = document.querySelector("input[value='Invert display']");
  5468. if (eleInvert)
  5469. {
  5470. eleInvert.value = "Invert Display";
  5471. // Add scroll to top
  5472. {
  5473. var eleScroll = document.createElement("input");
  5474. eleScroll.classList.add("stsh_scrollToTop");
  5475. eleScroll.setAttribute("onclick", "return false;");
  5476. eleScroll.type = "button";
  5477. eleScroll.value = "Scroll to Top";
  5478. eleScroll.addEventListener("click", function (ev)
  5479. {
  5480. window.scrollTo(0, 0);
  5481. });
  5482. var eleContainer = document.createElement("div");
  5483. eleContainer.classList.add("stsh_bottom_container");
  5484. eleContainer.classList.add("stsh_inline");
  5485. eleContainer.appendChild(document.createTextNode(" "));
  5486. eleContainer.appendChild(eleScroll);
  5487. insertAfterElement(eleContainer, eleInvert);
  5488. }
  5489. // Find next unmatched
  5490. // Sample: https://translation.steampowered.com/translate.php?paginationrows=1000&search_input=%01
  5491. {
  5492. var eleUnmatched = document.createElement("input");
  5493. eleUnmatched.classList.add("stsh_nextUnmatched");
  5494. eleUnmatched.setAttribute("type", "checkbox");
  5495. eleUnmatched.setAttribute("value", "true");
  5496. var eleUnmatchedLabel = document.createElement("label");
  5497. eleUnmatchedLabel.classList.add("stsh_checkbox_label");
  5498. eleUnmatchedLabel.classList.add("stsh_nextUnmatched_label");
  5499. eleUnmatchedLabel.classList.add("stsh_unselectable");
  5500. eleUnmatchedLabel.classList.add("stsh_cursor_pointer");
  5501. eleUnmatchedLabel.title =
  5502. "Find next unmatched for special chars, combining diacritical marks, \nand HTML elements count. "
  5503. + "\nClick any position to stop finding.";
  5504. var eleUnmatchedContent = document.createElement("span");
  5505. eleUnmatchedContent.classList.add("stsh_nextUnmatched_content");
  5506. eleUnmatchedContent.textContent = " Find Next Unmatched";
  5507. eleUnmatchedLabel.appendChild(eleUnmatched);
  5508. eleUnmatchedLabel.appendChild(eleUnmatchedContent);
  5509. eleContainer.appendChild(document.createTextNode(" "));
  5510. eleContainer.appendChild(eleUnmatchedLabel);
  5511. var findNextUnmatched = function(isInitial)
  5512. {
  5513. isInitial = isInitial || false;
  5514. console.log("FindNextUnmatched: In " + timingInit.findNextUnmatched + "ms");
  5515. setTimeoutCustom(function()
  5516. {
  5517. var eleUnmatched = document.querySelector(".stsh_nextUnmatched");
  5518. if (eleUnmatched && eleUnmatched.checked)
  5519. {
  5520. var isClicked = false;
  5521. var eleNext = document.querySelector(".stsh_nav_next:not(:disabled)");
  5522. if (eleNext)
  5523. {
  5524. if (!isInitial)
  5525. {
  5526. var eleStatusUnmatched = document.querySelector(".stsh_status_unmatched");
  5527. if (eleStatusUnmatched)
  5528. {
  5529. isClicked = false;
  5530. if (eleStatusUnmatched.classList.contains("stsh_spanStatusTrn"))
  5531. {
  5532. if (document.querySelector(".stsh_spanStatusSug.stsh_status_matched"))
  5533. {
  5534. isClicked = true;
  5535. }
  5536. }
  5537. }
  5538. else
  5539. {
  5540. isClicked = true;
  5541. }
  5542. }
  5543. else
  5544. {
  5545. isClicked = true;
  5546. }
  5547. }
  5548. if (!isClicked)
  5549. {
  5550. eleUnmatched.checked = false;
  5551. GM_setValue("nextUnmatched", "false");
  5552. }
  5553. else
  5554. {
  5555. GM_setValue("timeNextUnmatchedLast", getUnixTimestamp());
  5556. eleNext.click();
  5557. }
  5558. }
  5559. }, timingInit.findNextUnmatched);
  5560. }
  5561. var tmDiff = getUnixTimestamp() - GM_getValue("timeNextUnmatchedLast", 0);
  5562. if (tmDiff > 10)
  5563. {
  5564. // > 10s
  5565. eleUnmatched.checked = false;
  5566. GM_setValue("nextUnmatched", "false");
  5567. }
  5568. if (window !== window.parent)
  5569. {
  5570. var eleOuter = window.parent.document.querySelector("#suggestions_box_outer");
  5571. if (eleOuter)
  5572. {
  5573. if (eleOuter.style.display === "none")
  5574. {
  5575. // Closed iFrame
  5576. eleUnmatched.checked = false;
  5577. GM_setValue("nextUnmatched", "false");
  5578. }
  5579. }
  5580. }
  5581. if (GM_getValue("nextUnmatched", 0) === "true")
  5582. {
  5583. eleUnmatched.checked = true;
  5584. findNextUnmatched();
  5585. var uncheckFindNextUnmatched = function (ev)
  5586. {
  5587. var eleTarget = ev.target;
  5588. if (eleTarget.id !== "stsh_btn_displaySpecialChars"
  5589. && !eleTarget.classList.contains("stsh_nextUnmatched")
  5590. && !eleTarget.classList.contains("stsh_nextUnmatched_content")
  5591. && !eleTarget.classList.contains("stsh_nav_next"))
  5592. {
  5593. // Skip auto click
  5594. var eleUnmatched = document.querySelector(".stsh_nextUnmatched");
  5595. if (eleUnmatched)
  5596. {
  5597. console.log("FindNextUnmatched: Stop");
  5598. eleUnmatched.checked = false;
  5599. GM_setValue("nextUnmatched", "false");
  5600. document.removeEventListener("click", uncheckFindNextUnmatched);
  5601. }
  5602. }
  5603. };
  5604. // Stop finding with any clicked
  5605. document.addEventListener("click", uncheckFindNextUnmatched);
  5606. // Display specialChars
  5607. var eleSpecialChars = document.querySelector("#stsh_btn_displaySpecialChars");
  5608. if (eleSpecialChars)
  5609. {
  5610. eleSpecialChars.click();
  5611. }
  5612. }
  5613. eleUnmatched.addEventListener("click", function (ev)
  5614. {
  5615. var eleTarget = ev.target;
  5616. if (eleTarget.checked)
  5617. {
  5618. GM_setValue("nextUnmatched", "true");
  5619. findNextUnmatched(true);
  5620. }
  5621. else
  5622. {
  5623. GM_setValue("nextUnmatched", "false");
  5624. }
  5625. });
  5626. }
  5627. }
  5628. }
  5629. // Add copy button
  5630. {
  5631. if (eleTextSubmit)
  5632. {
  5633. var eleInput = document.createElement("input");
  5634. eleInput.classList.add("stsh_copy_new");
  5635. eleInput.type = "button";
  5636. eleInput.value = "Copy";
  5637. eleInput.title = "Copy current suggestion to clipboard";
  5638. insertAfterElement(eleInput, eleTextSubmit);
  5639. eleInput.addEventListener("click", function()
  5640. {
  5641. var eleTextNew = document.querySelector("#suggestion_value_new");
  5642. if (eleTextNew)
  5643. {
  5644. GM_setClipboard(eleTextNew.value);
  5645. focusWithoutScroll(eleTextNew);
  5646. }
  5647. });
  5648. }
  5649. var titleExtra = "\nSome tags and attributes were generated or removed by STS. "
  5650. + "\nSingle quote ' may be changed to double quote \" "
  5651. + "\n and double quote \" may be added for attribute values by browser. ";
  5652. var elesEdit = document.querySelectorAll(".stsh_action_edit");
  5653. for (var i = 0; i < elesEdit.length; i++)
  5654. {
  5655. var eleInput = document.createElement("input");
  5656. eleInput.classList.add("stsh_copy_sug");
  5657. eleInput.classList.add("stsh_blue_light");
  5658. eleInput.type = "button";
  5659. eleInput.value = "Copy";
  5660. eleInput.title = "Copy this suggestion to clipboard. " + titleExtra;
  5661. insertBeforeElement(eleInput, elesEdit[i]);
  5662. eleInput.addEventListener("click", function(ev)
  5663. {
  5664. var eleTarget = ev.target;
  5665. var eleSug = eleTarget.parentElement.parentElement
  5666. .parentElement.parentElement
  5667. .querySelector(".stsh_text_sug");
  5668. if (eleSug)
  5669. {
  5670. var html = removeStsHtmlTags(eleSug);
  5671. if (html)
  5672. {
  5673. GM_setClipboard(html);
  5674. focusWithoutScroll("#suggestion_value_new");
  5675. }
  5676. }
  5677. });
  5678. }
  5679. if (eleHeaderOrg)
  5680. {
  5681. var eleInput = document.createElement("input");
  5682. eleInput.classList.add("stsh_copy_org");
  5683. eleInput.type = "button";
  5684. eleInput.value = "Copy";
  5685. eleInput.title = "Copy original string to clipboard. " + titleExtra;
  5686. insertAfterElement(eleInput, eleHeaderOrg.firstElementChild);
  5687. eleInput.addEventListener("click", function(ev)
  5688. {
  5689. var eleTextOrg = document.querySelector(".stsh_text_org");
  5690. if (eleTextOrg)
  5691. {
  5692. var html = removeStsHtmlTags(eleTextOrg);
  5693. if (html)
  5694. {
  5695. GM_setClipboard(html);
  5696. focusWithoutScroll("#suggestion_value_new");
  5697. }
  5698. }
  5699. });
  5700. }
  5701. if (eleHeaderTrn && eleTextTrn && !eleTextTrn.classList.contains("stsh_text_trn_empty"))
  5702. {
  5703. var eleInput = document.createElement("input");
  5704. eleInput.classList.add("stsh_copy_trn");
  5705. eleInput.type = "button";
  5706. eleInput.value = "Copy";
  5707. eleInput.title = "Copy translated string to clipboard. " + titleExtra;
  5708. insertAfterElement(eleInput, eleHeaderTrn.firstElementChild);
  5709. eleInput.addEventListener("click", function(ev)
  5710. {
  5711. var eleTextTrn = document.querySelector(".stsh_text_trn:not(.stsh_text_trn_empty)");
  5712. if (eleTextTrn)
  5713. {
  5714. var html = removeStsHtmlTags(eleTextTrn);
  5715. if (html)
  5716. {
  5717. GM_setClipboard(html);
  5718. focusWithoutScroll("#suggestion_value_new");
  5719. }
  5720. }
  5721. });
  5722. }
  5723. }
  5724. // Add border to related action
  5725. {
  5726. if (userName)
  5727. {
  5728. var eleSugHistory = document.querySelector(".stsh_suggestion_list_history");
  5729. if (eleSugHistory)
  5730. {
  5731. var isRelated = false;
  5732. var strName = "by " + userName + " ";
  5733. eleSugHistory.innerHTML = eleSugHistory.innerHTML.replace("<br>String: ",
  5734. '<br><span class="stsh_suggestion_list_history_header">String: </span>');
  5735. for (var i = 0; i < eleSugHistory.childNodes.length; i++)
  5736. {
  5737. var node = eleSugHistory.childNodes[i];
  5738. if (node.nodeType === document.TEXT_NODE)
  5739. {
  5740. var index = (node.textContent + " ").indexOf(strName);
  5741. if (index > -1 && index < 12)
  5742. {
  5743. isRelated = true;
  5744. break;
  5745. }
  5746. }
  5747. }
  5748. if (isRelated)
  5749. {
  5750. eleSugHistory.classList.add("stsh_suggestion_list_history_related");
  5751. var eleDiv = document.createElement("div");
  5752. eleDiv.innerHTML = eleSugHistory.innerHTML
  5753. .replace(new RegExp("by (" + escapeRegExp(userName) + ")", "g")
  5754. , function(match, p1, offset, string)
  5755. {
  5756. return 'by <span class="stsh_profile_name stsh_blue_light2 stsh_cursor_help"'
  5757. + ' title="This string is related with your action.">'
  5758. + p1.replace(/\</g, "&lt;") + '</span>';
  5759. });
  5760. eleSugHistory.innerHTML = eleDiv.innerHTML;
  5761. }
  5762. }
  5763. }
  5764. }
  5765. } // End suggestions.php
  5766.  
  5767. if (url.indexOf("translate.php") > -1)
  5768. {
  5769. document.body && document.body.classList.add("stsh_page_translate");
  5770. var searchText = getQueryByName("search_input");
  5771. if (searchText !== "")
  5772. {
  5773. if (searchText.indexOf("SUGGESTIONS FROM: ") === 0)
  5774. {
  5775. document.title = searchText.replace("SUGGESTIONS FROM: ", "") + " - " + document.title;
  5776. }
  5777. else if (searchText.indexOf("REVIEWS FROM: ") === 0)
  5778. {
  5779. document.title = searchText.replace("REVIEW: ", "") + " - " + document.title;
  5780. }
  5781. else
  5782. {
  5783. document.title = searchText + " - " + document.title;
  5784. }
  5785. }
  5786. else
  5787. {
  5788. var fileID = getQueryByName("file_ID");
  5789. if (fileID !== "")
  5790. {
  5791. var eleFile = document.querySelector("#leftAreaContainer label[for='chosenfile']");
  5792. if (eleFile)
  5793. {
  5794. var file = eleFile.textContent.trim();
  5795. if (file.indexOf("Limit search results to CURRENT FILE: ") === 0)
  5796. {
  5797. file = file.replace("Limit search results to CURRENT FILE: ", "");
  5798. var fileNew = file.split("#").reverse().join(" # ").trim();
  5799. document.title = fileNew + " - " + document.title;
  5800. }
  5801. }
  5802. }
  5803. else
  5804. {
  5805. var eleInput = document.querySelector("#search_input");
  5806. if (eleInput)
  5807. {
  5808. var valInput = eleInput.value.trim();
  5809. if (valInput.indexOf("SUGGESTIONS FROM: ") === 0)
  5810. {
  5811. document.title = valInput.replace("SUGGESTIONS FROM: ", "") + " - " + document.title;
  5812. }
  5813. else if (valInput.indexOf("REVIEWS FROM: ") === 0)
  5814. {
  5815. document.title = valInput.replace("REVIEWS FROM: ", "REVIEW: ") + " - " + document.title;
  5816. }
  5817. else if (valInput === "---DAYLIGHT SAVINGS BATTLE---")
  5818. {
  5819. document.title = "DAYLIGHT SAVINGS BATTLE - " + document.title;
  5820. }
  5821. }
  5822. }
  5823. }
  5824. var outer = document.querySelector("#suggestions_box_outer");
  5825. if (outer)
  5826. {
  5827. outer.setAttribute("onclick", "doubleClickHideSuggestion(this);");
  5828. outer.dataset.stshHideSuggestion = 0;
  5829. outer.dataset.stshTextEdited = "false";
  5830. }
  5831. var divBtn = document.createElement("div");
  5832. document.body.appendChild(divBtn);
  5833. divBtn.innerHTML =
  5834. ' \
  5835. <div class="stsh_showing_group"> \
  5836. <span class="stsh_showing_header">Hide</span>\
  5837. <br> &nbsp; <input id="stsh_showing_keyApp" value="App" data-hidekey="0" class="stsh_btn_short stsh_showing_key" type="button" /> \
  5838. <input id="stsh_showing_keyGame" value="Game" data-hidekey="1" class="stsh_btn_short stsh_showing_key" type="button" /> \
  5839. <br> &nbsp; <input id="stsh_showing_keyFaq" value="FAQ" data-hidekey="2" class="stsh_btn_short stsh_showing_key" type="button" /> \
  5840. <input id="stsh_showing_keySupport" value="Support" data-hidekey="3" class="stsh_btn_short stsh_showing_key" type="button" /> \
  5841. <br> &nbsp; <input id="stsh_showing_keyPromo" value="Promo" data-hidekey="4" class="stsh_btn_short stsh_showing_key" type="button" /> \
  5842. <input id="stsh_showing_keyEmail" value="Email" data-hidekey="5" class="stsh_btn_short stsh_showing_key" type="button" /> \
  5843. <br> \
  5844. <br> &nbsp; <input id="stsh_showing_strNotMatch" value="Hide not similar" data-hidestr="0" class="stsh_btn_long stsh_showing_str" type="button" /> \
  5845. <br> &nbsp; <input id="stsh_showing_strLong" value="Hide very long" data-hidestr="1" class="stsh_btn_long stsh_showing_str" type="button" /> \
  5846. \
  5847. <br> &nbsp; <span class="stsh_showing_header">Hide Suggestions</span>\
  5848. <br> &nbsp; <input id="stsh_showing_notTranslated" value="Not Translated (0)" data-hidestatus="0" class="stsh_btn_long stsh_showing_status" type="button" /> \
  5849. <br> &nbsp; <input id="stsh_showing_suggested" value="Suggested (0)" data-hidestatus="1" class="stsh_btn_long stsh_showing_status" type="button" /> \
  5850. <br> &nbsp; <input id="stsh_showing_resuggested" value="Resuggested (0)" data-hidestatus="2" class="stsh_btn_long stsh_showing_status" type="button" /> \
  5851. <br> &nbsp; <input id="stsh_showing_approved" value="Approved (0)" data-hidestatus="3" class="stsh_btn_long stsh_showing_status" type="button" /> \
  5852. <br> &nbsp; <input id="stsh_showing_declined" value="Declined (0)" data-hidestatus="4" class="stsh_btn_long stsh_showing_status" type="button" /> \
  5853. <br> &nbsp; <input id="stsh_showing_translated" value="Translated (0)" data-hidestatus="5" class="stsh_btn_long stsh_showing_status" type="button" /> \
  5854. \
  5855. <br> &nbsp; <span class="stsh_showing_header">Sort by</span>\
  5856. <br> &nbsp; <input id="stsh_sort_key" value="Key" data-sort="0" class="stsh_btn_short stsh_sort" type="button" /> \
  5857. <input id="stsh_sort_string" value="String" data-sort="1" class="stsh_btn_short stsh_sort" type="button" /> \
  5858. <br> &nbsp; <input id="stsh_sort_word" value="Word" data-sort="2" class="stsh_btn_short stsh_sort" type="button" /> \
  5859. <input id="stsh_sort_length" value="Length" data-sort="3" class="stsh_btn_short stsh_sort" type="button" /> \
  5860. <br> \
  5861. <br> &nbsp; <input id="stsh_showing_refresh" value="Refresh" class="stsh_btn" type="button" onclick="hideSuggestionsBox(); return false;" /> \
  5862. <br> &nbsp; <input id="stsh_showing_all" value="Show All" class="stsh_btn" type="button" /> \
  5863. <br> \
  5864. </div> \
  5865. <div id="stsh_showing_current"></div> \
  5866. <div id="stsh_showing"></div> \
  5867. ';
  5868.  
  5869. // Count showing
  5870. var countShowing = function()
  5871. {
  5872. var trKeys = document.querySelectorAll("#keylist > table:nth-child(1) > tbody:nth-child(1) > tr");
  5873. var countAll = document.querySelectorAll("#keylist .copysmall").length;
  5874. var countShow = 0;
  5875. var countSuggest = 0;
  5876. var countResuggest = 0;
  5877. var countApprove = 0;
  5878. var countDecline = 0;
  5879. var countNotTranslated = 0;
  5880. var countTranslated = 0;
  5881. var txtApprove = "ready for Admin";
  5882. var txtDecline = "ready for removal";
  5883. var txtSuggest = "suggestion";
  5884. for (var i = 0; i < trKeys.length; i++)
  5885. {
  5886. if (!trKeys[i].classList.contains("stsh_hidden"))
  5887. {
  5888. var eleCounter = trKeys[i].querySelector("tr.copysmall > td:nth-child(3)");
  5889. if (eleCounter)
  5890. {
  5891. countShow++;
  5892. var txtCounter = eleCounter.textContent.trim();
  5893. if (txtCounter.indexOf(txtApprove) > -1)
  5894. {
  5895. countApprove++;
  5896. }
  5897. else if (txtCounter.indexOf(txtDecline) > -1)
  5898. {
  5899. countDecline++;
  5900. }
  5901. else if (txtCounter.indexOf(txtSuggest) > -1)
  5902. {
  5903. var eleNotTranslated = trKeys[i].querySelector("span.token_nottranslated");
  5904. if (eleNotTranslated)
  5905. {
  5906. countSuggest++;
  5907. }
  5908. else
  5909. {
  5910. countResuggest++;
  5911. }
  5912. }
  5913. else
  5914. {
  5915. var eleNotTranslated = trKeys[i].querySelector("span.token_nottranslated");
  5916. if (eleNotTranslated)
  5917. {
  5918. countNotTranslated++;
  5919. }
  5920. else
  5921. {
  5922. countTranslated++;
  5923. }
  5924. }
  5925. }
  5926. else
  5927. {
  5928. var eleTd = trKeys[i].querySelector("td");
  5929. if (eleTd)
  5930. {
  5931. if (eleTd.textContent.trim() === "")
  5932. {
  5933. removeElement(trKeys[i]);
  5934. }
  5935. }
  5936. }
  5937. }
  5938. }
  5939. var eleShowing = document.querySelector("#stsh_showing");
  5940. if (eleShowing)
  5941. {
  5942. var newHtml = "Showing: <span class=\"stsh_showing_counter\">" + countShow + " of " + countAll + "</span>"
  5943. + "<!-- " + countNotTranslated + ", " + countSuggest + ", " + countResuggest
  5944. + ", " + countApprove + ", " + countDecline + ", " + countTranslated + " -->";
  5945. if (eleShowing.innerHTML !== newHtml)
  5946. {
  5947. eleShowing.innerHTML = newHtml;
  5948.  
  5949. var elesBtnShowingStatus = document.querySelectorAll(".stsh_showing_status");
  5950. if (elesBtnShowingStatus.length === 6)
  5951. {
  5952. var counterArr = [countNotTranslated, countSuggest, countResuggest
  5953. , countApprove, countDecline, countTranslated ];
  5954. var counterTextArr = ["Not Translated", "Suggested", "Resuggested"
  5955. , "Approved", "Declined", "Translated" ];
  5956.  
  5957. for (var i = 0; i < elesBtnShowingStatus.length; i++)
  5958. {
  5959. elesBtnShowingStatus[i].value = counterTextArr[i] + " ("+ counterArr[i] +")" ;
  5960. };
  5961. }
  5962. }
  5963. }
  5964. var eleShowingCur = document.querySelector("#stsh_showing_current");
  5965. if (eleShowingCur)
  5966. {
  5967. var eleOuter = document.querySelector("#suggestions_box_outer");
  5968. if (eleOuter)
  5969. {
  5970. if (eleOuter.style.display !== "none")
  5971. {
  5972. if (eleShowingCur.style.display !== "initial")
  5973. eleShowingCur.style.display = "initial";
  5974. var eleIframe = document.querySelector("#suggestions_iframe");
  5975. if (eleIframe)
  5976. {
  5977. var iUrl = eleIframe.contentWindow.location.href;
  5978. var listId = parseInt(getQueryByName("list_id", iUrl)) || 0;
  5979. listId += 1;
  5980. var newHtml = "Current: <span class=\"stsh_showing_counter\">" + listId + " of " + countShow + "</span>";
  5981. if (eleShowingCur.innerHTML !== newHtml)
  5982. {
  5983. eleShowingCur.innerHTML = newHtml;
  5984. }
  5985. }
  5986. }
  5987. else
  5988. {
  5989. if (eleShowingCur.style.display !== "none")
  5990. {
  5991. eleShowingCur.style.display = "none";
  5992. eleShowingCur.innerHTML = "";
  5993. }
  5994. }
  5995. }
  5996. }
  5997. };
  5998. countShowing();
  5999. // Waiting for iframe
  6000. {
  6001. var obTarget_countRand = document.createElement("div");
  6002. obTarget_countRand.id = "stsh_showing_random";
  6003. obTarget_countRand.dataset.random = "0";
  6004. document.body.appendChild(obTarget_countRand);
  6005. var obMu_countRand = new MutationObserver(function(mutations)
  6006. {
  6007. mutations.forEach(function(mutation)
  6008. {
  6009. countShowing();
  6010. });
  6011. });
  6012.  
  6013. var obConfig_countRand = { attributes: true, attributeFilter: ["data-random"] };
  6014. obMu_countRand.observe(obTarget_countRand, obConfig_countRand);
  6015. }
  6016. // End Count showing
  6017.  
  6018. // Line Counter
  6019. var addLineCounter = function()
  6020. {
  6021. var elesCounter = document.querySelectorAll(".stsh_lineCounter");
  6022. if (elesCounter.length > 0)
  6023. {
  6024. var j = 1;
  6025. for (var i = 0; i < elesCounter.length; i++)
  6026. {
  6027. if (!elesCounter[i].parentElement.parentElement.parentElement
  6028. .parentElement.classList.contains("stsh_hidden"))
  6029. {
  6030. if (elesCounter[i].textContent.trim() != j)
  6031. {
  6032. // Compare string with int using loose equality
  6033. elesCounter[i].textContent = j;
  6034. }
  6035. j++;
  6036. }
  6037. }
  6038. }
  6039. else
  6040. {
  6041. var elesDiv = document.querySelectorAll("#keylist td:nth-child(1) > div");
  6042. for (var i = 0; i < elesDiv.length; i++)
  6043. {
  6044. var eleNew = document.createElement("span");
  6045. eleNew.classList.add("stsh_lineCounter_outer");
  6046. eleNew.innerHTML =
  6047. ' <span class="stsh_lineCounter"> ' + (i + 1) + ' </span> ';
  6048. elesDiv[i].appendChild(eleNew);
  6049. }
  6050. }
  6051. };
  6052. addLineCounter();
  6053. // End Line Counter
  6054. // Hide & sort suggestions
  6055. {
  6056. var hideStatus = function(mode)
  6057. {
  6058. /*
  6059. mode:
  6060. 0: notTranslated
  6061. 1: suggested
  6062. 2: resuggested
  6063. 3: approved
  6064. 4: declined
  6065. 5: translated
  6066. */
  6067.  
  6068. //console.log("hideStatus: " + mode);
  6069. if (mode < 0 || mode > 5) return;
  6070.  
  6071. var display = "none";
  6072. var txtApprove = "ready for Admin";
  6073. var txtDecline = "ready for removal";
  6074. var txtSuggest = "suggestion";
  6075. var trKeys = document.querySelectorAll("#keylist > table:nth-child(1) > tbody:nth-child(1) > tr");
  6076. for (var i = 0; i < trKeys.length; i++)
  6077. {
  6078. if (!trKeys[i].classList.contains("stsh_hidden"))
  6079. {
  6080. var curMode = -1;
  6081.  
  6082. var eleCounter = trKeys[i].querySelector("tr.copysmall > td:nth-child(3)");
  6083. if (eleCounter)
  6084. {
  6085.  
  6086. var txtCounter = eleCounter.textContent.trim();
  6087. if (txtCounter.indexOf(txtApprove) > -1)
  6088. {
  6089. curMode = 3; // Approved
  6090. }
  6091. else if (txtCounter.indexOf(txtDecline) > -1)
  6092. {
  6093. curMode = 4; // Declined
  6094. }
  6095. else if (txtCounter.indexOf(txtSuggest) > -1)
  6096. {
  6097. var eleNotTranslated = trKeys[i].querySelector("span.token_nottranslated");
  6098. if (eleNotTranslated)
  6099. {
  6100. curMode = 1; // Suggested
  6101. }
  6102. else
  6103. {
  6104. curMode = 2; // Resuggested
  6105. }
  6106. }
  6107. else
  6108. {
  6109. var eleNotTranslated = trKeys[i].querySelector("span.token_nottranslated");
  6110. if (eleNotTranslated)
  6111. {
  6112. curMode = 0; // Not Translated
  6113. }
  6114. else
  6115. {
  6116. curMode = 5; // Translated
  6117. }
  6118. }
  6119. }
  6120.  
  6121. if (curMode === mode)
  6122. {
  6123. trKeys[i].classList.add("stsh_hidden");
  6124. }
  6125. }
  6126. }
  6127. }
  6128. var sortKey = function(mode)
  6129. {
  6130. /*
  6131. mode:
  6132. 0: key
  6133. 1: string
  6134. 2: word
  6135. 3: length
  6136. */
  6137. if (mode < 0) return;
  6138. var keyArr = [];
  6139. var valArr = [];
  6140. var dot = "...";
  6141. var dotLengthMinus = 0 - dot.length;
  6142. var strNotTranslated = "NOT TRANSLATED";
  6143. var strTr = "";
  6144. var rgxAlphabet = /[a-z0-9]/i;
  6145. var eleKeys = document.querySelectorAll
  6146. (" \
  6147. #keylist > table:nth-child(1) \
  6148. > tbody:nth-child(1) > tr > td:nth-child(1) > div:nth-child(1) \
  6149. > table:nth-child(1) > tbody:nth-child(2) > tr:nth-child(1) > td:nth-child(1) \
  6150. ");
  6151. for (var i = 0; i < eleKeys.length; i++)
  6152. {
  6153. try
  6154. {
  6155. /*
  6156. key:
  6157. tr: is translated
  6158. sg: is suggested
  6159. dt: has dot
  6160. sb: spacebar count
  6161. sc: special char count
  6162. sp: has special char
  6163. ln: length
  6164. lt: length translated
  6165. st: spacebar count translated
  6166. */
  6167. var dot = "...";
  6168. var dotLengthMinus = 0 - dot.length;
  6169. var isDot = false;
  6170. var isSuggested = false;
  6171. var isTranslated = false;
  6172. var key = eleKeys[i].textContent.trim() + " ";
  6173. var str = "";
  6174. if (mode !== 0)
  6175. {
  6176. str = eleKeys[i].parentElement.nextSibling.nextSibling.firstElementChild.textContent.trim();
  6177. isDot = (str.substr(dotLengthMinus) === dot);
  6178. isSuggested = (eleKeys[i].nextElementSibling.nextElementSibling.textContent.trim() !== "");
  6179. strTr = eleKeys[i].parentElement.nextElementSibling.lastElementChild.textContent.trim();
  6180. isTranslated = (strTr !== strNotTranslated);
  6181. }
  6182. if (mode === 0)
  6183. {
  6184. // mode: key
  6185. if (key.indexOf("GLOSSARY") === 0)
  6186. {
  6187. key = "0" + key;
  6188. }
  6189. }
  6190. if (mode === 1)
  6191. {
  6192. // mode: string
  6193. key = (isTranslated ? "tr00_ " : "tr99_ ") + strTr
  6194. + (isSuggested ? " _sg00" : " _sg99") + " ___ " + key;
  6195. if (str.length > 0 && !rgxAlphabet.test(str[0]))
  6196. {
  6197. key = "zzzzz" + str + " ___ " + key;
  6198. }
  6199. else
  6200. {
  6201. key = str + " ___ " + key;
  6202. }
  6203. }
  6204. else if (mode === 2)
  6205. {
  6206. // mode: word
  6207. key = (isTranslated ? "tr00_" : "tr99_")
  6208. + "st" + padZero(strTr.split(" ").length, 2) + "_"
  6209. + "lt" + padZero(strTr.length, 3) + " "
  6210. + strTr + (isSuggested ? " _sg00" : " _sg99") + " ___ " + key;
  6211. key = (isDot ? "dt99_" : "dt00_")
  6212. + "sb" + padZero(str.split(" ").length, 2)
  6213. + "_sc" + padZero(str.split(/[^a-z0-9 ]/i).length, 2)
  6214. + " ___ " + str + " ___ " + key;
  6215. }
  6216. else if (mode === 3)
  6217. {
  6218. // length
  6219. var length = 0;
  6220. if (str[0] === "<" || str[0] === "[")
  6221. {
  6222. length = str.length + 800;
  6223. }
  6224. else if (str.indexOf("<") > 0 || str.indexOf("[") > 0)
  6225. {
  6226. length = str.length + 600;
  6227. }
  6228. else
  6229. {
  6230. length = str.length;
  6231. }
  6232. key = (isTranslated ? "tr00_" : "tr99_") + "lt" + padZero(strTr.length, 3) + " "
  6233. + strTr + (isSuggested ? " _sg00" : " _sg99") + " ___ " + key;
  6234. key = (isDot ? "dt99_" : "dt00_")
  6235. + "sp" + (str.split(/[^a-z0-9]/i).length > 1 ? "99_" : "00_")
  6236. + "ln" + padZero(length, 3)
  6237. + " ___ " + str + " ___ " + key;
  6238. }
  6239. key = key.toLowerCase();
  6240. keyArr.push(key);
  6241. var eleParent = eleKeys[i].parentElement.parentElement.parentElement
  6242. .parentElement.parentElement.parentElement;
  6243. //eleParent.dataset.stshKey = key;
  6244. //console.log("Key: " + key);
  6245. valArr[key] = eleParent.outerHTML.trim();
  6246. }
  6247. catch (ex)
  6248. {
  6249. console.error("sortKey", ex.message);
  6250. }
  6251. }
  6252. var keyArrTmp = keyArr.slice();
  6253. keyArr.sort();
  6254. var isSame = true;
  6255. for (var i = 0; i < keyArr.length; i++)
  6256. {
  6257. if (keyArr[i] !== keyArrTmp[i])
  6258. {
  6259. isSame = false;
  6260. }
  6261. }
  6262. if (!isSame)
  6263. {
  6264. var eleTable = document.querySelector("#keylist > table:nth-child(1) > tbody:nth-child(1)");
  6265. if (eleTable)
  6266. {
  6267. var newInner = "";
  6268. for (var i = 0; i < keyArr.length; i++)
  6269. {
  6270. newInner += valArr[keyArr[i]];
  6271. }
  6272. eleTable.innerHTML = newInner;
  6273. }
  6274. }
  6275. }
  6276. var activeHideStatus = [0, 0, 0, 0, 0, 0];
  6277. // notTranslated, suggested, resuggested, approved, declined, translated
  6278. var activeHideKey = [0, 0, 0, 0, 0, 0];
  6279. // app, game, faq, support, promo, email
  6280. var activeHideStr = [0, 0];
  6281. // notMatch, long
  6282. var activeSort = -1;
  6283. var eleBtnShowAll = document.querySelector("#stsh_showing_all");
  6284. if (eleBtnShowAll)
  6285. {
  6286. eleBtnShowAll.addEventListener("click", function()
  6287. {
  6288. var elesBtnShowing = document.querySelectorAll(
  6289. ".stsh_showing_status, .stsh_showing_key, .stsh_showing_str");
  6290. for (var i = 0; i < elesBtnShowing.length; i++)
  6291. {
  6292. elesBtnShowing[i].disabled = false;
  6293. }
  6294. for (var i = 0; i < activeHideStatus.length; i++)
  6295. {
  6296. activeHideStatus[i] = 0;
  6297. }
  6298. for (var i = 0; i < activeHideKey.length; i++)
  6299. {
  6300. activeHideKey[i] = 0;
  6301. }
  6302. for (var i = 0; i < activeHideStr.length; i++)
  6303. {
  6304. activeHideStr[i] = 0;
  6305. }
  6306. activeSort = -1;
  6307. hideKey(-1); // Show all
  6308. countShowing();
  6309. });
  6310. }
  6311.  
  6312. var elesBtnShowingStatus = document.querySelectorAll(".stsh_showing_status");
  6313. for (var i = 0; i < elesBtnShowingStatus.length; i++)
  6314. {
  6315. elesBtnShowingStatus[i].addEventListener("click", function(ev)
  6316. {
  6317. var mode = parseInt(ev.target.dataset.hidestatus) || 0;
  6318. activeHideStatus[mode] = 1;
  6319. hideStatus(mode);
  6320. ev.target.disabled = true;
  6321. });
  6322. }
  6323. var obTarget_hider = document.querySelector("#keylist_container");
  6324. if (obTarget_hider)
  6325. {
  6326. var obMu_hider = new MutationObserver(function(mutations)
  6327. {
  6328. mutations.forEach(function(mutation)
  6329. {
  6330. //console.log("obMu_hider");
  6331. for (var i = 0; i < activeHideStatus.length; i++)
  6332. {
  6333. if (activeHideStatus[i] === 1)
  6334. {
  6335. hideStatus(i);
  6336. }
  6337. }
  6338. for (var i = 0; i < activeHideKey.length; i++)
  6339. {
  6340. if (activeHideKey[i] === 1)
  6341. {
  6342. hideKey(i);
  6343. }
  6344. }
  6345. for (var i = 0; i < activeHideStr.length; i++)
  6346. {
  6347. if (activeHideStr[i] === 1)
  6348. {
  6349. hideStr(i);
  6350. }
  6351. }
  6352. sortKey(activeSort);
  6353. });
  6354. });
  6355. var obConfig_hider = { childList: true };
  6356. obMu_hider.observe(obTarget_hider, obConfig_hider);
  6357. }
  6358.  
  6359. var elesBtnSort = document.querySelectorAll(".stsh_sort");
  6360. for (var i = 0; i < elesBtnSort.length; i++)
  6361. {
  6362. elesBtnSort[i].addEventListener("click", function(ev)
  6363. {
  6364. var mode = parseInt(ev.target.dataset.sort) || 0;
  6365. activeSort = mode;
  6366. sortKey(activeSort);
  6367. });
  6368. }
  6369.  
  6370. var setVisibleKey = function(startKey, visible)
  6371. {
  6372. // Use ("", true) to show all
  6373. startKey = startKey.toLowerCase();
  6374. var display = visible !== true ? "none" : "";
  6375. var eleKeys = document.querySelectorAll
  6376. (" \
  6377. #keylist > table:nth-child(1) \
  6378. > tbody:nth-child(1) > tr > td:nth-child(1) > div:nth-child(1) \
  6379. > table:nth-child(1) > tbody:nth-child(2) > tr:nth-child(1) > td:nth-child(1) \
  6380. ");
  6381. for (var i = 0; i < eleKeys.length; i++)
  6382. {
  6383. try
  6384. {
  6385. if (eleKeys[i].textContent.trim().toLowerCase().indexOf(startKey) > -1)
  6386. {
  6387. var eleTarget = eleKeys[i].parentElement.parentElement.parentElement
  6388. .parentElement.parentElement.parentElement;
  6389. if (visible && eleTarget.classList.contains("stsh_hidden"))
  6390. {
  6391. eleTarget.classList.remove("stsh_hidden");
  6392. }
  6393. else if (!visible && !eleTarget.classList.contains("stsh_hidden"))
  6394. {
  6395. eleTarget.classList.add("stsh_hidden");
  6396. }
  6397. }
  6398. }
  6399. catch (ex)
  6400. {
  6401. console.error("setVisibleKey", ex.message);
  6402. }
  6403. }
  6404. }
  6405. var hideKey = function(mode)
  6406. {
  6407. /*
  6408. mode:
  6409. -1: showAll
  6410. 0: app
  6411. 1: game
  6412. 2: faq
  6413. 3: support
  6414. 4: promo
  6415. 5: email
  6416. */
  6417. if (mode === -1) // showAll
  6418. {
  6419. setVisibleKey("", true);
  6420. }
  6421. else if (mode === 0) // app
  6422. {
  6423. setVisibleKey("# storefront_english_apps.txt #", false);
  6424. setVisibleKey("# storefront_english_main.txt # #app_", false);
  6425. setVisibleKey("# community_english.txt # SharedFiles_App_", false);
  6426. setVisibleKey("# appmgmt_english.txt #", false);
  6427. setVisibleKey("STEAM/VR", false);
  6428. }
  6429. else if (mode === 1) // game
  6430. {
  6431. setVisibleKey("GAMES/", false);
  6432. setVisibleKey("TF_", false);
  6433. }
  6434. else if (mode === 2) // faq
  6435. {
  6436. setVisibleKey("# support_faq_english.txt #", false);
  6437. }
  6438. else if (mode === 3) // support
  6439. {
  6440. setVisibleKey("# supportui_english.txt #", false);
  6441. setVisibleKey("# help_english.txt #", false);
  6442. }
  6443. else if (mode === 4) // promo
  6444. {
  6445. setVisibleKey("#promo", false);
  6446. setVisibleKey("#hardware", false);
  6447. setVisibleKey("ControllerBinding", false);
  6448. setVisibleKey("Library_Controller", false);
  6449. setVisibleKey("STEAM/HARDWARE", false);
  6450. setVisibleKey("STEAM/DELTA", false);
  6451. setVisibleKey("GAMES/KILLINGFLOOR2", false);
  6452. }
  6453. else if (mode === 5) // email
  6454. {
  6455. setVisibleKey("#email", false);
  6456. }
  6457. }
  6458. var elesBtnShowingKey = document.querySelectorAll(".stsh_showing_key");
  6459. for (var i = 0; i < elesBtnShowingKey.length; i++)
  6460. {
  6461. elesBtnShowingKey[i].addEventListener("click", function(ev)
  6462. {
  6463. var mode = parseInt(ev.target.dataset.hidekey) || 0;
  6464. activeHideKey[mode] = 1;
  6465. hideKey(mode);
  6466. ev.target.disabled = true;
  6467. });
  6468. }
  6469. var hideStr = function(mode)
  6470. {
  6471. /*
  6472. mode:
  6473. 0: notMatch
  6474. 1: long
  6475. */
  6476. if (mode === 0) // notMatch
  6477. {
  6478. var searchStr = decodeURIComponent(getQueryByName("search_input")).replace(/\\+/g," ").trim();
  6479. searchStr = searchStr.toLowerCase();
  6480. var eleStrs = document.querySelectorAll
  6481. (" \
  6482. #keylist \
  6483. > table:nth-child(1) > tbody:nth-child(1) > tr > td:nth-child(1) > div:nth-child(1) \
  6484. > table:nth-child(1) > tbody:nth-child(2) > tr:nth-child(2) \
  6485. ");
  6486. for (var i = 0; i < eleStrs.length; i++)
  6487. {
  6488. try
  6489. {
  6490. var valStr = eleStrs[i].children[0].textContent.trim().toLowerCase();
  6491. var valTrn = eleStrs[i].children[2].textContent.trim().toLowerCase();
  6492. if (valStr !== searchStr && valTrn !== searchStr)
  6493. {
  6494. var eleTarget = eleStrs[i].parentElement.parentElement
  6495. .parentElement.parentElement.parentElement;
  6496. if (!eleTarget.classList.contains("stsh_hidden"))
  6497. {
  6498. eleTarget.classList.add("stsh_hidden");
  6499. }
  6500. }
  6501. }
  6502. catch (ex)
  6503. {
  6504. console.error("hideStrNotMatch", ex.message);
  6505. }
  6506. }
  6507. }
  6508. else if (mode === 1) // long
  6509. {
  6510. var dot = "...";
  6511. var dotLengthMinus = 0 - dot.length;
  6512. var eleStrs = document.querySelectorAll
  6513. (" \
  6514. #keylist \
  6515. > table:nth-child(1) > tbody:nth-child(1) > tr > td:nth-child(1) > div:nth-child(1) \
  6516. > table:nth-child(1) > tbody:nth-child(2) > tr:nth-child(2) > td:nth-child(1) \
  6517. ");
  6518. for (var i = 0; i < eleStrs.length; i++)
  6519. {
  6520. try
  6521. {
  6522. var valStr = eleStrs[i].textContent.trim();
  6523. if (valStr.substr(dotLengthMinus) === dot)
  6524. {
  6525. var eleTarget = eleStrs[i].parentElement.parentElement
  6526. .parentElement.parentElement.parentElement.parentElement;
  6527. if (!eleTarget.classList.contains("stsh_hidden"))
  6528. {
  6529. eleTarget.classList.add("stsh_hidden");
  6530. }
  6531. }
  6532. }
  6533. catch (ex)
  6534. {
  6535. console.error("hideStrLong", ex.message);
  6536. }
  6537. }
  6538. }
  6539. }
  6540. var elesBtnShowingStr = document.querySelectorAll(".stsh_showing_str");
  6541. for (var i = 0; i < elesBtnShowingStr.length; i++)
  6542. {
  6543. elesBtnShowingStr[i].addEventListener("click", function(ev)
  6544. {
  6545. var mode = parseInt(ev.target.dataset.hidestr) || 0;
  6546. activeHideStr[mode] = 1;
  6547. hideStr(mode);
  6548. ev.target.disabled = true;
  6549. });
  6550. }
  6551. } // End Hide & sort suggestions
  6552.  
  6553. resizeSuggestionBox();
  6554. // Add Frame button when iframe load failed
  6555. {
  6556. var obTarget_ifrm = document.querySelector("#suggestions_iframe");
  6557. if (obTarget_ifrm)
  6558. {
  6559. var obMu_ifrm = new MutationObserver(function(mutations)
  6560. {
  6561. mutations.forEach(function(mutation)
  6562. {
  6563. var divFrame = document.querySelector("#stsh_frame");
  6564. if (!divFrame)
  6565. {
  6566. var divOuter = document.querySelector("#suggestions_box_outer");
  6567. if (divOuter)
  6568. {
  6569. divFrame = document.createElement("div");
  6570. divFrame.id = "stsh_frame";
  6571. divOuter.appendChild(divFrame);
  6572. }
  6573. }
  6574. if (divFrame)
  6575. {
  6576. var ifrm = document.querySelector("#suggestions_iframe");
  6577. if (ifrm)
  6578. {
  6579. var src = ifrm.getAttribute("src");
  6580. var token = getQueryByName("token_key", src);
  6581. divFrame.innerHTML =
  6582. ' \
  6583. <br><br> \
  6584. <div id="stsh_frame_sub"> \
  6585. Token: <span class="stsh_blue">' + token + '</span> \
  6586. <br><br> \
  6587. <a class="stsh_a_button" target="_blank" href="' + src + '">Frame</a> \
  6588. <br><br> \
  6589. This frame may be blocked by ad blocker software. \
  6590. <br> \
  6591. Please whitelist https://translation.steampowered.com to prevent this missing frame. \
  6592. </div> \
  6593. ';
  6594. }
  6595. }
  6596. });
  6597. });
  6598.  
  6599. var obConfig_ifrm = { attributes: true, attributeFilter: ["src"] };
  6600. obMu_ifrm.observe(obTarget_ifrm, obConfig_ifrm);
  6601. }
  6602. }
  6603. // Open frame if only one string
  6604. {
  6605. setTimeoutCustom(function()
  6606. {
  6607. var elesCopy = document.querySelectorAll("#keylist .copysmall");
  6608. if (elesCopy.length === 1)
  6609. {
  6610. var eleDiv = elesCopy[0].parentElement.parentElement.parentElement;
  6611. if (eleDiv.tagName === "DIV")
  6612. {
  6613. if (!isVisible())
  6614. {
  6615. eleDiv.click();
  6616. }
  6617. }
  6618. }
  6619. }, timingInit.openFrame);
  6620. }
  6621. // Fix STS search options
  6622. {
  6623. for (var i = 0; i < 6; i++)
  6624. {
  6625. var elesSort = document.querySelectorAll("#search #sort" + i);
  6626. if (elesSort.length === 2)
  6627. {
  6628. elesSort[1].id = "status" + i;
  6629. }
  6630. }
  6631. var elesLabel = document.querySelectorAll("#search label[for='sort0']");
  6632. if (elesLabel.length === 2)
  6633. {
  6634. elesLabel[1].setAttribute("for", "status0");
  6635. }
  6636. var eleLabelEntire = document.querySelector("label[for='keys']");
  6637. if (eleLabelEntire && eleLabelEntire.textContent.trim() === "ENTIRE DB")
  6638. {
  6639. eleLabelEntire.setAttribute("for", "all");
  6640. }
  6641. }
  6642. // Add date navigation
  6643. {
  6644. var eleInput = document.querySelector("input#search_input");
  6645. if (eleInput)
  6646. {
  6647. var date = "";
  6648. var valInput = eleInput.value.trim();
  6649. if (valInput.indexOf("DATE: ") === 0)
  6650. {
  6651. date = valInput.replace("DATE: ", "");
  6652. }
  6653. var eleBtn = document.querySelector("button#search_input");
  6654. if (eleBtn)
  6655. {
  6656. if (!date)
  6657. {
  6658. if (eleBtn.value.indexOf("DATE: ") === 0)
  6659. {
  6660. date = eleBtn.value.replace("DATE: ", "");
  6661. }
  6662. }
  6663. if (date)
  6664. {
  6665. eleBtn.classList.add("stsh_date_cur");
  6666. eleBtn.title = eleBtn.value.replace("DATE: ", "");
  6667. eleBtn.textContent = "TODAY";
  6668. eleBtn.removeAttribute("id");
  6669. eleBtn.removeAttribute("name");
  6670. var eleDiv = document.createElement("div");
  6671. eleDiv.classList.add("stsh_date_group");
  6672. if (eleBtn.previousSibling.nodeType === document.TEXT_NODE)
  6673. {
  6674. // Remove all &nbsp;
  6675. removeElement(eleBtn.previousSibling);
  6676. }
  6677. insertAfterElement(eleDiv, eleBtn.previousElementSibling);
  6678. eleDiv.appendChild(eleBtn);
  6679. // Calc prev and next date
  6680. {
  6681. var ts = getUnixTimestamp(date);
  6682. var sDay = 86400;
  6683. var datePrev = getDateGmt(ts - sDay);
  6684. var dateNext = getDateGmt(ts + sDay);
  6685. var eleBtnLeft = document.createElement("button");
  6686. eleBtnLeft.classList.add("stsh_date_prev");
  6687. eleBtnLeft.setAttribute("type", "submit");
  6688. eleBtnLeft.value = "DATE: " + datePrev;
  6689. eleBtnLeft.title = datePrev;
  6690. eleBtnLeft.textContent = "<<";
  6691. insertBeforeElement(eleBtnLeft, eleBtn);
  6692. var eleBtnRight = document.createElement("button");
  6693. eleBtnRight.classList.add("stsh_date_next");
  6694. eleBtnRight.setAttribute("type", "submit");
  6695. eleBtnRight.value = "DATE: " + dateNext;
  6696. eleBtnRight.title = dateNext;
  6697. eleBtnRight.textContent = ">>";
  6698. insertAfterElement(eleBtnRight, eleBtn);
  6699. var applyInputDate = function(ev)
  6700. {
  6701. var eleTarget = ev.target;
  6702. var eleInput = document.querySelector("input#search_input");
  6703. if (eleInput)
  6704. {
  6705. eleInput.value = eleTarget.value;
  6706. }
  6707. };
  6708. eleBtn.addEventListener("click", applyInputDate);
  6709. eleBtnLeft.addEventListener("click", applyInputDate);
  6710. eleBtnRight.addEventListener("click", applyInputDate);
  6711. }
  6712. }
  6713. }
  6714. }
  6715. }
  6716. // Add shortcut keys for pagination
  6717. var bindPagination = function()
  6718. {
  6719. var elesPrev = document.querySelectorAll(".pagination > a:first-child");
  6720. if (elesPrev.length === 2)
  6721. {
  6722. elesPrev[0].textContent = "Prev";
  6723. elesPrev[1].textContent = "Prev";
  6724. addKeyCtrl(document, elesPrev[0], ["BracketLeft", 219], "[", 2|8); // [
  6725. disableAfterClick(elesPrev[0]);
  6726. }
  6727. var elesNext = document.querySelectorAll(".pagination > a:last-child");
  6728. if (elesNext.length === 2)
  6729. {
  6730. elesNext[0].textContent = "Next";
  6731. elesNext[1].textContent = "Next";
  6732. addKeyCtrl(document, elesNext[0], ["BracketRight", 221, 171], "]", 2|8); // ]
  6733. disableAfterClick(elesNext[0]);
  6734. }
  6735. };
  6736. bindPagination();
  6737. // Clean pagination urls
  6738. var cleanPagination = function()
  6739. {
  6740. var elesPage = document.querySelectorAll(".pagination > a");
  6741. cleanUrlTimestamp(elesPage);
  6742. };
  6743. cleanPagination();
  6744. // Bind observer for keyList
  6745. {
  6746. var obTarget_keyList = document.querySelector("#keylist_container");
  6747. if (obTarget_keyList)
  6748. {
  6749. var tmOb_keyList = -1;
  6750. var obMu_keyList = new MutationObserver(function(mutations)
  6751. {
  6752. mutations.forEach(function(mutation)
  6753. {
  6754. if ((mutation.type !== "attributes"
  6755. || mutation.target.tagName === "TR")
  6756. && mutation.target.tagName !== "A")
  6757. {
  6758. clearTimeout(tmOb_keyList);
  6759. tmOb_keyList = setTimeoutCustom(function(mutation)
  6760. {
  6761. countShowing();
  6762. addLineCounter();
  6763. bindPagination();
  6764. cleanPagination();
  6765. //console.log("keyList: " + tmOb_keyList);
  6766. }, timingInit.bindObserverKeyList, mutation);
  6767. }
  6768. });
  6769. });
  6770. var obConfig_keyList = { childList: true, subtree: true, attributes: true, attributeFilter: ["class"] };
  6771. obMu_keyList.observe(obTarget_keyList, obConfig_keyList);
  6772. }
  6773. }
  6774. } // End translate.php
  6775.  
  6776. if (url.indexOf("user_activity.php") > -1)
  6777. {
  6778. document.body && document.body.classList.add("stsh_page_userActivity");
  6779. setTimeoutCustom(function()
  6780. {
  6781. var isMyProfile = false;
  6782. // Resolve mixed content
  6783. {
  6784. var hostTag =
  6785. [
  6786. ["img", "src"],
  6787. ["img", "src"],
  6788. ["img", "src"],
  6789. ["a", "href"],
  6790. ["a", "href"],
  6791. ];
  6792. var hostOld =
  6793. [
  6794. "http://cdn.akamai.steamstatic.com/",
  6795. "http://media.steampowered.com/",
  6796. "http://cdn.edgecast.steamstatic.com/",
  6797. "http://steamcommunity.com/",
  6798. "http://translation.steampowered.com",
  6799. ];
  6800. var hostReplace =
  6801. [
  6802. "https://steamcdn-a.akamaihd.net/",
  6803. "https://steamcdn-a.akamaihd.net/",
  6804. "https://steamcdn-a.akamaihd.net/",
  6805. "https://steamcommunity.com/",
  6806. "https://translation.steampowered.com",
  6807. ];
  6808. for (var j = 0; j < hostOld.length; j++)
  6809. {
  6810. var eles = document.querySelectorAll(hostTag[j][0] + "[" + hostTag[j][1] + "^='" + hostOld[j] + "']");
  6811. for (var i = 0; i < eles.length; i++)
  6812. {
  6813. eles[i].setAttribute(hostTag[j][1]
  6814. , eles[i].getAttribute(hostTag[j][1]).replace(hostOld[j], hostReplace[j]));
  6815. }
  6816. }
  6817. }
  6818. // Check current profile is my profile or not
  6819. {
  6820. if (userId)
  6821. {
  6822. var userPage = getQueryByName("user", url);
  6823. if (userId === userPage)
  6824. {
  6825. isMyProfile = true;
  6826. }
  6827. }
  6828. if (!isMyProfile)
  6829. {
  6830. var eleASug = document.querySelector(".friend_block_avatar > a[href*='//translation.steampowered.com/translate.php'");
  6831. if (eleASug && eleASug.textContent.trim() === "YOUR SUGGESTIONS")
  6832. {
  6833. isMyProfile = true;
  6834. }
  6835. }
  6836. if (!isMyProfile)
  6837. {
  6838. if (document.querySelector("#moderator_announcement"))
  6839. {
  6840. isMyProfile = true;
  6841. }
  6842. }
  6843. }
  6844. var user = "";
  6845. var eleAvatar = document.querySelector(".friend_block_avatar > a[href^='https://steamcommunity.com']");
  6846. if (eleAvatar)
  6847. {
  6848. if (eleAvatar.href.indexOf("https://steamcommunity.com/profiles/") === 0)
  6849. {
  6850. user = eleAvatar.href.replace("https://steamcommunity.com/profiles/", "");
  6851. }
  6852. var name = eleAvatar.firstElementChild.getAttribute("title");
  6853. if (name === "")
  6854. {
  6855. name = user;
  6856. }
  6857. document.title = name + " - " + document.title;
  6858. }
  6859.  
  6860. var stsh_activityAddLink_start = getTimeMs();
  6861. var stsh_activityAddLink_itv = setIntervalCustom(function(user)
  6862. {
  6863. // Add more links in user activity
  6864. var stsh_activityAddLink_isEnd = false;
  6865. var stsh_activityAddLink_cur = getTimeMs();
  6866. var h3s = document.querySelectorAll("#leftAreaContainer h3");
  6867. if (h3s.length === 2)
  6868. {
  6869. var td = h3s[1].parentElement;
  6870. var matchArr = td.innerHTML.match(/<\/h3>.+<br>/i);
  6871. if (matchArr)
  6872. {
  6873. var name = matchArr[0]
  6874. .replace("</h3>-", "")
  6875. .replace("-<br>", "")
  6876. .replace("<br>", "")
  6877. .trim();
  6878. if (name === "")
  6879. {
  6880. name = user;
  6881. }
  6882. if (name === "")
  6883. {
  6884. name = "Steam";
  6885. }
  6886. var tagNew = "";
  6887. if (user === "")
  6888. {
  6889. tagNew =
  6890. "\
  6891. </h3>\
  6892. <a id='stsh_sectionId' class='stsh_blue' target='_blank' href='https://steamcommunity.com/my'>\
  6893. " + name + "</a>, \
  6894. <a class='stsh_green' target='_blank' href='/WhereIsEsty.php'>Esty</a><br><br>\
  6895. ";
  6896. }
  6897. else
  6898. {
  6899. tagNew =
  6900. "\
  6901. </h3>\
  6902. <a id='stsh_sectionId' class='stsh_blue' target='_blank' href='https://steamcommunity.com/profiles/" + user + "'>\
  6903. " + name + "</a>, \
  6904. <a class='stsh_green' target='_blank' href='/WhereIsEsty.php?collectionof=" + user + "'>Esty</a>\
  6905. "
  6906. /*
  6907. // Typonion
  6908. + ", <a class='stsh_green' target='_blank' href='/translate.php?user="
  6909. + user + "&onionhunter=1&liststatus=1'>Onion</a>
  6910. */
  6911. + " <br><br> ";
  6912. }
  6913. td.innerHTML = td.innerHTML.replace(/<\/h3>.+<br>/i, tagNew);
  6914. stsh_activityAddLink_isEnd = true;
  6915. }
  6916. if (stsh_activityAddLink_isEnd || stsh_activityAddLink_cur - stsh_activityAddLink_start > 10000)
  6917. {
  6918. clearInterval(stsh_activityAddLink_itv);
  6919. }
  6920. }
  6921. }, 300, user);
  6922. var countWord = "";
  6923. var countSugg = "";
  6924. var inputDials = document.querySelectorAll("#leftAreaContainer input.dial");
  6925. if (inputDials.length === 2)
  6926. {
  6927. countWord = inputDials[0].getAttribute("title").replace("words", "").trim();
  6928. countSugg = inputDials[1].getAttribute("title").replace("suggestions", "").trim();
  6929. }
  6930. var tdCount = document.querySelector("#leftAreaContainer td[align='left']");
  6931. if (tdCount)
  6932. {
  6933. tdCount.innerHTML =
  6934. '\
  6935. <div class="stsh_profile_count stsh_profile_count_word">Word: ' + countWord + '</div> \
  6936. <div class="stsh_profile_count stsh_profile_count_sugg">Suggestion: ' + countSugg + '</div>\
  6937. ';
  6938. }
  6939. var sug = document.body.textContent;
  6940. var regComment = /VIEW COMMENT/g;
  6941. var regSuggest = /VIEW SUGGESTION/g;
  6942. var strComment = "...RECEIVED A MODERATOR COMMENT";
  6943. var strPending = "...ARE PENDING";
  6944. var strApproved = "...WERE APPROVED";
  6945. var strDeclined = "...WERE DECLINED";
  6946. var strApplied = "...HAVE BEEN APPLIED WITHIN THE LAST 14 DAYS";
  6947. var strRemoved = "...HAVE BEEN REMOVED WITHIN THE LAST 14 DAYS";
  6948. var startComment = sug.indexOf(strComment);
  6949. var startPending = sug.indexOf(strPending);
  6950. var startApproved = sug.indexOf(strApproved);
  6951. var startDeclined = sug.indexOf(strDeclined);
  6952. var startApplied = sug.indexOf(strApplied);
  6953. var startRemoved = sug.indexOf(strRemoved);
  6954. var sugComment = sug.substring(startComment,startPending);
  6955. var sugPending = sug.substring(startPending,startApproved);
  6956. var sugApproved = sug.substring(startApproved,startDeclined);
  6957. var sugDeclined = sug.substring(startDeclined,startApplied);
  6958. var sugApplied = sug.substring(startApplied,startRemoved);
  6959. var sugRemoved = sug.substring(startRemoved);
  6960. var countComment = (sugComment.match(regComment) || []).length;
  6961. var countPending = (sugPending.match(regSuggest) || []).length;
  6962. var countApproved = (sugApproved.match(regSuggest) || []).length;
  6963. var countDeclined = (sugDeclined.match(regSuggest) || []).length;
  6964. var countApplied = (sugApplied.match(regSuggest) || []).length;
  6965. var countRemoved = (sugRemoved.match(regSuggest) || []).length;
  6966. var divBtn = document.createElement("div");
  6967. document.body.appendChild(divBtn);
  6968. divBtn.innerHTML =
  6969. ' \
  6970. <div class="stsh_menu_group"> \
  6971. &nbsp; <input id="stsh_btnToProgress" value="To Progress" class="stsh_btn_long" type="button" \
  6972. onclick="scrollToId(\'stsh_sectionId\', -50); return false;" /><br> \
  6973. \
  6974. &nbsp; <span class="stsh_scroll_header">Scroll To</span>\
  6975. <li class="stsh_suggestion_btn stsh_suggestion stsh_suggestion_comment"><input value="Comment (' + countComment + ')" \
  6976. class="stsh_btn_long" type="button" onclick="scrollToId(\'stsh_sectionComment\'); return false;" ></li> \
  6977. <li class="stsh_suggestion_btn stsh_suggestion stsh_suggestion_pending"><input value="Pending (' + countPending + ')" \
  6978. class="stsh_btn_long" type="button" onclick="scrollToId(\'stsh_sectionPending\'); return false;" ></li> \
  6979. <li class="stsh_suggestion_btn stsh_suggestion stsh_suggestion_approved"><input value="Approved (' + countApproved + ')" \
  6980. class="stsh_btn_long" type="button" onclick="scrollToId(\'stsh_sectionApproved\'); return false;" ></li> \
  6981. <li class="stsh_suggestion_btn stsh_suggestion stsh_suggestion_declined"><input value="Declined (' + countDeclined + ')" \
  6982. class="stsh_btn_long" type="button" onclick="scrollToId(\'stsh_sectionDeclined\'); return false;" ></li> \
  6983. <li class="stsh_suggestion_btn stsh_suggestion stsh_suggestion_applied"><input value="Applied (' + countApplied + ')" \
  6984. class="stsh_btn_long" type="button" onclick="scrollToId(\'stsh_sectionApplied\'); return false;" ></li> \
  6985. <li class="stsh_suggestion_btn stsh_suggestion stsh_suggestion_removed"><input value="Removed (' + countRemoved + ')" \
  6986. class="stsh_btn_long" type="button" onclick="scrollToId(\'stsh_sectionRemoved\'); return false;" ></li> \
  6987. <br> \
  6988. &nbsp; <input id="stsh_btnHideSuggestion" value="Suggestions" class="stsh_btn_long" type="button" \
  6989. onclick="return false;" title="Toggle hidden/shown suggestion list" /><br> \
  6990. <br> \
  6991. &nbsp; <input value="Refresh" class="stsh_btn_long" type="button" onclick="window.location = window.location.href; return false;" /> \
  6992. <br> \
  6993. </div> \
  6994. ';
  6995.  
  6996. var divContainer = document.querySelector("#leftAreaContainer");
  6997. if (divContainer)
  6998. {
  6999. var inner = divContainer.innerHTML;
  7000. var htmlPending = /\.\.\.ARE \<a [^\<]+\>PENDING\<\/a\>/i.exec(inner);
  7001. var htmlApproved = /\.\.\.WERE \<a [^\<]+\>APPROVED\<\/a\>/i.exec(inner);
  7002. var htmlDeclined = /\.\.\.WERE \<a [^\<]+\>DECLINED\<\/a\>/i.exec(inner);
  7003. if (htmlPending && htmlApproved && htmlDeclined)
  7004. {
  7005. divContainer.innerHTML = inner
  7006. .replace("...RECEIVED A MODERATOR COMMENT",
  7007. "<span id='stsh_sectionComment' class='stsh_suggestion_header'>"
  7008. + "...RECEIVED A MODERATOR COMMENT ("
  7009. + countComment + ")</span>")
  7010. .replace(htmlPending,
  7011. "<span id='stsh_sectionPending' class='stsh_suggestion_header'>" + htmlPending + " ("
  7012. + countPending + ")</span>")
  7013. .replace(htmlApproved,
  7014. "<span id='stsh_sectionApproved' class='stsh_suggestion_header'>" + htmlApproved + " ("
  7015. + countApproved + ")</span>")
  7016. .replace(htmlDeclined,
  7017. "<span id='stsh_sectionDeclined' class='stsh_suggestion_header'>" + htmlDeclined + " ("
  7018. + countDeclined + ")</span>")
  7019. .replace("...HAVE BEEN APPLIED WITHIN THE LAST 14 DAYS",
  7020. "<span id='stsh_sectionApplied' class='stsh_suggestion_header'>"
  7021. + "...HAVE BEEN APPLIED WITHIN THE LAST 14 DAYS ("
  7022. + countApplied + ")</span>")
  7023. .replace("...HAVE BEEN REMOVED WITHIN THE LAST 14 DAYS",
  7024. "<span id='stsh_sectionRemoved' class='stsh_suggestion_header'>"
  7025. + "...HAVE BEEN REMOVED WITHIN THE LAST 14 DAYS ("
  7026. + countRemoved + ")</span>");
  7027. }
  7028. }
  7029. if (document.querySelector("#hours"))
  7030. {
  7031. var eleBtn = document.querySelector("#stsh_btnToProgress");
  7032. if (eleBtn)
  7033. {
  7034. var ele = document.createElement("input");
  7035. ele.classList.add("stsh_btn_long");
  7036. ele.setAttribute("value", "To Hours");
  7037. ele.setAttribute("type", "button");
  7038. ele.setAttribute("onclick", "scrollToElement(\"input[name*='[remarks]']\", -48); return false;");
  7039. insertAfterElement(ele, eleBtn);
  7040. ele = document.createTextNode(" \u00A0 ");
  7041. insertAfterElement(ele, eleBtn);
  7042. ele = document.createElement("br");
  7043. insertAfterElement(ele, eleBtn);
  7044. }
  7045. }
  7046. var cans = document.querySelectorAll("canvas");
  7047. for (var i = 0; i < cans.length; i++)
  7048. {
  7049. removeElement(cans[i]);
  7050. }
  7051. /* // Unknown reason
  7052. var aKeys = document.querySelectorAll("#leftAreaContainer li > a:nth-child(1)");
  7053. for (var i = 0; i < aKeys.length; i++)
  7054. {
  7055. var key = aKeys[i].textContent;
  7056. var keyArr = key.substr(21).trim().split(" >> ");
  7057. keyArr[0] = "<span style='color: #FFF !important;'>" + keyArr[0] + "</span>";
  7058. var keyNew = key.substr(0,21) + keyArr.join(" >> ") + "";
  7059. aKeys[i].innerHTML = keyNew;
  7060. }
  7061. */
  7062. var sugModeComment = 0;
  7063. var sugModePending = 1;
  7064. var sugModeApproved = 2;
  7065. var sugModeDeclined = 3;
  7066. var sugModeApplied = 4;
  7067. var sugModeRemoved = 5;
  7068. var sugMode = sugModeComment;
  7069. var eleSugFirst = document.querySelector
  7070. (" \
  7071. #leftAreaContainer > a[href^='translate.php?search_input='] \
  7072. , #leftAreaContainer > form > a[href^='translate.php?search_input='] \
  7073. ");
  7074. if (eleSugFirst)
  7075. {
  7076. var eleSugHeadPrev = eleSugFirst.previousElementSibling.previousElementSibling;
  7077. if (eleSugHeadPrev.id === "stsh_sectionRemoved")
  7078. {
  7079. sugMode = sugModeRemoved;
  7080. }
  7081. else if (eleSugHeadPrev.id === "stsh_sectionApplied")
  7082. {
  7083. sugMode = sugModeApplied;
  7084. }
  7085. else if (eleSugHeadPrev.id === "stsh_sectionDeclined")
  7086. {
  7087. sugMode = sugModeDeclined;
  7088. }
  7089. else if (eleSugHeadPrev.id === "stsh_sectionApproved")
  7090. {
  7091. sugMode = sugModeApproved;
  7092. }
  7093. else if (eleSugHeadPrev.id === "stsh_sectionPending")
  7094. {
  7095. sugMode = sugModePending;
  7096. }
  7097. var eleSugNext = eleSugFirst;
  7098. while (eleSugNext)
  7099. {
  7100. if (eleSugNext.tagName === "A")
  7101. {
  7102. var attrHref = eleSugNext.getAttribute("href");
  7103. if (attrHref && attrHref.indexOf("translate.php?search_input=") === 0)
  7104. {
  7105. eleSugNext.classList.add("stsh_suggestion");
  7106. if (sugMode === sugModeComment)
  7107. {
  7108. eleSugNext.classList.add("stsh_suggestion_comment");
  7109. }
  7110. else if (sugMode === sugModePending)
  7111. {
  7112. eleSugNext.classList.add("stsh_suggestion_pending");
  7113. }
  7114. else if (sugMode === sugModeApproved)
  7115. {
  7116. eleSugNext.classList.add("stsh_suggestion_approved");
  7117. }
  7118. else if (sugMode === sugModeDeclined)
  7119. {
  7120. eleSugNext.classList.add("stsh_suggestion_declined");
  7121. }
  7122. else if (sugMode === sugModeApplied)
  7123. {
  7124. eleSugNext.classList.add("stsh_suggestion_applied");
  7125. }
  7126. else if (sugMode === sugModeRemoved)
  7127. {
  7128. eleSugNext.classList.add("stsh_suggestion_removed");
  7129. }
  7130. }
  7131. }
  7132. else if (eleSugNext.tagName === "SPAN" && eleSugNext.classList.contains("stsh_suggestion_header"))
  7133. {
  7134. if (eleSugNext.id === "stsh_sectionRemoved")
  7135. {
  7136. sugMode = sugModeRemoved;
  7137. }
  7138. else if (eleSugNext.id === "stsh_sectionApplied")
  7139. {
  7140. sugMode = sugModeApplied;
  7141. }
  7142. else if (eleSugNext.id === "stsh_sectionDeclined")
  7143. {
  7144. sugMode = sugModeDeclined;
  7145. }
  7146. else if (eleSugNext.id === "stsh_sectionApproved")
  7147. {
  7148. sugMode = sugModeApproved;
  7149. }
  7150. else if (eleSugNext.id === "stsh_sectionPending")
  7151. {
  7152. sugMode = sugModePending;
  7153. }
  7154. }
  7155. eleSugNext = eleSugNext.nextElementSibling;
  7156. }
  7157. }
  7158. // Change language & correct url
  7159. {
  7160. var aProgresses = document.querySelectorAll("div > .friend_block_avatar a[onmouseout]");
  7161. for (var i = 0; i < aProgresses.length; i++)
  7162. {
  7163. var langCur = getQueryByName("lang", aProgresses[i].href);
  7164. if (langCur === "")
  7165. {
  7166. aProgresses[i].href = aProgresses[i].href + lang;
  7167. }
  7168. else
  7169. {
  7170. if (langCur !== lang)
  7171. {
  7172. //var langQuery = (url.indexOf("?") > -1) ? "&lang=" : "?lang=";
  7173. //window.location = url + langQuery + langCur;
  7174. console.log("Lang: " + langCur);
  7175. }
  7176. }
  7177. var aContent = aProgresses[i].textContent.trim();
  7178. if (aContent.indexOf("SUGGESTIONS") > -1)
  7179. {
  7180. aProgresses[i].href = aProgresses[i].href + "&listsort=5&liststatus=1&paginationrows=1000";
  7181. }
  7182. else if (aContent.indexOf("REVIEWS") > -1)
  7183. {
  7184. aProgresses[i].href = aProgresses[i].href + "&listsort=5&liststatus=3&paginationrows=1000";
  7185. }
  7186. }
  7187. }
  7188. // Hours
  7189. if (document.querySelector("#hours"))
  7190. {
  7191. var calculateHours = function()
  7192. {
  7193. var rgxDate = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
  7194. var rgxTime = /^(\d{1,2}:\d{2}(:\d{2})?|\d{1,2}\.\d{2})$/;
  7195. var eleFrom = document.querySelector("#stsh_hoursCalc_from");
  7196. var eleTo = document.querySelector("#stsh_hoursCalc_to");
  7197. var eleRes = document.querySelector("#stsh_hoursCalc_result");
  7198. if (eleFrom && eleTo && eleRes)
  7199. {
  7200. var rawFrom = eleFrom.value.trim();
  7201. var rawTo = eleTo.value.trim();
  7202. var valFrom = 0;
  7203. var valTo = 0;
  7204. if (rgxDate.test(rawFrom))
  7205. {
  7206. rawFrom = rawFrom.substr(11);
  7207. }
  7208. if (rgxTime.test(rawFrom))
  7209. {
  7210. var arrTime = rawFrom.split(":");
  7211. if (arrTime.length === 1)
  7212. {
  7213. arrTime = rawFrom.split(".");
  7214. }
  7215. valFrom = parseInt(arrTime[1]) + (parseInt(arrTime[0]) * 60);
  7216. }
  7217. if (rgxDate.test(rawTo))
  7218. {
  7219. rawTo = rawTo.substr(11);
  7220. }
  7221. if (rgxTime.test(rawTo))
  7222. {
  7223. var arrTime = rawTo.split(":");
  7224. if (arrTime.length === 1)
  7225. {
  7226. arrTime = rawTo.split(".");
  7227. }
  7228. valTo = parseInt(arrTime[1]) + (parseInt(arrTime[0]) * 60);
  7229. }
  7230. var valDiff = Math.abs(valTo - valFrom);
  7231. var valHr = parseInt(valDiff / 60);
  7232. var valMn = valDiff % 60;
  7233. eleRes.textContent = padZero(valHr, 2) + ":" + padZero(valMn, 2);
  7234. }
  7235. }
  7236. var curDateStr = getDateUs();
  7237. // Add hours calculator
  7238. {
  7239. var eleFinalize = document.querySelector("#hours input[name='Finalize']");
  7240. if (eleFinalize)
  7241. {
  7242. var eleFinalizeParent = eleFinalize.parentElement;
  7243. eleFinalizeParent.setAttribute("colspan", "2");
  7244. eleFinalizeParent.style.verticalAlign = "top";
  7245. var elePad = document.createElement("td");
  7246. insertBeforeElement(elePad, eleFinalizeParent);
  7247. var eleCalc = document.createElement("td");
  7248. eleCalc.classList.add("stsh_hoursCalc");
  7249. insertBeforeElement(eleCalc, eleFinalizeParent);
  7250. if (eleCalc.parentElement.previousElementSibling.querySelector("input[type='radio']"))
  7251. {
  7252. eleCalc.appendChild(document.createElement("br"));
  7253. }
  7254. var ele = document.createElement("b");
  7255. ele.textContent = " Hours Calculator (Estimated) ";
  7256. eleCalc.appendChild(ele);
  7257. eleCalc.appendChild(document.createElement("br"));
  7258. ele = document.createElement("span");
  7259. ele.innerHTML =
  7260. ' \
  7261. Enter date or time to calculate range (calculate only hours and minutes). \
  7262. <br>You can enter date "2016-01-01 08:05:00" or time "8:05" or time "8.05".\
  7263. ';
  7264. ele.setAttribute("style", "display: inline-block; padding-bottom: 4px;");
  7265. eleCalc.appendChild(ele);
  7266. eleCalc.appendChild(document.createElement("br"));
  7267. ele = document.createElement("span");
  7268. ele.textContent = " From: ";
  7269. eleCalc.appendChild(ele);
  7270. ele = document.createElement("input");
  7271. ele.id = "stsh_hoursCalc_from";
  7272. ele.setAttribute("type", "text");
  7273. ele.setAttribute("onkeypress", "return event.keyCode !== 13;");
  7274. ele.setAttribute("autocomplete", "off");
  7275. ele.addEventListener("keyup", function()
  7276. {
  7277. calculateHours();
  7278. });
  7279. eleCalc.appendChild(ele);
  7280. ele = document.createElement("span");
  7281. ele.innerHTML = "&nbsp;&nbsp; To: ";
  7282. eleCalc.appendChild(ele);
  7283. ele = document.createElement("input");
  7284. ele.id = "stsh_hoursCalc_to";
  7285. ele.setAttribute("type", "text");
  7286. ele.setAttribute("onkeypress", "return event.keyCode !== 13;");
  7287. ele.setAttribute("autocomplete", "off");
  7288. ele.addEventListener("keyup", function()
  7289. {
  7290. calculateHours();
  7291. });
  7292. eleCalc.appendChild(ele);
  7293. ele = document.createElement("input");
  7294. ele.id = "stsh_hoursCalc_toNow";
  7295. ele.setAttribute("type", "button");
  7296. ele.setAttribute("value", "Now");
  7297. ele.setAttribute("onclick", "return false;");
  7298. ele.addEventListener("click", function()
  7299. {
  7300. var eleTo = document.querySelector("#stsh_hoursCalc_to");
  7301. eleTo.value = getTimeUs();
  7302. calculateHours();
  7303. });
  7304. eleCalc.appendChild(ele);
  7305. ele = document.createElement("span");
  7306. ele.innerHTML = "&nbsp;&nbsp; Result: ";
  7307. eleCalc.appendChild(ele);
  7308. ele = document.createElement("b");
  7309. ele.id = "stsh_hoursCalc_result"
  7310. ele.textContent = " 00:00 ";
  7311. eleCalc.appendChild(ele);
  7312. }
  7313. }
  7314. // Hilight current date
  7315. {
  7316. var elesTd = document.querySelectorAll("#hours > table > tbody > tr > td:nth-child(1)");
  7317. for (var i = 0; i < elesTd.length; i++)
  7318. {
  7319. if (elesTd[i].textContent.indexOf(curDateStr) > -1)
  7320. {
  7321. elesTd[i].parentElement.id = "stsh_hours_curDate";
  7322. elesTd[i].parentElement.classList.add("stsh_hours_curDate");
  7323. break;
  7324. }
  7325. }
  7326. }
  7327. // Auto calculate hours in current date
  7328. {
  7329. var timePendingFirst = "";
  7330. var timePendingLast = "";
  7331. var elesPending = document.querySelectorAll("#mainbody .stsh_suggestion_pending");
  7332. for (var i = 0; i < elesPending.length; i++)
  7333. {
  7334. var content = elesPending[i].textContent.trim().substr(0, 19);
  7335. if (content.substr(0, 10) === curDateStr)
  7336. {
  7337. timePendingFirst = content.substr(11, 5);
  7338. if (timePendingLast === "")
  7339. {
  7340. timePendingLast = timePendingFirst;
  7341. }
  7342. }
  7343. else
  7344. {
  7345. break;
  7346. }
  7347. }
  7348. var timeApprovedFirst = "";
  7349. var timeApprovedLast = "";
  7350. var elesApproved = document.querySelectorAll("#mainbody .stsh_suggestion_approved");
  7351. for (var i = 0; i < elesApproved.length; i++)
  7352. {
  7353. var content = elesApproved[i].textContent.trim().substr(0, 19);
  7354. if (content.substr(0, 10) === curDateStr)
  7355. {
  7356. timeApprovedFirst = content.substr(11, 5);
  7357. if (timeApprovedLast === "")
  7358. {
  7359. timeApprovedLast = timeApprovedFirst;
  7360. }
  7361. }
  7362. else
  7363. {
  7364. break;
  7365. }
  7366. }
  7367. if (timePendingFirst === "")
  7368. {
  7369. timePendingFirst = timeApprovedFirst;
  7370. }
  7371. if (timeApprovedFirst === "")
  7372. {
  7373. timeApprovedFirst = timePendingFirst;
  7374. }
  7375. if (timePendingLast === "")
  7376. {
  7377. timePendingLast = timeApprovedLast;
  7378. }
  7379. if (timeApprovedLast === "")
  7380. {
  7381. timeApprovedLast = timePendingLast;
  7382. }
  7383. var timeFirst = timeApprovedFirst < timePendingFirst ? timeApprovedFirst : timePendingFirst;
  7384. var timeLast = timeApprovedLast > timePendingLast ? timeApprovedLast : timePendingLast;
  7385. if (timeFirst !== "")
  7386. {
  7387. var eleFrom = document.querySelector("#stsh_hoursCalc_from");
  7388. if (eleFrom)
  7389. {
  7390. eleFrom.value = timeFirst;
  7391. }
  7392. var eleTo = document.querySelector("#stsh_hoursCalc_to");
  7393. if (eleTo)
  7394. {
  7395. eleTo.value = timeLast;
  7396. }
  7397. calculateHours();
  7398. }
  7399. }
  7400. // Make minutes add to hours
  7401. setTimeoutCustom(function()
  7402. {
  7403. var elesMn = document.querySelectorAll("#hours input[name*='[minutes]']");
  7404. for (var i = 0; i < elesMn.length; i++)
  7405. {
  7406. elesMn[i].setAttribute("min", "-15");
  7407. elesMn[i].setAttribute("max", "60");
  7408. elesMn[i].addEventListener("change", function(ev)
  7409. {
  7410. var eleMn = ev.target;
  7411. var eleHr = eleMn.parentElement.previousElementSibling.firstElementChild;
  7412. var valMn = parseInt(eleMn.value) || 0;
  7413. var valHr = parseInt(eleHr.value) || 0;
  7414. if (valMn < 0)
  7415. {
  7416. if (valHr > 0)
  7417. {
  7418. eleHr.value = valHr - 1;
  7419. eleMn.value = 45;
  7420. }
  7421. else
  7422. {
  7423. eleMn.value = 0;
  7424. }
  7425. }
  7426. else if (valMn > 59)
  7427. {
  7428. if (valHr < 23)
  7429. {
  7430. eleHr.value = valHr + 1;
  7431. eleMn.value = 0;
  7432. }
  7433. else
  7434. {
  7435. eleMn.value = 45;
  7436. }
  7437. }
  7438. });
  7439. }
  7440. }, 500);
  7441. // Make deferred can be clicked
  7442. {
  7443. var eleDeferred = document.querySelector("#hours td > i > span[title^='DATE']");
  7444. if (eleDeferred)
  7445. {
  7446. eleDeferred.dataset.title = eleDeferred.title;
  7447. eleDeferred.title = "Click to reveal";
  7448. eleDeferred.addEventListener("click", function(ev)
  7449. {
  7450. var ele = ev.target;
  7451. var eleDetail = document.querySelector(".stsh_deferred");
  7452. if (!eleDetail)
  7453. {
  7454. eleDetail = document.createElement("div");
  7455. eleDetail.classList.add("stsh_deferred");
  7456. ele.parentElement.parentElement
  7457. .parentElement.parentElement
  7458. .lastElementChild.firstElementChild
  7459. .appendChild(eleDetail);
  7460. }
  7461. var space = String.fromCharCode(160);
  7462. var space3 = space + space + space;
  7463. eleDetail.innerHTML = "<br>TOTAL DEFERRED HOURS" + space3 + " <br>"
  7464. + ele.dataset.title.substr(61).trim()
  7465. .replace(/\n/g, space3 + " <br>")
  7466. + space3;
  7467. });
  7468. }
  7469. }
  7470. // Hide past date
  7471. {
  7472. var hidePast = function ()
  7473. {
  7474. var isHidden = false;
  7475. var elesMn = document.querySelectorAll("#hours input[name*='[minutes]']");
  7476. if (elesMn.length > 0)
  7477. {
  7478. if (elesMn[0].name === "date[1969-12-31][minutes]")
  7479. {
  7480. isHidden = true;
  7481. }
  7482. }
  7483. if (isHidden)
  7484. {
  7485. for (var i = 1, l = elesMn.length - 1; i < l; i++)
  7486. {
  7487. elesMn[i].parentElement.parentElement.classList.add("stsh_hidden");
  7488. }
  7489. }
  7490. };
  7491. setTimeoutCustom(hidePast, 500);
  7492. }
  7493. }
  7494. // Hide wallet
  7495. // Hide email noti
  7496. {
  7497. if (!isMyProfile)
  7498. {
  7499. var elesAWallet = document.querySelectorAll("a[id^='walletkeys']");
  7500. for (var i = 0; i < elesAWallet.length; i++)
  7501. {
  7502. var eleCur = elesAWallet[i];
  7503. for (var j = 0; j < 5; j++)
  7504. {
  7505. eleCur.classList.add("stsh_hidden");
  7506. eleCur = eleCur.nextElementSibling;
  7507. }
  7508. }
  7509. var eleSub = document.querySelector("#subscribe");
  7510. if (eleSub)
  7511. {
  7512. eleSub.classList.add("stsh_hidden");
  7513. eleSub.previousElementSibling.classList.add("stsh_hidden");
  7514. eleSub.previousElementSibling.previousElementSibling.classList.add("stsh_hidden");
  7515. eleSub.nextElementSibling.classList.add("stsh_hidden");
  7516. eleSub.nextElementSibling.nextElementSibling.classList.add("stsh_hidden");
  7517. }
  7518. }
  7519. }
  7520. // Set visible suggestion list
  7521. {
  7522. var setVisibleSuggestion = function(visible)
  7523. {
  7524. var display = visible !== true ? "none" : "";
  7525. var eles = document.querySelectorAll(".copy");
  7526. for (var i = 0; i < eles.length; i++)
  7527. {
  7528. if (eles[i].id && eles[i].id.indexOf("showwalletkeys") < 0
  7529. && eles[i].id !== "abuse_report"
  7530. && eles[i].id !== "moderator_announcement")
  7531. {
  7532. if (eles[i].style.display !== display)
  7533. {
  7534. eles[i].style.display = display;
  7535. }
  7536. }
  7537. }
  7538. }
  7539. var eleHide = document.querySelector("#stsh_btnHideSuggestion");
  7540. if (eleHide)
  7541. {
  7542. var isHide = GM_getValue("profileHideSuggestion", 0);
  7543. if (isHide)
  7544. {
  7545. eleHide.dataset.modeNext = "show";
  7546. eleHide.value = "Suggestions: Hide";
  7547. setVisibleSuggestion(false);
  7548. }
  7549. else
  7550. {
  7551. eleHide.dataset.modeNext = "hide";
  7552. eleHide.value = "Suggestions: Show";
  7553. setVisibleSuggestion(true);
  7554. }
  7555. eleHide.addEventListener("click", function(ev)
  7556. {
  7557. var eleHide = ev.target;
  7558. if (eleHide.dataset.modeNext === "show")
  7559. {
  7560. eleHide.dataset.modeNext = "hide";
  7561. eleHide.value = "Suggestions: Show";
  7562. setVisibleSuggestion(true);
  7563. GM_setValue("profileHideSuggestion", 0);
  7564. }
  7565. else
  7566. {
  7567. eleHide.dataset.modeNext = "show";
  7568. eleHide.value = "Suggestions: Hide";
  7569. setVisibleSuggestion(false);
  7570. GM_setValue("profileHideSuggestion", 1);
  7571. }
  7572. });
  7573. }
  7574. }
  7575. // Add resolved comment checkbox
  7576. {
  7577. if (isMyProfile)
  7578. {
  7579. var objComment = GM_getValue("profile_comment", 0);
  7580. //console.log(GM_getValue("profile_comment"));
  7581. if (!objComment)
  7582. {
  7583. objComment = {};
  7584. }
  7585. if (!objComment[userId])
  7586. {
  7587. objComment[userId] = {};
  7588. }
  7589. var elesSugComment = document.querySelectorAll("#mainbody .stsh_suggestion_comment");
  7590. for (var i = 0; i < elesSugComment.length; i++)
  7591. {
  7592. var eleComment = elesSugComment[i].nextElementSibling.nextElementSibling
  7593. .nextElementSibling.lastElementChild;
  7594. if (eleComment)
  7595. {
  7596. eleComment.classList.add("stsh_suggestion_comment_detail");
  7597. var eleInput = document.createElement("input");
  7598. eleInput.classList.add("stsh_comment_resolved");
  7599. eleInput.setAttribute("type", "checkbox");
  7600. eleInput.setAttribute("value", "true");
  7601. var eleStrong = document.createElement("strong");
  7602. eleStrong.textContent = "Resolved:";
  7603. var eleDate = document.createElement("span");
  7604. eleDate.classList.add("stsh_comment_resolved_date");
  7605. var eleLabel = document.createElement("label");
  7606. eleLabel.classList.add("stsh_comment_resolved_label");
  7607. eleLabel.classList.add("stsh_unselectable");
  7608. eleLabel.classList.add("stsh_blue_light");
  7609. eleLabel.classList.add("stsh_cursor_pointer");
  7610. eleLabel.setAttribute("title", "Mark this comment as resolved. "
  7611. + "\nThis helps you indicated this string was corrected or not.");
  7612. eleLabel.appendChild(eleStrong);
  7613. eleLabel.appendChild(document.createTextNode(" "));
  7614. eleLabel.appendChild(eleInput);
  7615. eleLabel.appendChild(document.createTextNode(" "));
  7616. eleLabel.appendChild(eleDate);
  7617. insertAfterElement(eleLabel, eleComment);
  7618. var comment = eleComment.lastChild.textContent.trim();
  7619. var key = elesSugComment[i].textContent.trim();
  7620. var identifer = key + " ___ " + comment;
  7621. eleInput.dataset.stshUser = userId;
  7622. eleInput.dataset.stshIdentifier = identifer;
  7623. if (objComment[userId][identifer])
  7624. {
  7625. if (objComment[userId][identifer].resolved === "true")
  7626. {
  7627. eleInput.checked = true;
  7628. eleLabel.lastElementChild.textContent =
  7629. getDateTimeUs(objComment[userId][identifer].time);
  7630. }
  7631. }
  7632. else
  7633. {
  7634. objComment[userId][identifer] =
  7635. {
  7636. resolved: "false",
  7637. time: getUnixTimestamp(),
  7638. };
  7639. }
  7640. eleInput.addEventListener("click", function (ev)
  7641. {
  7642. var ele = ev.target;
  7643. var userId = ele.dataset.stshUser;
  7644. var identifer = ele.dataset.stshIdentifier;
  7645. var objComment = GM_getValue("profile_comment", 0);
  7646. if (!objComment)
  7647. {
  7648. objComment = {};
  7649. }
  7650. if (!objComment[userId])
  7651. {
  7652. objComment[userId] = {};
  7653. }
  7654. objComment[userId][identifer] =
  7655. {
  7656. resolved: ele.checked ? "true" : "false",
  7657. time: getUnixTimestamp(),
  7658. };
  7659. GM_setValue("profile_comment", objComment);
  7660. //console.log(GM_getValue("profile_comment"));
  7661. if (ele.checked && ele.nextElementSibling)
  7662. {
  7663. ele.nextElementSibling.textContent = "Now";
  7664. }
  7665. });
  7666. }
  7667. }
  7668. // Clean up
  7669. {
  7670. }
  7671. // Save
  7672. GM_setValue("profile_comment", objComment);
  7673. }
  7674. }
  7675. // Check mod status
  7676. {
  7677. if (isMyProfile)
  7678. {
  7679. var isMod = !!document.querySelector("#moderator_announcement");
  7680. var userMod = GM_getValue("mod", "");
  7681. if (userId && userId !== userMod)
  7682. {
  7683. GM_setValue("mod", userId);
  7684. }
  7685. }
  7686. }
  7687. }, timingInit.pageUserActivity);
  7688. } // End user_activity.php
  7689. if (/\/rally[0-9]{0,4}/.test(url))
  7690. {
  7691. document.body && document.body.classList.add("stsh_page_rally");
  7692. resizeSuggestionBox();
  7693. var outer = document.querySelector("#suggestions_box_outer");
  7694. if (outer)
  7695. {
  7696. outer.setAttribute("onclick", "hideSuggestionsBox();");
  7697. }
  7698. // Set cur lang to first
  7699. {
  7700. var first = document.querySelector(".gradienttable tr:nth-child(6)");
  7701. if (first)
  7702. {
  7703. var cur = null;
  7704. var tdLangs = document.querySelectorAll(".gradienttable tr > td:nth-child(1)");
  7705. for (var i = 0; i < tdLangs.length; i++)
  7706. {
  7707. if (lang === tdLangs[i].textContent.trim().toLowerCase())
  7708. {
  7709. cur = tdLangs[i].parentElement;
  7710. break;
  7711. }
  7712. }
  7713. if (cur)
  7714. {
  7715. cur.classList.add("stsh_curLang");
  7716. first.parentElement.insertBefore(cur, first);
  7717. }
  7718. }
  7719. }
  7720. // Change rows per page
  7721. {
  7722. var eleAs = document.querySelectorAll(".gradienttable tr:nth-child(6) a[href^='translate.php?']");
  7723. for (var i = 0; i < eleAs.length; i++)
  7724. {
  7725. eleAs[i].href = eleAs[i].href + "&paginationrows=1000";
  7726. }
  7727. }
  7728. var inputClose = document.querySelector("td:nth-child(3) > input:nth-child(1)");
  7729. if (inputClose)
  7730. {
  7731. inputClose.value = "Close (Esc)";
  7732. }
  7733. } // End rally.php
  7734. if (/\/rally_results_?[0-9]{0,4}/.test(url))
  7735. {
  7736. document.body && document.body.classList.add("stsh_page_rallyResults");
  7737. var h3 = document.querySelector("table.curved h3");
  7738. if (h3)
  7739. {
  7740. document.title = h3.textContent.trim();
  7741. }
  7742. var eleTable = document.querySelector("body > div:nth-child(1) > table:nth-child(1)");
  7743. if (eleTable)
  7744. {
  7745. eleTable.style.width = "";
  7746. }
  7747. var inputClose = document.querySelector("td:nth-child(3) > input:nth-child(1)");
  7748. if (inputClose)
  7749. {
  7750. inputClose.value = "Close (Esc)";
  7751. inputClose.focus();
  7752. }
  7753. // Add frame and background button
  7754. {
  7755. var eleTdFirst = document.querySelector("td:nth-child(1)");
  7756. if (eleTdFirst)
  7757. {
  7758. var eleTdFrame = document.createElement("td");
  7759. eleTdFrame.setAttribute("align", "right");
  7760. eleTdFrame.innerHTML =
  7761. ' <a class="stsh_a_button" target="_blank" href="' + url + '">Frame</a> ';
  7762. insertBeforeElement(eleTdFrame, eleTdFirst);
  7763. var img = document.body.style.backgroundImage;
  7764. if (img.indexOf("url(\"") === 0)
  7765. {
  7766. img = img.replace("url(\"", "").replace("\")", "");
  7767. var eleTdImage = document.createElement("td");
  7768. eleTdImage.setAttribute("align", "right");
  7769. eleTdImage.innerHTML =
  7770. ' <a class="stsh_a_button" target="_blank" href="' + img + '">View Background</a> ';
  7771. insertAfterElement(eleTdImage, eleTdFrame);
  7772. }
  7773. }
  7774. }
  7775. var inputPrev = document.querySelector("input[value^='Prev']");
  7776. if (inputPrev)
  7777. {
  7778. addKeyCtrl(document, inputPrev, ["BracketLeft", 219], "[", 1|2); // [
  7779. disableAfterClick(inputPrev);
  7780. }
  7781. var inputNext = document.querySelector("input[value^='Next']");
  7782. if (inputNext)
  7783. {
  7784. addKeyCtrl(document, inputNext, ["BracketRight", 221, 171], "]", 1|2); // ]
  7785. disableAfterClick(inputNext);
  7786. }
  7787. // Hilight cur lang
  7788. {
  7789. var elesLang = document.querySelectorAll("table.curved > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(3) > h2:nth-child(1)");
  7790. for (var i = 0; i < elesLang.length; i++)
  7791. {
  7792. if (lang === elesLang[i].textContent.trim().toLowerCase())
  7793. {
  7794. var eleParent = elesLang[i].parentElement.parentElement.parentElement.parentElement;
  7795. //eleParent.style.backgroundColor = "#474D1A";
  7796. eleParent.classList.add("stsh_curLang");
  7797. eleParent.setAttribute("bgcolor", "#474D1A");
  7798. eleParent.setAttribute("onmouseout", "this.bgColor='#474D1A'");
  7799. eleParent.setAttribute("onmouseover", "this.bgColor='#76802B'");
  7800. break;
  7801. }
  7802. }
  7803. }
  7804. // Reset points position
  7805. {
  7806. var eleSpan = document.querySelector("h5 > span");
  7807. if (eleSpan)
  7808. {
  7809. eleSpan.parentElement.parentElement.removeAttribute("style");
  7810. }
  7811. }
  7812. } // End rally_results.php
  7813. if (/\/rallyreplay_?[0-9]{0,4}/.test(url))
  7814. {
  7815. document.body && document.body.classList.add("stsh_page_rallyReplay");
  7816. // Set cur lang to first
  7817. {
  7818. var elesFrame = document.querySelectorAll("#leftAreaContainer div[id^='frame']");
  7819. for (var i = 0; i < elesFrame.length; i++)
  7820. {
  7821. var first = elesFrame[i].querySelector(".gradienttable tr:nth-child(6)");
  7822. if (first)
  7823. {
  7824. var cur = null;
  7825. var tdLangs = elesFrame[i].querySelectorAll(".gradienttable tr > td:nth-child(1)");
  7826. for (var j = 0; j < tdLangs.length; j++)
  7827. {
  7828. if (lang === tdLangs[j].textContent.trim().toLowerCase())
  7829. {
  7830. cur = tdLangs[j].parentElement;
  7831. break;
  7832. }
  7833. }
  7834. if (cur)
  7835. {
  7836. cur.classList.add("stsh_curLang");
  7837. first.parentElement.insertBefore(cur, first);
  7838. }
  7839. }
  7840. }
  7841. }
  7842. var eleBtn = document.querySelector("input[value='FASTEST']");
  7843. if (eleBtn)
  7844. {
  7845. var ele = document.createElement("input");
  7846. ele.setAttribute("type", "button");
  7847. ele.setAttribute("value", "RESTART");
  7848. ele.setAttribute("style", "padding: 0; border: none; background: none;");
  7849. ele.setAttribute("onclick",
  7850. " \
  7851. indexReplay = 0; \
  7852. elsFrame.eq(indexReplay).fadeOut(0, function() \
  7853. { \
  7854. indexReplay = (indexReplay + 1) % lenFrame; \
  7855. elsFrame.eq(indexReplay).fadeIn(0); \
  7856. }); \
  7857. ");
  7858. insertAfterElement(ele, eleBtn);
  7859. insertAfterElement(document.createTextNode(" | "), eleBtn);
  7860. }
  7861. } // End rallyreplay.php
  7862. if (url.indexOf("/WhereIsEsty.php") > -1)
  7863. {
  7864. document.body && document.body.classList.add("stsh_page_whereIsEsty");
  7865. resizeSuggestionBox();
  7866. var outer = document.querySelector("#suggestions_box_outer");
  7867. if (outer)
  7868. {
  7869. outer.setAttribute("onclick", "hideSuggestionsBox();");
  7870. }
  7871. var divContainer = document.querySelector("#pageContainer");
  7872. if (divContainer)
  7873. {
  7874. var ele = document.createElement("div");
  7875. ele.id = "logout";
  7876. ele.innerHTML =
  7877. ' <a class="stsh_a_button" target="_blank" href="/home.php">Home</a> ';
  7878. divContainer.appendChild(ele);
  7879. }
  7880.  
  7881. var divContent = document.querySelector("#leftAreaContainer > div");
  7882. if (divContent)
  7883. {
  7884. var countSnap = document.querySelectorAll("div.box").length;
  7885. var user = "";
  7886. var name = "";
  7887.  
  7888. var eleImg = document.querySelector("#leftAreaContainer > div > div > a > img ");
  7889. if (eleImg)
  7890. {
  7891. name = eleImg.getAttribute("title");
  7892. user = eleImg.parentElement.getAttribute("href").replace("https://steamcommunity.com/profiles/", "");
  7893. }
  7894. var ele = document.createElement("div");
  7895. ele.classList.add("stsh_snapshot");
  7896. ele.innerHTML = "<a class='stsh_blue' target='_blank' href='/user_activity.php?user="
  7897. + user + "'>" + name + "</a>"
  7898. + "<br>Snapshot: " + countSnap;
  7899.  
  7900. divContent.appendChild(ele);
  7901. }
  7902. } // End WhereIsEsty.php
  7903. if (url.indexOf("/stickerbox.php") > -1)
  7904. {
  7905. document.body && document.body.classList.add("stsh_page_stickerbox");
  7906. document.querySelector("textarea[name='add_comment']").focus();
  7907. var inputPrev = document.querySelector("img[src*='z0lEQVRIx5WWaWxVRRTH'");
  7908. if (inputPrev)
  7909. {
  7910. addKeyCtrl(document, inputPrev, ["BracketLeft", 219]); // [
  7911. disableAfterClick(inputPrev);
  7912. }
  7913. var inputNext = document.querySelector("img[src*='40lEQVRIx5WWe0xXZRjH'");
  7914. if (inputNext)
  7915. {
  7916. addKeyCtrl(document, inputNext, ["BracketRight", 221, 171]); // ]
  7917. disableAfterClick(inputNext);
  7918. }
  7919. } // End stickerbox.php
  7920. if (/\/(home\.php|index\.php)/i.test(url))
  7921. {
  7922. document.body && document.body.classList.add("stsh_page_home");
  7923. // Add class
  7924. {
  7925. var elesH1 = document.querySelectorAll("#leftAreaContainer h1");
  7926. for (var i = 0; i < elesH1.length; i++)
  7927. {
  7928. var text = elesH1[i].textContent.trim();
  7929. if (text === "Current Serverwide Focus")
  7930. {
  7931. elesH1[i].classList.add("stsh_home_focus");
  7932. }
  7933. else if (text.indexOf("Oldest") === 0)
  7934. {
  7935. elesH1[i].classList.add("stsh_home_application");
  7936. }
  7937. else if (text.indexOf("Most Outdated") === 0)
  7938. {
  7939. elesH1[i].classList.add("stsh_home_untranslated");
  7940. }
  7941. else if (text === "Latest 10 Cross-Language Discussions About Certain Tokens")
  7942. {
  7943. elesH1[i].classList.add("stsh_home_discussion");
  7944. }
  7945. else if (text === "Overall Progress")
  7946. {
  7947. elesH1[i].classList.add("stsh_home_progress");
  7948. }
  7949. }
  7950. var elesLi = document.querySelectorAll("#alldiscussions > ul > li > ul > li");
  7951. for (var i = 0; i < elesLi.length; i++)
  7952. {
  7953. elesLi[i].classList.add("stsh_home_discussion_comment");
  7954. var eleFirst = elesLi[i].firstElementChild;
  7955. if (eleFirst && eleFirst.tagName === "FONT")
  7956. {
  7957. elesLi[i].classList.add("stsh_home_discussion_langCur");
  7958. }
  7959. else
  7960. {
  7961. elesLi[i].classList.add("stsh_home_discussion_langOther");
  7962. }
  7963. }
  7964. }
  7965. // Decode URI in discussion
  7966. {
  7967. var rgxUrl = /https?:[^ ]+/ig;;
  7968. var elesPost = document.querySelectorAll(".stsh_home_discussion_comment");
  7969. for (var i = 0; i < elesPost.length; i++)
  7970. {
  7971. for (var j = 0; j < elesPost[i].childNodes.length; j++)
  7972. {
  7973. if (elesPost[i].childNodes[j].nodeType === document.TEXT_NODE)
  7974. {
  7975. var isChanged = false;
  7976. var comment = elesPost[i].childNodes[j].textContent + " ";
  7977. var commentUrls = comment.match(rgxUrl) || [];
  7978. for (var k = 0; k < commentUrls.length; k++)
  7979. {
  7980. if (commentUrls[k].indexOf("%") > -1)
  7981. {
  7982. var urlDecode = commentUrls[k];
  7983. try
  7984. {
  7985. urlDecode = decodeURIComponent(commentUrls[k]);
  7986. isChanged = true;
  7987. }
  7988. catch (ex)
  7989. {
  7990. console.error("DecodeUriDiscussion", ex.message);
  7991. }
  7992. comment = comment.replace(commentUrls[k], urlDecode);
  7993. }
  7994. }
  7995. if (isChanged)
  7996. {
  7997. elesPost[i].childNodes[j].textContent = comment;
  7998. }
  7999. }
  8000. }
  8001. }
  8002. }
  8003. // Set cur lang to first
  8004. {
  8005. var first = null;
  8006. var cur = null;
  8007. var curLang = lang.substring(0, 4);
  8008. if (curLang === "schi")
  8009. curLang = "sim.";
  8010. else if (curLang === "tchi")
  8011. curLang = "tra.";
  8012. var eleLangs = document.querySelectorAll("#overall .progress");
  8013. if (eleLangs.length > 0)
  8014. {
  8015. first = eleLangs[0];
  8016. for (var i = 0; i < eleLangs.length; i++)
  8017. {
  8018. if (curLang === eleLangs[i].textContent.trim().substring(0, 4).toLowerCase())
  8019. {
  8020. cur = eleLangs[i];
  8021. break;
  8022. }
  8023. }
  8024. if (cur)
  8025. {
  8026. cur.classList.add("stsh_blue");
  8027. var curSib1 = cur.nextSibling;
  8028. var curSib2 = curSib1.nextSibling;
  8029. var curSib3 = curSib2.nextSibling;
  8030. var curSib4 = curSib3.nextSibling;
  8031. var curSib5 = curSib4.nextSibling;
  8032. var curSib6 = curSib5.nextSibling;
  8033. insertBeforeElement(cur, first);
  8034. insertAfterElement(curSib6, cur);
  8035. insertAfterElement(curSib5, cur);
  8036. insertAfterElement(curSib4, cur);
  8037. insertAfterElement(curSib3, cur);
  8038. insertAfterElement(curSib2, cur);
  8039. insertAfterElement(curSib1, cur);
  8040. }
  8041. }
  8042. }
  8043. if (document.querySelector("#logout"))
  8044. {
  8045. var tmplHome =
  8046. ' \
  8047. <div class="stsh_home_group"> \
  8048. <span class="stsh_home_header">Shortcuts</span> \
  8049. <div> \
  8050. <a class="stsh_a_button stsh_btn_med" target="_blank" \
  8051. href="/translate.php?search_input=DATE%3A+%DATE%&paginationrows=1000">New Today</a \
  8052. ><a class="stsh_a_button stsh_btn_med" target="_blank" href="/glossary.php">Glossary</a> \
  8053. </div> \
  8054. %PROFILE% \
  8055. <span class="stsh_home_header">Rally</span> \
  8056. <div> \
  8057. <a class="stsh_a_button stsh_btn_med" target="_blank" href="/rally.php">Rally</a \
  8058. >%RALLY% \
  8059. </div> \
  8060. <span class="stsh_home_header">Events</span> \
  8061. <div> \
  8062. <a class="stsh_a_button stsh_btn_med stsh_grey" target="_blank" href="/rallyreplay.php">Rally Replay</a \
  8063. ><a class="stsh_a_button stsh_btn_med stsh_grey" target="_blank" href="/onionolooorm.php">Typonion</a \
  8064. ><a class="stsh_a_button stsh_btn_med" target="_blank" href="/dstbattle.php">DST Battle</a \
  8065. ><a class="stsh_a_button stsh_btn_med" target="_blank" href="/dota2.php">DOTA 2</a> \
  8066. </div> \
  8067. <span class="stsh_home_header stsh_home_section_scroll">Scroll To</span> \
  8068. <div class="stsh_home_section_scroll"> \
  8069. <a class="stsh_a_button stsh_btn_med" onclick="window.scrollTo(0, 0); return false;" >Focus</a \
  8070. ><a class="stsh_a_button stsh_btn_med" onclick="scrollToElement(\'.stsh_home_untranslated\', -4); return false;" >Untranslated</a \
  8071. ><a class="stsh_a_button stsh_btn_med" onclick="scrollToElement(\'.stsh_home_discussion\', -4); return false;" >Discussion</a \
  8072. ><a class="stsh_a_button stsh_btn_med" onclick="scrollToElement(\'.stsh_home_progress\', -4); return false;" >Progress</a> \
  8073. </div> \
  8074. <br> \
  8075. <div><a class="stsh_a_button stsh_btn_med" target="_self" href="/home.php">Refresh</a></div> \
  8076. </div> \
  8077. ';
  8078. tmplHome = tmplHome.replace("%DATE%", getDateUs());
  8079. // Rally
  8080. {
  8081. var date = new Date();
  8082. var yearLast = date.getUTCFullYear();
  8083. var yearFirst = 2013;
  8084. var yearDisabled = [2015, 2018];
  8085. var isEven = (yearLast - yearFirst + (isRally() ? 1 : 0)) % 2 === 0;
  8086. var count = 0;
  8087. var strRally = "";
  8088. for (var i = yearLast; i >= yearFirst; i--)
  8089. {
  8090. if (i < yearLast || isRally())
  8091. {
  8092. if (count % 2 === (isEven ? 0 : 1))
  8093. {
  8094. strRally += '<div>';
  8095. }
  8096. if (count === 0 && !isEven)
  8097. {
  8098. strRally += '<div><a class="stsh_a_button stsh_btn_med'
  8099. + (yearDisabled.indexOf(i) > -1 ? " stsh_grey" : "")
  8100. + '" target="_blank" '
  8101. + 'href="/rally' + i + '.php">Rally ' + i + '</a></div>';
  8102. }
  8103. else
  8104. {
  8105. strRally += '<a class="stsh_a_button stsh_btn_short'
  8106. + (yearDisabled.indexOf(i) > -1 ? " stsh_grey" : "")
  8107. + '" target="_blank" '
  8108. + 'href="/rally' + i + '.php">' + i + '</a>';
  8109. }
  8110. if (count > 0 && count % 2 === (isEven ? 1 : 0))
  8111. {
  8112. strRally += '</div>';
  8113. }
  8114. count++;
  8115. }
  8116. }
  8117. tmplHome = tmplHome.replace("%RALLY%", strRally);
  8118. }
  8119. // Profile
  8120. {
  8121. var strProfile = "";
  8122. if (userId)
  8123. {
  8124. strProfile = '<div class="stsh_group_space">'
  8125. + '<a class="stsh_a_button stsh_btn_med" target="_blank" '
  8126. + 'href="/translate.php?user=' + userId
  8127. + '&listsort=5&liststatus=1&paginationrows=1000">My Suggestions</a>';
  8128. var userMod = GM_getValue("mod", "");
  8129. if (userMod === userId)
  8130. {
  8131. strProfile += '<a class="stsh_a_button stsh_btn_med" target="_blank" '
  8132. + 'href="/translate.php?user=' + userId
  8133. + '&moderator=1&listsort=5&liststatus=3&paginationrows=1000">My Reviews</a>';
  8134. }
  8135. strProfile += '</div>';
  8136. }
  8137. tmplHome = tmplHome.replace("%PROFILE%", strProfile);
  8138. }
  8139. var eleNew = document.createElement("div");
  8140. eleNew.innerHTML = tmplHome;
  8141. document.body.appendChild(eleNew);
  8142. }
  8143. // Fix STS JS error
  8144. {
  8145. var eleTimer = document.querySelector("#timer");
  8146. if (!eleTimer)
  8147. {
  8148. var ele = document.createElement("div");
  8149. ele.id = "timer";
  8150. ele.classList.add("stsh_hidden");
  8151. document.body.appendChild(ele);
  8152. }
  8153. }
  8154. // Add rows per page
  8155. {
  8156. var eleAs = document.querySelectorAll("#leftAreaContainer > div:not([id]) >.progress a[href^='translate.php?']");
  8157. for (var i = 0; i < eleAs.length; i++)
  8158. {
  8159. eleAs[i].href = eleAs[i].href + "&paginationrows=1000";
  8160. }
  8161. }
  8162. // Add counter to title
  8163. {
  8164. var counter = [0, 0];
  8165. var eleComment = document.querySelector("#leftAreaContainer > b > a[href^='user_activity.php?user=']:nth-child(3)");
  8166. if (eleComment)
  8167. {
  8168. counter[0] = eleComment.textContent.trim();
  8169. }
  8170. var elePrivate = document.querySelector("#titleprivatemessages");
  8171. if (elePrivate)
  8172. {
  8173. var rgxPrivate = /Private Messages \((\d) new\)/i;
  8174. counter[1] =(elePrivate.textContent.match(rgxPrivate) || [0, 0])[1];
  8175. }
  8176. if (counter[0] && counter[1])
  8177. {
  8178. document.title = "(" + counter[0] + "," + counter[1] + ") " + document.title;
  8179. }
  8180. else if (counter[0] || counter[1])
  8181. {
  8182. document.title = "(" + (counter[0] || counter[1]) + ") " + document.title;
  8183. }
  8184. }
  8185. // Toggle file discussion
  8186. {
  8187. var elesLi = document.querySelectorAll("#alldiscussions > ul > li");
  8188. for (var i = 0; i < elesLi.length; i++)
  8189. {
  8190. var node = elesLi[i].firstChild;
  8191. if (node && node.nodeType === document.TEXT_NODE)
  8192. {
  8193. var eleSpan = document.createElement("span");
  8194. eleSpan.classList.add("stsh_home_discussion_file");
  8195. eleSpan.textContent = node.textContent;
  8196. elesLi[i].replaceChild(eleSpan, node);
  8197. eleSpan.addEventListener("click", function(ev)
  8198. {
  8199. var eleTarget = ev.target;
  8200. var eleUl = eleTarget.nextElementSibling;
  8201. if (eleUl && eleUl.tagName === "UL")
  8202. {
  8203. if (eleUl.style.display === "none")
  8204. {
  8205. eleUl.style.display = "block";
  8206. }
  8207. else
  8208. {
  8209. eleUl.style.display = "none";
  8210. }
  8211. }
  8212. });
  8213. }
  8214. }
  8215. }
  8216. // Hide other languages
  8217. {
  8218. var eleAllDiscuss = document.querySelector("#alldiscussions");
  8219. if (eleAllDiscuss)
  8220. {
  8221. var strHide = "Hide other languages";
  8222. var strShow = "Show other languages";
  8223. var eleBtn = document.createElement("input");
  8224. eleBtn.classList.add("stsh_home_hideOtherLang");
  8225. eleBtn.type = "button";
  8226. eleBtn.value = strHide;
  8227. eleBtn.dataset.modeNext = "hide";
  8228. insertBeforeElement(eleBtn, eleAllDiscuss.firstElementChild);
  8229.  
  8230. eleBtn.addEventListener("click", function(ev)
  8231. {
  8232. var eleTarget = ev.target;
  8233. var mode = "hide";
  8234. if (eleTarget.dataset.modeNext === "hide")
  8235. {
  8236. mode = "hide";
  8237. eleTarget.dataset.modeNext = "show";
  8238. eleTarget.value = strShow;
  8239. }
  8240. else
  8241. {
  8242. mode = "show";
  8243. eleTarget.dataset.modeNext = "hide";
  8244. eleTarget.value = strHide;
  8245. }
  8246. if (mode === "hide")
  8247. {
  8248. var elesLang = document.querySelectorAll(".stsh_home_discussion_langOther");
  8249. for (var i = 0; i < elesLang.length; i++)
  8250. {
  8251. elesLang[i].classList.add("stsh_hidden");
  8252. }
  8253. }
  8254. else
  8255. {
  8256. var elesLang = document.querySelectorAll(".stsh_home_discussion_langOther.stsh_hidden");
  8257. for (var i = 0; i < elesLang.length; i++)
  8258. {
  8259. elesLang[i].classList.remove("stsh_hidden");
  8260. }
  8261. }
  8262. });
  8263. }
  8264. }
  8265. // Correct app links
  8266. {
  8267. var strIncludeApps = "&includeapps=1";
  8268. var elesApp = document.querySelectorAll("a[href^='translate.php?lang=thai&search_input=%23app_']");
  8269. for (var i = 0; i < elesApp.length; i++)
  8270. {
  8271. var href = elesApp[i].getAttribute("href");
  8272. if (href.indexOf(strIncludeApps) < 0)
  8273. {
  8274. elesApp[i].setAttribute("href", href + strIncludeApps);
  8275. }
  8276. }
  8277. }
  8278. } // End home.php
  8279. if (url.indexOf("/glossary.php") > -1)
  8280. {
  8281. document.body && document.body.classList.add("stsh_page_glossary");
  8282. // Add shortcuts
  8283. {
  8284. var contentGlos =
  8285. ' \
  8286. <div class="stsh_home_group"> \
  8287. <span class="stsh_home_header">Shortcuts</span> \
  8288. <br> &nbsp; \
  8289. <a class="stsh_a_button stsh_btn_med" target="_blank" \
  8290. href="/translate.php?chosenfile=1&listfilter=1&listsort=3&paginationrows=1000&branch_ID=49&file_ID=226"> \
  8291. Glossary</a> &nbsp; \
  8292. <br> &nbsp; \
  8293. <a class="stsh_a_button stsh_btn_med" target="_blank" \
  8294. href="/translate.php?chosenfile=1&listfilter=1&listsort=3&paginationrows=1000&branch_ID=49&file_ID=232"> \
  8295. Phrases</a> &nbsp; \
  8296. <br> \
  8297. </div> \
  8298. ';
  8299. var eleNew = document.createElement("div");
  8300. eleNew.innerHTML = contentGlos;
  8301. document.body.appendChild(eleNew);
  8302. }
  8303. // Improve glossary links
  8304. {
  8305. var elesLink = document.querySelectorAll("#votes_container > .lbAction a[href^='./translate.php?search_input=']");
  8306. for (var i = 0; i < elesLink.length; i++)
  8307. {
  8308. elesLink[i].href = elesLink[i].href.replace("keyonly=0", "keyonly=2")
  8309. .replace("listsort=0", "listsort=4")
  8310. .replace("paginationrows=50", "paginationrows=1000");
  8311. }
  8312. }
  8313. } // End glossary.php
  8314. if (url.indexOf("/dstbattle.php") > -1)
  8315. {
  8316. document.body && document.body.classList.add("stsh_page_dstbattle");
  8317. // Hilight cur lang
  8318. {
  8319. var cur = null;
  8320. var elesLang = document.querySelectorAll(".gradienttable > tbody:nth-child(1) > tr > th:nth-child(1)");
  8321. for (var i = 1; i < elesLang.length; i++)
  8322. {
  8323. if (lang === elesLang[i].textContent.trim().replace(/[0-9]+\. /, "").toLowerCase())
  8324. {
  8325. cur = elesLang[i].parentElement;
  8326. break;
  8327. }
  8328. }
  8329. if (cur)
  8330. {
  8331. cur.classList.add("stsh_dst_curLang");
  8332. }
  8333. }
  8334. } // End dstbattle.php
  8335. if (url.indexOf("/statistics.php") > -1)
  8336. {
  8337. document.body && document.body.classList.add("stsh_page_statistics");
  8338. setTimeoutCustom(function()
  8339. {
  8340. var qBranch = getQueryByName("branch_ID");
  8341. var qFile = getQueryByName("file_ID");
  8342. if (qBranch === "" && qFile === "")
  8343. {
  8344. var getProgress = function(content)
  8345. {
  8346. content = content.trim();
  8347. var rgxNum = /[0-9]+/g;
  8348. var data = "";
  8349. if (content.indexOf("<15") > -1)
  8350. {
  8351. data = "014"
  8352. }
  8353. else if (content.indexOf("100") < 0)
  8354. {
  8355. data = "0" + (content.match(rgxNum) || ["00"])[0];
  8356. }
  8357. else
  8358. {
  8359. data = "100";
  8360. }
  8361. return data;
  8362. }
  8363. var branch = "";
  8364. var elesTr = document.querySelectorAll(".tableprogress tr");
  8365. for (var i = 0; i < elesTr.length; i++)
  8366. {
  8367. var eleH = elesTr[i].querySelector("h2");
  8368. if (eleH)
  8369. {
  8370. branch = eleH.textContent.trim();
  8371. }
  8372. else
  8373. {
  8374. var eleA = elesTr[i].querySelector("td:nth-child(2) > a:nth-child(1)[href^='translate.php']");
  8375. if (eleA)
  8376. {
  8377. elesTr[i].classList.add("stsh_stat_progress");
  8378. elesTr[i].dataset.translated = getProgress(eleA.textContent);
  8379. elesTr[i].dataset.approved = getProgress(
  8380. eleA.parentElement.nextElementSibling.firstElementChild.textContent);
  8381. elesTr[i].dataset.branch = branch;
  8382. elesTr[i].dataset.file = elesTr[i].firstElementChild.textContent.trim();
  8383. }
  8384. }
  8385. }
  8386. var eleDiv = document.createElement("div");
  8387. document.body.appendChild(eleDiv);
  8388. eleDiv.innerHTML =
  8389. ' \
  8390. <div class="stsh_showing_group"> \
  8391. <span class="stsh_showing_header">Hide</span>\
  8392. <br> &nbsp; <input id="stsh_stat_hideGame" value="Game" class="stsh_btn_short" type="button" /> \
  8393. <input id="stsh_stat_hideSteam" value="Steam" class="stsh_btn_short" type="button" /> \
  8394. <br> &nbsp; <input id="stsh_stat_hideApproved" value="Approved" class="stsh_btn_long" type="button" /> \
  8395. <br> &nbsp; <input id="stsh_stat_hideCompleted" value="Completed" class="stsh_btn_long" type="button" /> \
  8396. <br> \
  8397. <br> &nbsp; <input id="stsh_stat_showAll" value="Show All" class="stsh_btn_long" type="button" /> \
  8398. </div> \
  8399. ';
  8400.  
  8401. var eleHideGame = document.querySelector("#stsh_stat_hideGame");
  8402. eleHideGame.addEventListener("click", function()
  8403. {
  8404. var elesProgress = document.querySelectorAll(".stsh_stat_progress:not(.stsh_hidden)");
  8405. for (var i = 0; i < elesProgress.length; i++)
  8406. {
  8407. if (elesProgress[i].dataset.branch.indexOf("games/") === 0)
  8408. {
  8409. elesProgress[i].classList.add("stsh_hidden");
  8410. }
  8411. }
  8412. });
  8413. var eleHideSteam = document.querySelector("#stsh_stat_hideSteam");
  8414. eleHideSteam.addEventListener("click", function()
  8415. {
  8416. var elesProgress = document.querySelectorAll(".stsh_stat_progress:not(.stsh_hidden)");
  8417. for (var i = 0; i < elesProgress.length; i++)
  8418. {
  8419. if (elesProgress[i].dataset.branch.indexOf("steam") === 0)
  8420. {
  8421. elesProgress[i].classList.add("stsh_hidden");
  8422. }
  8423. }
  8424. });
  8425. var eleHideApproved = document.querySelector("#stsh_stat_hideApproved");
  8426. eleHideApproved.addEventListener("click", function()
  8427. {
  8428. var elesProgress = document.querySelectorAll(".stsh_stat_progress:not(.stsh_hidden)");
  8429. for (var i = 0; i < elesProgress.length; i++)
  8430. {
  8431. if (elesProgress[i].dataset.translated === elesProgress[i].dataset.approved)
  8432. {
  8433. elesProgress[i].classList.add("stsh_hidden");
  8434. }
  8435. }
  8436. });
  8437. var eleHideCompleted = document.querySelector("#stsh_stat_hideCompleted");
  8438. eleHideCompleted.addEventListener("click", function()
  8439. {
  8440. var elesProgress = document.querySelectorAll(".stsh_stat_progress:not(.stsh_hidden)");
  8441. for (var i = 0; i < elesProgress.length; i++)
  8442. {
  8443. if (elesProgress[i].dataset.translated === "100" && elesProgress[i].dataset.approved === "100")
  8444. {
  8445. elesProgress[i].classList.add("stsh_hidden");
  8446. }
  8447. }
  8448. });
  8449. var eleShowAll = document.querySelector("#stsh_stat_showAll");
  8450. eleShowAll.addEventListener("click", function()
  8451. {
  8452. var elesProgress = document.querySelectorAll(".stsh_stat_progress.stsh_hidden");
  8453. for (var i = 0; i < elesProgress.length; i++)
  8454. {
  8455. elesProgress[i].classList.remove("stsh_hidden");
  8456. }
  8457. });
  8458. }
  8459. // Add rows per page
  8460. {
  8461. var eleAs = document.querySelectorAll("#leftAreaContainer a[href^='translate.php?']");
  8462. for (var i = 0; i < eleAs.length; i++)
  8463. {
  8464. eleAs[i].href = eleAs[i].href + "&paginationrows=1000";
  8465. }
  8466. }
  8467. }, timingInit.improveStatistics);
  8468. } // End statistics.php
  8469. if (url.indexOf("index.php") > -1
  8470. || url === "https://translation.steampowered.com/")
  8471. {
  8472. document.body && document.body.classList.add("stsh_page_index");
  8473. var eleDes = document.querySelector("#verify-form > form");
  8474. if (eleDes)
  8475. {
  8476. var eleSpan = document.createElement("span");
  8477. eleSpan.classList.add("stsh_autoLoginOption");
  8478.  
  8479. var eleInput = document.createElement("input");
  8480. eleInput.id = "stsh_autoLogin";
  8481. eleInput.setAttribute("type", "checkbox");
  8482. eleInput.setAttribute("value", "auto");
  8483. var autoLogin = function()
  8484. {
  8485. var eleImage = document.querySelector("#verify-form > form > input[class='image']");
  8486. if (eleImage)
  8487. {
  8488. setTimeoutCustom(function()
  8489. {
  8490. var eleInput = document.querySelector("#stsh_autoLogin");
  8491. if (eleInput && eleInput.checked)
  8492. {
  8493. eleImage.click();
  8494. }
  8495. }, timingInit.autoLogin);
  8496. }
  8497. }
  8498. if (GM_getValue("autoLogin", 0) === "true")
  8499. {
  8500. eleInput.checked = true;
  8501. autoLogin();
  8502. }
  8503.  
  8504. eleInput.addEventListener("click", function (e)
  8505. {
  8506. var ele = e.target;
  8507. if (ele.checked)
  8508. {
  8509. GM_setValue("autoLogin", "true");
  8510. autoLogin();
  8511. }
  8512. else
  8513. {
  8514. GM_setValue("autoLogin", "false");
  8515. }
  8516. });
  8517.  
  8518. var eleLabel = document.createElement("label");
  8519. eleLabel.setAttribute("for", "stsh_autoLogin");
  8520. eleLabel.textContent = " Auto Login";
  8521. eleLabel.title = "Auto click login button"
  8522.  
  8523. eleSpan.appendChild(eleInput);
  8524. eleSpan.appendChild(eleLabel);
  8525. eleDes.appendChild(eleSpan);
  8526. }
  8527. } // End index.php
  8528. if (url.indexOf("try_auth.php") > -1)
  8529. {
  8530. document.body && document.body.classList.add("stsh_page_tryAuth");
  8531. setTimeoutCustom(function()
  8532. {
  8533. document.forms[0].submit();
  8534. }, timingInit.authSubmit);
  8535. } // End try_auth.php
  8536. window.addEventListener("beforeunload", function (e)
  8537. {
  8538. clearTimeoutAll();
  8539. clearIntervalAll();
  8540. });
  8541. if (perfStart > 0)
  8542. {
  8543. var perfEnd = performance.now();
  8544. //console.log("STS Helper - Perf: " + (perfEnd - perfStart).toFixed(2) + "ms, Page: " + window.location.pathname);
  8545. }
  8546. } // End Main
  8547.  
  8548. function client()
  8549. {
  8550. var clientScript =
  8551. ' \
  8552. /* STSH JS - clientScript */ \
  8553. var timeoutList = []; \
  8554. var intervalList = []; \
  8555. \
  8556. function setTimeoutCustom(func, tm, params) \
  8557. { \
  8558. var id = setTimeout(func, tm, params); \
  8559. timeoutList.push(id); \
  8560. return id; \
  8561. } \
  8562. \
  8563. function clearTimeoutAll() \
  8564. { \
  8565. for (var i = 0; i < timeoutList.length; i++) \
  8566. { \
  8567. clearTimeout(timeoutList[i]); \
  8568. } \
  8569. } \
  8570. \
  8571. function setIntervalCustom(func, tm, params) \
  8572. { \
  8573. var id = setInterval(func, tm, params); \
  8574. intervalList.push(id); \
  8575. return id; \
  8576. } \
  8577. \
  8578. function clearIntervalAll() \
  8579. { \
  8580. for (var i = 0; i < intervalList.length; i++) \
  8581. { \
  8582. clearInterval(intervalList[i]); \
  8583. } \
  8584. } \
  8585. \
  8586. function scrollToId(id, offset) \
  8587. { \
  8588. scrollToElement("#" + id, offset); \
  8589. } \
  8590. \
  8591. function scrollToElement(selector, offset) \
  8592. { \
  8593. if (typeof offset === "undefined") \
  8594. { \
  8595. offset = -20; \
  8596. } \
  8597. \
  8598. var ele = document.querySelector(selector); \
  8599. if (ele) \
  8600. { \
  8601. ele.scrollIntoView(true); \
  8602. window.scrollBy(0, offset); \
  8603. } \
  8604. } \
  8605. \
  8606. function getTimeMs() \
  8607. { \
  8608. return (new Date()).getTime(); \
  8609. } \
  8610. \
  8611. function registerHideSuggestion() \
  8612. { \
  8613. if (typeof hideSuggestionsBox !== "undefined" || (parent && parent.hideSuggestionsBox)) \
  8614. { \
  8615. document.addEventListener("keydown", function(e) \
  8616. { \
  8617. if (e.keyCode === 27) \
  8618. { \
  8619. if (parent) \
  8620. { \
  8621. parent.hideSuggestionsBox(); \
  8622. } \
  8623. else \
  8624. { \
  8625. hideSuggestionsBox(); \
  8626. } \
  8627. } \
  8628. return false; \
  8629. }); \
  8630. } \
  8631. } \
  8632. registerHideSuggestion(); \
  8633. \
  8634. function doubleClickHideSuggestion(ele) \
  8635. { \
  8636. var maxDiff = 3000; \
  8637. var msDiff = maxDiff; \
  8638. var isEdited = false; \
  8639. \
  8640. if (ele && ele.dataset) \
  8641. { \
  8642. msDiff = getTimeMs() - (ele.dataset.stshHideSuggestion || 0); \
  8643. isEdit = ele.dataset.stshTextEdited === "true"; \
  8644. } \
  8645. \
  8646. if (!isEdit || msDiff < maxDiff) \
  8647. { \
  8648. hideSuggestionsBox(); \
  8649. ele.dataset.stshHideSuggestion = 0; \
  8650. } \
  8651. else \
  8652. { \
  8653. ele.dataset.stshHideSuggestion = getTimeMs(); \
  8654. } \
  8655. } \
  8656. \
  8657. function clickToSelect(ele) \
  8658. { \
  8659. var range = document.createRange(); \
  8660. range.setStartBefore(ele.firstChild); \
  8661. range.setEndAfter(ele.lastChild); \
  8662. var sel = window.getSelection(); \
  8663. sel.removeAllRanges(); \
  8664. sel.addRange(range); \
  8665. } \
  8666. \
  8667. function syncUrlArray() \
  8668. { \
  8669. var strStart = "showSuggestionsBox( \'"; \
  8670. var strEnd = "\' ); return false;"; \
  8671. var strCur = "&list_id="; \
  8672. var strAll = "&endnext="; \
  8673. var regPos = /&list_id=\\d+&endnext=\\d+/g; \
  8674. var isEdit = false; \
  8675. var eleDivs = []; \
  8676. var urls = []; \
  8677. \
  8678. var pattUrlTimestamp = \
  8679. { \
  8680. type2: /\\&t=[0-9]{6,}/g, \
  8681. type4: /\\&[0-9]{6,}\\&/g, \
  8682. }; \
  8683. \
  8684. var trKeys = document.querySelectorAll("#keylist > table:nth-child(1) > tbody:nth-child(1) > tr"); \
  8685. for (var i = 0; i < trKeys.length; i++) \
  8686. { \
  8687. if (!trKeys[i].classList.contains("stsh_hidden")) \
  8688. { \
  8689. var eleDiv = trKeys[i].childNodes[0].childNodes[0]; \
  8690. if (typeof eleDiv.getAttribute !== "undefined" \
  8691. && eleDiv.getAttribute("onclick")) \
  8692. { \
  8693. eleDivs.push(eleDiv); \
  8694. } \
  8695. } \
  8696. } \
  8697. \
  8698. for (var i = 0, l = eleDivs.length; i < l; i++) \
  8699. { \
  8700. var evOld = eleDivs[i].getAttribute("onclick"); \
  8701. if (evOld) \
  8702. { \
  8703. var url = evOld.replace(strStart,"").replace(strEnd,"").replace(regPos,""); \
  8704. url = url + strCur + i + strAll + l; \
  8705. \
  8706. if (pattUrlTimestamp.type2.test(url)) \
  8707. { \
  8708. url = url.replace(pattUrlTimestamp.type2, ""); \
  8709. } \
  8710. if (pattUrlTimestamp.type4.test(url)) \
  8711. { \
  8712. url = url.replace(pattUrlTimestamp.type4, "&"); \
  8713. } \
  8714. \
  8715. urls.push(url); \
  8716. \
  8717. var evNew = strStart + url + strEnd; \
  8718. if (evOld !== evNew) \
  8719. { \
  8720. eleDivs[i].setAttribute("onclick", evNew); \
  8721. isEdit = true; \
  8722. } \
  8723. } \
  8724. } \
  8725. \
  8726. if (isEdit || typeof URLarray === "undefined" || URLarray.length !== urls.length) \
  8727. { \
  8728. URLarray = urls; \
  8729. } \
  8730. } \
  8731. \
  8732. function setFrameColor(color) \
  8733. { \
  8734. var frame = document.querySelector("div#suggestions_box iframe"); \
  8735. if (frame) \
  8736. { \
  8737. if (frame.style.backgroundColor !== color) \
  8738. { \
  8739. frame.style.setProperty("background-color", color, "important"); \
  8740. } \
  8741. } \
  8742. } \
  8743. \
  8744. function padZero(num, size) \
  8745. { \
  8746. return (1e15+num+"").slice(-size); \
  8747. } \
  8748. \
  8749. function doInstant() \
  8750. { \
  8751. var url = document.documentURI; \
  8752. \
  8753. /* Fix STS JS error */ \
  8754. setTimeoutCustom(function() \
  8755. { \
  8756. if (typeof hide_list === "undefined") \
  8757. { \
  8758. hide_list = function() { /*console.log("sts: hide_list");*/ }; \
  8759. } \
  8760. \
  8761. if (typeof changeIt === "undefined") \
  8762. { \
  8763. changeIt = function() { /*console.log("sts: changeIt");*/ }; \
  8764. } \
  8765. \
  8766. if (typeof getendnext === "undefined") \
  8767. { \
  8768. getendnext = function() { /*console.log("sts: getendnext");*/ return ""; }; \
  8769. } \
  8770. }, 1000); \
  8771. \
  8772. if (url.indexOf("user_activity.php") > -1) \
  8773. { \
  8774. setTimeoutCustom(function() \
  8775. { \
  8776. if (typeof $ !== "undefined") \
  8777. { \
  8778. /* Restore drawing progress */ \
  8779. $(".dial").css("display", "inline"); \
  8780. $(".dial").knob( \
  8781. { \
  8782. "draw": function() \
  8783. { \
  8784. $(this.i).val(this.cv + "%"); \
  8785. } \
  8786. }); \
  8787. } \
  8788. }, 500); \
  8789. } \
  8790. else if (url.indexOf("translate.php") > -1) \
  8791. { \
  8792. getsuggestionURL = function(urlno) \
  8793. { \
  8794. /* Overwrite STS to remove timestamp */ \
  8795. return URLarray[urlno]; \
  8796. }; \
  8797. \
  8798. var obTarget_sync = document.querySelector("#keylist_container"); \
  8799. if (obTarget_sync) \
  8800. { \
  8801. var tmOb_sync = -1; \
  8802. var obMu_sync = new MutationObserver(function(mutations) \
  8803. { \
  8804. mutations.forEach(function(mutation) \
  8805. { \
  8806. if (mutation.type !== "attributes" \
  8807. || mutation.target.tagName === "TR") \
  8808. { \
  8809. clearTimeout(tmOb_sync); \
  8810. tmOb_sync = setTimeoutCustom(function() \
  8811. { \
  8812. syncUrlArray(); \
  8813. /*console.log("syncUrlArray: " + tmOb_sync);*/ \
  8814. }, 50); \
  8815. } \
  8816. }); \
  8817. }); \
  8818. \
  8819. var obConfig_sync = { childList: true, subtree: true, attributes: true, attributeFilter: ["class"] }; \
  8820. obMu_sync.observe(obTarget_sync, obConfig_sync); \
  8821. } \
  8822. } \
  8823. else if (url.indexOf("suggestions.php") > -1) \
  8824. { \
  8825. if (parent !== window) \
  8826. { \
  8827. var main = document.querySelector("#suggestionmain"); \
  8828. if (main) \
  8829. { \
  8830. var styleCp = window.getComputedStyle(main); \
  8831. if (styleCp) \
  8832. { \
  8833. var color = styleCp.backgroundColor; \
  8834. parent.setFrameColor(color); \
  8835. } \
  8836. } \
  8837. } \
  8838. } \
  8839. \
  8840. window.addEventListener("beforeunload", function (e) \
  8841. { \
  8842. clearTimeoutAll(); \
  8843. clearIntervalAll(); \
  8844. }); \
  8845. \
  8846. } \
  8847. doInstant(); \
  8848. \
  8849. ';
  8850.  
  8851. var eleClientScript = document.createElement("script");
  8852. eleClientScript.innerHTML = clientScript;
  8853. document.head.appendChild(eleClientScript);
  8854. } // End client
  8855.  
  8856. attachOnReady(initStyle);
  8857. attachOnReady(client);
  8858. attachOnReady(main);
  8859.  
  8860. })();
  8861.  
  8862. // End