WME TTS test

Play TTS

  1. // ==UserScript==
  2. // @name WME TTS test
  3. // @description Play TTS
  4. // @version 0.11
  5. // @author Vinkoy
  6. // @include https://www.waze.com/editor/*
  7. // @include https://www.waze.com/*/editor/*
  8. // @include https://editor-beta.waze.com/editor/*
  9. // @include https://editor-beta.waze.com/*/editor/*
  10. // @namespace https://greasyfork.org/en/scripts/23202-wme-tts-test
  11. // @grant none
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. var minutes_value = 20;
  16. var round_exit_value = 1;
  17.  
  18. function TTStest_bootstrap()
  19. {
  20. var oWaze=Window.W;
  21. var oI18n=Window.I18n;
  22.  
  23. if (typeof unsafeWindow !== "undefined")
  24. {
  25. oWaze=unsafeWindow.W;
  26. oI18n=unsafeWindow.I18n;
  27. }
  28.  
  29. if (typeof oWaze === "undefined")
  30. {
  31. setTimeout(TTStest_bootstrap, 500);
  32. return;
  33. }
  34. if (typeof oWaze.map === "undefined")
  35. {
  36. setTimeout(TTStest_bootstrap, 500);
  37. return;
  38. }
  39. if (typeof oWaze.selectionManager === "undefined")
  40. {
  41. setTimeout(TTStest_bootstrap, 500);
  42. return;
  43. }
  44. if (typeof oI18n === "undefined")
  45. {
  46. setTimeout(TTStest_bootstrap, 500);
  47. return;
  48. }
  49. if (typeof oI18n.translations === "undefined")
  50. {
  51. setTimeout(TTStest_bootstrap, 500);
  52. return;
  53. }
  54.  
  55. oWaze.selectionManager.events.register("selectionchanged", null, addBtns);
  56. setTimeout(TTStest_initBindKey, 500);
  57. }
  58.  
  59. function addBtns()
  60. {
  61. if(!document.getElementById("WME-test-tts") && W.selectionManager.getSelectedFeatures().length > 0 && W.selectionManager.getSelectedFeatures()[0].model.type === 'segment')
  62. {
  63. var btnSection = document.createElement('div');
  64. btnSection.id = "WME-test-tts";
  65. var userTabs = document.getElementById('edit-panel');
  66. if (!(userTabs && getElementsByClassName('nav-tabs', userTabs)))
  67. return;
  68.  
  69. var navTabs = getElementsByClassName('nav-tabs', userTabs)[0];
  70. if (typeof navTabs !== "undefined")
  71. {
  72. if (!getElementsByClassName('tab-content', userTabs))
  73. return;
  74.  
  75. var tabContent = getElementsByClassName('tab-content', userTabs)[0];
  76.  
  77. if (typeof tabContent !== "undefined")
  78. {
  79. newtab = document.createElement('li');
  80. newtab.innerHTML = '<a href="#WME-test-tts" id="wmettstest" data-toggle="tab">TTS <i class="fa fa-lock" id="wmetts_lock"></i></a>';
  81. navTabs.appendChild(newtab);
  82.  
  83. var class_style_turn = 'class="btn btn-default" style="font-size:18px; width:40px; padding:0px; background-color: #4CC600; cursor: pointer;" ';
  84. var class_style_keep = 'class="btn btn-default" style="font-size:18px; width:40px; padding:0px; background-color: #CBFF84; cursor: pointer;" ';
  85. var class_style_exit = 'class="btn btn-default" style="font-size:18px; width:40px; padding:0px; background-color: #6CB5FF; cursor: pointer;" ';
  86. var class_style_roundabout = 'class="btn btn-default" style="font-size:24px; width:40px; padding:0px; cursor: pointer;" ';
  87.  
  88. var street = W.model.streets.get(W.selectionManager.getSelectedFeatures()[0].model.attributes.primaryStreetID);
  89. var streetName = 'Безымянный сегмент';
  90. if (typeof street !== "undefined" && street !== null)
  91. {
  92. if (street.name !== null)
  93. {
  94. streetName = street.name;
  95. }
  96. }
  97.  
  98. btnSection.innerHTML = '<div class="form-group">'+
  99. '<h4>TTS Test <sup>' + GM_info.script.version + '</sup>&nbsp;<sub><a href="https://greasyfork.org/en/scripts/23202-wme-tts-test" title="Link" target="_blank"><span class="fa fa-external-link"></span></a></sub></h4>' +
  100. '<div class="controls-container">' +
  101. '</br>' +
  102. '<button id="wmettsStreet" class="btn btn-default" title="'+streetName+'"><i class="fa fa-volume-up" style="font-size:16px;"></i>&nbsp;&nbsp;'+streetName+'</button>&nbsp;' +
  103. '</br></br>' +
  104. '<button id="wmettsContinue" class="btn btn-default" title="Продолжайте движение около '+minutes_value+' минут"><i class="fa fa-volume-up" style="font-size:16px;"></i>&nbsp;&nbsp;Продолжайте движение около</button>&nbsp;' +
  105. '</br>' +
  106. '<input type="number" id="minutes" value="'+minutes_value+'" style="width: 60px; margin-top: 5px;"/>&nbsp; минут' +
  107. '</br>' +
  108. '<button id="wmettsContStraight" class="btn btn-default" title="Продолжайте движение прямо на "><i class="fa fa-volume-up" style="font-size:16px;"></i>&nbsp;&nbsp;Продолжайте движение прямо на <i>'+streetName+'</i></button>&nbsp;' +
  109. '</br>' +
  110. '<button id="wmettsUturn" class="btn btn-default" title="Развернитесь на '+streetName+'"><i class="fa fa-volume-up" style="font-size:16px;"></i>&nbsp;&nbsp; Развернитесь на <i>'+streetName+'</i></button>&nbsp;' +
  111. '</br>' +
  112. '<button id="wmettsGoing" class="btn btn-default" title="поедем по '+streetName+'"><i class="fa fa-volume-up" style="font-size:16px;"></i>&nbsp;&nbsp; Поедем по <i>'+streetName+'</i></button>&nbsp;' +
  113. '</br></br>' +
  114. '<label class="control-label">Поверните...</label>' +
  115. '<button id="wmettsTL" '+class_style_turn+' title="Поверните налево">←</button>&nbsp;' +
  116. '<button id="wmettsTR" '+class_style_turn+' title="Поверните направо">→</button>&nbsp;' +
  117. '</br></br>' +
  118. '<label class="control-label">Держитесь...</label>' +
  119. '<button id="wmettsKL" '+class_style_keep+' title="Держитесь левее">↖</button>&nbsp;' +
  120. '<button id="wmettsKR" '+class_style_keep+' title="Держитесь правее">↗</button>&nbsp;' +
  121. '</br></br>' +
  122. '<label class="control-label">Съезд...</label>' +
  123. '<button id="wmettsEL" '+class_style_exit+' title="Съезд слева">↖</button>&nbsp;' +
  124. '<button id="wmettsER" '+class_style_exit+' title="Съезд справа">↗</button>&nbsp;' +
  125. '</br></br>' +
  126. '<label class="control-label">Съезд на кольце...</label>' +
  127. '<button id="wmettsRND" '+class_style_roundabout+' title="На кольце '+round_exit_value+' съезд">☼</button>&nbsp;' +
  128. '<input type="number" id="round_exit" value="'+round_exit_value+'" min="1" max="7" style="width: 60px; margin-top: 5px;"/>&nbsp; съезд' +
  129. '</div></div>';
  130.  
  131. btnSection.className = "tab-pane";
  132. tabContent.appendChild(btnSection);
  133. }
  134. else
  135. btnSection.id='';
  136. }
  137. else
  138. btnSection.id='';
  139.  
  140. if(btnSection.id !== '')
  141. {
  142. document.getElementById('wmettsStreet').onclick = playTTS;
  143. document.getElementById('wmettsContinue').onclick = playTTS;
  144. document.getElementById('wmettsContStraight').onclick = playTTS;
  145. document.getElementById('wmettsTL').onclick = playTTS;
  146. document.getElementById('wmettsTR').onclick = playTTS;
  147. document.getElementById('wmettsKL').onclick = playTTS;
  148. document.getElementById('wmettsKR').onclick = playTTS;
  149. document.getElementById('wmettsEL').onclick = playTTS;
  150. document.getElementById('wmettsER').onclick = playTTS;
  151. document.getElementById('wmettsRND').onclick = playTTS;
  152. document.getElementById('wmettsUturn').onclick = playTTS;
  153. document.getElementById('wmettsGoing').onclick = playTTS;
  154. document.getElementById('minutes').onchange = function(){
  155. minutes_value = document.getElementById('minutes').value;
  156. };
  157. document.getElementById('round_exit').onchange = function(){
  158. round_exit_value = document.getElementById('round_exit').value;
  159. };
  160. }
  161. }
  162. else if ( !document.getElementById("WME-test-tts") && W.selectionManager.getSelectedFeatures().length > 0 && W.selectionManager.getSelectedFeatures()[0].model.type == "venue" )
  163. {
  164. var btnSection = document.createElement('div');
  165. btnSection.id = "WME-test-tts";
  166. var userTabs = document.getElementById('edit-panel');
  167. if (!(userTabs && getElementsByClassName('nav-tabs', userTabs)))
  168. return;
  169.  
  170. var navTabs = getElementsByClassName('nav-tabs', userTabs)[0];
  171. if (typeof navTabs !== "undefined")
  172. {
  173. if (!getElementsByClassName('tab-content', userTabs))
  174. return;
  175.  
  176. var tabContent = getElementsByClassName('tab-content', userTabs)[0];
  177.  
  178. if (typeof tabContent !== "undefined")
  179. {
  180. newtab = document.createElement('li');
  181. newtab.innerHTML = '<a href="#WME-test-tts" id="wmettstest" data-toggle="tab">TTS <i class="fa fa-lock" id="wmetts_lock"></i></a>';
  182. navTabs.appendChild(newtab);
  183.  
  184. var venue = W.selectionManager.getSelectedFeatures()[0].model.attributes.name;
  185. var poiName = 'ПОИ БЕЗ ИМЕНИ';
  186. if (W.selectionManager.getSelectedFeatures()[0].model.attributes.name !== "")
  187. {
  188. poiName = W.selectionManager.getSelectedFeatures()[0].model.attributes.name;
  189. }
  190.  
  191.  
  192. btnSection.innerHTML = '<div class="form-group">'+
  193. '<h4>TTS Test <sup>' + GM_info.script.version + '</sup>&nbsp;<sub><a href="https://greasyfork.org/en/scripts/23202-wme-tts-test" title="Link" target="_blank"><span class="fa fa-external-link"></span></a></sub></h4>' +
  194. '<div class="controls-container">' +
  195. '</br>' +
  196. '<button id="wmettsStreet" class="btn btn-default" title="'+poiName+'"><i class="fa fa-volume-up" style="font-size:16px;"></i>&nbsp;&nbsp;'+poiName+'</button>&nbsp;' +
  197. '</br></br>' +
  198. '</div></div>';
  199.  
  200. btnSection.className = "tab-pane";
  201. tabContent.appendChild(btnSection);
  202. }
  203. else
  204. btnSection.id='';
  205. }
  206. else
  207. btnSection.id='';
  208.  
  209. if(btnSection.id !== '')
  210. {
  211. if(document.getElementById('wmettsStreet')) document.getElementById('wmettsStreet').onclick = playTTS;
  212. if(document.getElementById('wmettsContinue')) document.getElementById('wmettsContinue').onclick = playTTS;
  213. if(document.getElementById('wmettsContStraight')) document.getElementById('wmettsContStraight').onclick = playTTS;
  214. if(document.getElementById('wmettsTL')) document.getElementById('wmettsTL').onclick = playTTS;
  215. if(document.getElementById('wmettsTR')) document.getElementById('wmettsTR').onclick = playTTS;
  216. if(document.getElementById('wmettsKL')) document.getElementById('wmettsKL').onclick = playTTS;
  217. if(document.getElementById('wmettsKR')) document.getElementById('wmettsKR').onclick = playTTS;
  218. if(document.getElementById('wmettsEL')) document.getElementById('wmettsEL').onclick = playTTS;
  219. if(document.getElementById('wmettsER')) document.getElementById('wmettsER').onclick = playTTS;
  220. if(document.getElementById('wmettsUturn')) document.getElementById('wmettsUturn').onclick = playTTS;
  221. if(document.getElementById('wmettsGoing')) document.getElementById('wmettsGoing').onclick = playTTS;
  222. if(document.getElementById('wmettsRND')) document.getElementById('wmettsRND').onclick = playTTS;
  223. }
  224. }
  225.  
  226. if(document.getElementById("WME-test-tts"))
  227. {
  228. if (W.selectionManager.getSelectedFeatures().length > 0)
  229. {
  230. var disabledButton=false;
  231. var model=W.selectionManager.getSelectedFeatures()[0].model;
  232.  
  233. if ((model.type !== 'segment' || !(model.getAddress().attributes.hasOwnProperty('street') && model.getAddress().attributes.street !== null && model.getAddress().attributes.street.name !== null)) && (model.type !== 'venue' || model.attributes.name === ""))
  234. disabledButton=true;
  235.  
  236. var lock=document.getElementById('wmetts_lock');
  237. if (lock)
  238. {
  239.  
  240. if (disabledButton)
  241. {
  242. lock.setAttribute('style','color:red;');
  243. lock.setAttribute('class', "fa fa-lock");
  244. }
  245. else
  246. {
  247. lock.setAttribute('style','color:green;');
  248. lock.setAttribute('class', "fa fa-unlock");
  249. }
  250. }
  251.  
  252. if(document.getElementById('wmettsStreet')) document.getElementById('wmettsStreet').disabled = disabledButton;
  253. if(document.getElementById('wmettsContinue')) document.getElementById('wmettsContinue').disabled = disabledButton;
  254. if(document.getElementById('wmettsContStraight')) document.getElementById('wmettsContStraight').disabled = disabledButton;
  255. if(document.getElementById('wmettsTL')) document.getElementById('wmettsTL').disabled = disabledButton;
  256. if(document.getElementById('wmettsTR')) document.getElementById('wmettsTR').disabled = disabledButton;
  257. if(document.getElementById('wmettsKL')) document.getElementById('wmettsKL').disabled = disabledButton;
  258. if(document.getElementById('wmettsKR')) document.getElementById('wmettsKR').disabled = disabledButton;
  259. if(document.getElementById('wmettsEL')) document.getElementById('wmettsEL').disabled = disabledButton;
  260. if(document.getElementById('wmettsER')) document.getElementById('wmettsER').disabled = disabledButton;
  261. if(document.getElementById('wmettsUturn')) document.getElementById('wmettsUturn').disabled = disabledButton;
  262. if(document.getElementById('wmettsGoing')) document.getElementById('wmettsGoing').disabled = disabledButton;
  263. if(document.getElementById('wmettsRND')) document.getElementById('wmettsRND').disabled = disabledButton;
  264. }
  265. }
  266. }
  267.  
  268. function playTTS()
  269. {
  270. var ttsName = '';
  271. if (W.selectionManager.getSelectedFeatures()[0].model.type === 'segment' )
  272. {
  273. if (W.selectionManager.getSelectedFeatures().length != 1)
  274. {
  275. alert('Выберите только один сегмент');
  276. return;
  277. }
  278.  
  279. var street = W.model.streets.get(W.selectionManager.getSelectedFeatures()[0].model.attributes.primaryStreetID);
  280. if (typeof street !== "undefined")
  281. {
  282. if (street.name === null)
  283. {
  284. alert('Безымянный сегмент');
  285. return;
  286. }
  287. else
  288. {
  289. ttsName = street.name;
  290. }
  291. }
  292. else
  293. {
  294. console.log('WME_TTS undefined street');
  295. return;
  296. }
  297. }
  298. else if (W.selectionManager.getSelectedFeatures()[0].model.type === 'venue')
  299. {
  300. ttsName = W.selectionManager.getSelectedFeatures()[0].model.attributes.name;
  301. }
  302.  
  303. var preText = '';
  304. switch (this.id)
  305. {
  306. case 'wmettsStreet':
  307. preText = ' ';
  308. break;
  309. case 'wmettsContinue':
  310. preText = 'продолжайте движение около ';
  311. var minutes;
  312. if (document.getElementById('minutes') !== null )
  313. minutes = minutes_value + ' мин. до ';
  314. else
  315. minutes = '20 мин. до ';
  316. ttsName = minutes + ttsName;
  317. break;
  318. case 'wmettsContStraight':
  319. preText = 'продолжайте движение прямо на ';
  320. break;
  321. case 'wmettsTL':
  322. preText = 'поверните налево на ';
  323. break;
  324. case 'wmettsTR':
  325. preText = 'поверните направо на ';
  326. break;
  327. case 'wmettsKL':
  328. preText = 'держитесь левее на ';
  329. break;
  330. case 'wmettsKR':
  331. preText = 'держитесь правее на ';
  332. break;
  333. case 'wmettsEL':
  334. preText = 'съезд слева на ';
  335. break;
  336. case 'wmettsER':
  337. preText = 'съезд справа на ';
  338. break;
  339. case 'wmettsUturn':
  340. preText = 'развернитесь на ';
  341. break;
  342. case 'wmettsGoing':
  343. preText = 'Поедем по ';
  344. break;
  345. case 'wmettsRND':
  346. var round_exit_text;
  347. switch (round_exit_value)
  348. {
  349. case '1':
  350. round_exit_text = 'первый';
  351. break;
  352. case '2':
  353. round_exit_text = 'второй';
  354. break;
  355. case '3':
  356. round_exit_text = 'третий';
  357. break;
  358. case '4':
  359. round_exit_text = 'четвёртый';
  360. break;
  361. case '5':
  362. round_exit_text = 'пятый';
  363. break;
  364. case '6':
  365. round_exit_text = 'шестой';
  366. break;
  367. case '7':
  368. round_exit_text = 'седьмой';
  369. break;
  370. default:
  371. round_exit_text = 'первый';
  372. }
  373. preText = 'на кольце '+round_exit_text+' съезд на ';
  374. break;
  375. default:
  376. alert("Unknown error");
  377. }
  378.  
  379. if (preText !== '')
  380. {
  381. new Audio('https://ttsgw.world.waze.com/TTSGateway/Text2SpeechServlet?text='+preText+ttsName+'&lang=ru-RU&lon=0&lat=0&version=6&protocol=2&sessionid=12345654321&content_type=audio%2Fmpeg&type=street&validate_data=positive&skipCache=true').play();
  382. }
  383. }
  384.  
  385. function getElementsByClassName(classname, node) {
  386. if(!node)
  387. node = document.getElementsByTagName("body")[0];
  388. var a = [];
  389. var re = new RegExp('\\b' + classname + '\\b');
  390. var els = node.getElementsByTagName("*");
  391. for (var i=0,j=els.length; i<j; i++)
  392. if (re.test(els[i].className)) a.push(els[i]);
  393. return a;
  394. }
  395.  
  396.  
  397. TTStest_bootstrap();
  398.  
  399.  
  400.  
  401. // ------------------------------
  402. function playTTSHand()
  403. {
  404. if ((typeof arguments[0]) === "object")
  405. {
  406. switch(arguments[0].type)
  407. {
  408. case 'click': // click button
  409. {
  410. var e=document.getElementById(arguments[0].id);
  411. if(e)
  412. e.click();
  413.  
  414. break;
  415. }
  416. }
  417. }
  418. }
  419.  
  420. function TTStest_initBindKey()
  421. {
  422. var Config =[
  423. {handler: 'wmettsStreet', title: 'Имя сегмента/ПОИ', func:playTTSHand, key:-1, arg:{type:'click',id:'wmettsStreet'}},
  424. {handler: 'wmettsContinue', title: 'Продолжайте движение', func:playTTSHand, key:-1, arg:{type:'click',id:'wmettsContinue'}},
  425. {handler: 'wmettsContStraight', title: 'Продолжайте движение', func:playTTSHand, key:-1, arg:{type:'click',id:'wmettsContStraight'}},
  426. {handler: 'wmettsTL', title: 'Поверните налево на', func:playTTSHand, key:-1, arg:{type:'click',id:'wmettsTL'}},
  427. {handler: 'wmettsTR', title: 'Поверните направо на', func:playTTSHand, key:-1, arg:{type:'click',id:'wmettsTR'}},
  428. {handler: 'wmettsKL', title: 'Держитесь левее на', func:playTTSHand, key:-1, arg:{type:'click',id:'wmettsKL'}},
  429. {handler: 'wmettsKR', title: 'Держитесь правее на', func:playTTSHand, key:-1, arg:{type:'click',id:'wmettsKR'}},
  430. {handler: 'wmettsEL', title: 'Съезд слева на', func:playTTSHand, key:-1, arg:{type:'click',id:'wmettsEL'}},
  431. {handler: 'wmettsER', title: 'Съезд справа на', func:playTTSHand, key:-1, arg:{type:'click',id:'wmettsER'}},
  432. {handler: 'wmettsUturn', title: 'Развернитесь на', func:playTTSHand, key:-1, arg:{type:'click',id:'wmettsUturn'}},
  433. {handler: 'wmettsGoing', title: 'Поедем по', func:playTTSHand, key:-1, arg:{type:'click',id:'wmettsGoing'}},
  434. {handler: 'wmettsRND', title: 'На кольце первый съезд на', func:playTTSHand, key:-1, arg:{type:'click',id:'wmettsRND'}},
  435. ];
  436.  
  437. for(var i=0; i < Config.length; ++i)
  438. {
  439. WMEKSRegisterKeyboardShortcut('WME TTS test', 'WME TTS test', Config[i].handler, Config[i].title, Config[i].func, Config[i].key, Config[i].arg);
  440. }
  441.  
  442. WMEKSLoadKeyboardShortcuts('WME TTS test');
  443.  
  444. window.addEventListener("beforeunload", function() {
  445. WMEKSSaveKeyboardShortcuts('WME TTS test');
  446. }, false);
  447. }
  448.  
  449. // from: https://greasyfork.org/ru/scripts/16071-wme-keyboard-shortcuts (modify)
  450. /*
  451. when adding shortcuts each shortcut will need a uniuque name
  452. the command to add links is WMERegisterKeyboardShortcut(ScriptName, ShortcutsHeader, NewShortcut, ShortcutDescription, FunctionToCall, ShortcutKeysObj) {
  453. ScriptName: This is the name of your script used to track all of your shortcuts on load and save.
  454. ScriptName: replace 'WMEAwesome' with your scripts name such as 'SomeOtherScript'
  455. ShortcutsHeader: this is the header that will show up in the keyboard editor
  456. NewShortcut: This is the name of the shortcut and needs to be uniuque from all of the other shortcuts, from other scripts, and WME
  457. ShortcutDescription: This wil show up as the text next to your shortcut
  458. FunctionToCall: this is the name of your function that will be called when the keyboard shortcut is presses
  459. ShortcutKeysObj: the is the object representing the keys watched set this to '-1' to let the users specify their own shortcuts.
  460. ShortcutKeysObj: The alt, shift, and ctrl keys are A=alt, S=shift, C=ctrl. for short cut to use "alt shift ctrl and l" the object would be 'ASC+l'
  461. */
  462. function WMEKSRegisterKeyboardShortcut(e,r,t,a,o,s,c){try{I18n.translations[I18n.locale].keyboard_shortcuts.groups[e].members.length}catch(n){W.accelerators.Groups[e]=[],W.accelerators.Groups[e].members=[],I18n.translations[I18n.locale].keyboard_shortcuts.groups[e]=[],I18n.translations[I18n.locale].keyboard_shortcuts.groups[e].description=r,I18n.translations[I18n.locale].keyboard_shortcuts.groups[e].members=[]}if(o&&"function"==typeof o){I18n.translations[I18n.locale].keyboard_shortcuts.groups[e].members[t]=a,W.accelerators.addAction(t,{group:e});var l="-1",i={};i[l]=t,W.accelerators._registerShortcuts(i),null!==s&&(i={},i[s]=t,W.accelerators._registerShortcuts(i)),W.accelerators.events.register(t,null,function(){o(c)})}else alert("The function "+o+" has not been declared")}function WMEKSLoadKeyboardShortcuts(e){if(localStorage[e+"KBS"])for(var r=JSON.parse(localStorage[e+"KBS"]),t=0;t<r.length;t++)W.accelerators._registerShortcuts(r[t])}function WMEKSSaveKeyboardShortcuts(e){var r=[];for(var t in W.accelerators.Actions){var a="";if(W.accelerators.Actions[t].group==e){W.accelerators.Actions[t].shortcut?(W.accelerators.Actions[t].shortcut.altKey===!0&&(a+="A"),W.accelerators.Actions[t].shortcut.shiftKey===!0&&(a+="S"),W.accelerators.Actions[t].shortcut.ctrlKey===!0&&(a+="C"),""!==a&&(a+="+"),W.accelerators.Actions[t].shortcut.keyCode&&(a+=W.accelerators.Actions[t].shortcut.keyCode)):a="-1";var o={};o[a]=W.accelerators.Actions[t].id,r[r.length]=o}}localStorage[e+"KBS"]=JSON.stringify(r)}
  463. /* ********************************************************** */
  464.  
  465. })();