init.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  1. // Replace .no-js class with .js
  2. document.documentElement.className = document.documentElement.className.replace('no-js', 'js');
  3. $(document).ready(function () {
  4. if ($('.body-login')[0]) {
  5. $('input').first().focus();
  6. }
  7. $('.submenu-select-dropdown').each(function () {
  8. $(this).wrap("<span class='submenu-select-wrapper'></span>");
  9. $(this).after("<span class='holder'></span>");
  10. });
  11. $('.submenu-select-dropdown')
  12. .change(function () {
  13. var selectedOption = $(this).find(':selected').text();
  14. $(this).next('.holder').text(selectedOption);
  15. })
  16. .trigger('change');
  17. $('.js-to-top').on('click', function () {
  18. $('html, body').animate({ scrollTop: 0 }, 'normal');
  19. });
  20. $('.button').on('click', function (evt) {
  21. var action = $(this).data('action');
  22. var id = $(this).data('id');
  23. if (action == 'submit' && document.getElementById(id)) {
  24. evt.preventDefault();
  25. $(document.getElementById(id)).submit();
  26. }
  27. });
  28. $(window).scroll(function () {
  29. set_sticky_class();
  30. });
  31. $('.toolbar-sorting-toggle').click(function (evt) {
  32. evt.preventDefault();
  33. $('.toolbar-sorting-menu').toggleClass('u-hidden');
  34. });
  35. // SEARCH BOX
  36. $('.toolbar-search .js-search-input').hover(
  37. function () {
  38. clearTimeout(VE.tmp.search_display_interval);
  39. clearTimeout(VE.tmp.search_hover_interval);
  40. VE.tmp.search_display_interval = setTimeout(function () {
  41. $('.js-search-input').addClass('activated');
  42. }, 150);
  43. },
  44. function () {
  45. clearTimeout(VE.tmp.search_display_interval);
  46. clearTimeout(VE.tmp.search_hover_interval);
  47. VE.tmp.search_hover_interval = setTimeout(function () {
  48. if (!VE.tmp.search_activated && !$('.js-search-input').val().length) {
  49. $('.js-search-input').removeClass('activated');
  50. }
  51. }, 600);
  52. }
  53. );
  54. $('.js-search-input').focus(function () {
  55. VE.tmp.search_activated = 1;
  56. clearTimeout(VE.tmp.search_hover_interval);
  57. });
  58. $('.js-search-input').blur(function () {
  59. VE.tmp.search_activated = 0;
  60. clearTimeout(VE.tmp.search_hover_interval);
  61. VE.tmp.search_hover_interval = setTimeout(function () {
  62. if (!$('.js-search-input').val().length) {
  63. $('.js-search-input').removeClass('activated');
  64. }
  65. }, 600);
  66. });
  67. // TIMER
  68. if ($('.movement.left').length) {
  69. VE.helpers.refresh_timer.right = $('.movement.right');
  70. VE.helpers.refresh_timer.left = $('.movement.left');
  71. VE.helpers.refresh_timer.start();
  72. $('.pause').click(function () {
  73. VE.helpers.refresh_timer.stop();
  74. $('.pause').addClass('u-hidden');
  75. $('.play').removeClass('u-hidden');
  76. $('.refresh-timer').addClass('paused');
  77. });
  78. $('.play').click(function () {
  79. VE.helpers.refresh_timer.start();
  80. $('.pause').removeClass('u-hidden');
  81. $('.play').addClass('u-hidden');
  82. $('.refresh-timer').removeClass('paused');
  83. });
  84. }
  85. // SORTING
  86. $('#vstobjects input, #vstobjects select, #vstobjects textarea').change(function () {
  87. VE.tmp.form_changed = 1;
  88. });
  89. $('.toolbar-sorting-menu span').click(function () {
  90. $('.toolbar-sorting-menu').toggleClass('u-hidden');
  91. if ($(this).hasClass('active')) return;
  92. $('.toolbar-sorting-menu span').removeClass('active');
  93. $(this).addClass('active');
  94. VE.tmp.sort_par = $(this).parent('li').attr('entity');
  95. VE.tmp.sort_as_int = $(this).parent('li').attr('sort_as_int');
  96. VE.tmp.sort_direction = $(this).hasClass('up') * 1 || -1;
  97. $('.toolbar-sorting-toggle b').html($(this).parent('li').find('.name').html());
  98. $('.toolbar-sorting-toggle .fas').removeClass('fa-arrow-up-a-z fa-arrow-down-a-z');
  99. $(this).hasClass('up')
  100. ? $('.toolbar-sorting-toggle .fas').addClass('fa-arrow-up-a-z')
  101. : $('.toolbar-sorting-toggle .fas').addClass('fa-arrow-down-a-z');
  102. $('.units .l-unit')
  103. .sort(function (a, b) {
  104. if (VE.tmp.sort_as_int)
  105. return parseInt($(a).attr(VE.tmp.sort_par)) >= parseInt($(b).attr(VE.tmp.sort_par))
  106. ? VE.tmp.sort_direction
  107. : VE.tmp.sort_direction * -1;
  108. else
  109. return $(a).attr(VE.tmp.sort_par) <= $(b).attr(VE.tmp.sort_par)
  110. ? VE.tmp.sort_direction
  111. : VE.tmp.sort_direction * -1;
  112. })
  113. .appendTo('.units');
  114. });
  115. $('#objects').submit(function (e) {
  116. if (!e.originalEvent) {
  117. return;
  118. }
  119. e.preventDefault();
  120. $('.ch-toggle').each(function () {
  121. if ($(this).prop('checked')) {
  122. key = this.name;
  123. div = $('<input type="hidden" name="' + key + '" value="' + this.value + '">');
  124. $('#objects').append(div);
  125. }
  126. });
  127. $('#objects').submit();
  128. return false;
  129. });
  130. // Shortcuts
  131. shortcut.add(
  132. 'Ctrl+Enter',
  133. function () {
  134. $('form#vstobjects').submit();
  135. },
  136. {
  137. type: 'keydown',
  138. propagate: false,
  139. disable_in_input: false,
  140. target: document,
  141. }
  142. );
  143. shortcut.add(
  144. 'Ctrl+Backspace',
  145. function () {
  146. var redirect = $('a.button#btn-back').attr('href');
  147. if (VE.tmp.form_changed && redirect) {
  148. VE.helpers.createConfirmationDialog($('.js-confirm-dialog-redirect'), '', redirect);
  149. } else if ($('form#vstobjects .button.cancel')[0]) {
  150. location.href = $('form#vstobjects input.cancel')
  151. .attr('onclick')
  152. .replace("location.href='", '')
  153. .replace("'", '');
  154. } else if (redirect) {
  155. location.href = redirect;
  156. }
  157. },
  158. {
  159. type: 'keydown',
  160. propagate: false,
  161. disable_in_input: false,
  162. target: document,
  163. }
  164. );
  165. shortcut.add(
  166. 'f',
  167. function () {
  168. $('.js-search-input').addClass('activated').focus();
  169. },
  170. {
  171. type: 'keydown',
  172. propagate: false,
  173. disable_in_input: true,
  174. target: document,
  175. }
  176. );
  177. $(window).on('keypress', function (evt) {
  178. var tag = evt.target.tagName.toLowerCase();
  179. if (evt.charCode == 97 && tag != 'input' && tag != 'textarea' && tag != 'selectbox') {
  180. evt.preventDefault();
  181. if (!evt.ctrlKey && !evt.shiftKey) {
  182. if ($('.button#btn-create').length) {
  183. location.href = $('.button#btn-create').attr('href');
  184. }
  185. } else {
  186. if ($('.l-unit .ch-toggle:eq(0)').prop('checked')) {
  187. $('.l-unit').removeClass('selected');
  188. $('.l-unit .ch-toggle').prop('checked', false);
  189. } else {
  190. $('.l-unit').addClass('selected');
  191. $('.l-unit .ch-toggle').prop('checked', true);
  192. }
  193. }
  194. }
  195. });
  196. shortcut.add(
  197. '1',
  198. function () {
  199. var target = $('.main-menu .main-menu-item:nth-of-type(1) a');
  200. if (target.length != 1) {
  201. return;
  202. }
  203. if (VE.tmp.form_changed) {
  204. VE.helpers.createConfirmationDialog(
  205. $('.js-confirm-dialog-redirect'),
  206. '',
  207. target.attr('href')
  208. );
  209. } else {
  210. location.href = target.attr('href');
  211. }
  212. },
  213. {
  214. type: 'keydown',
  215. propagate: false,
  216. disable_in_input: true,
  217. target: document,
  218. }
  219. );
  220. shortcut.add(
  221. '2',
  222. function () {
  223. var target = $('.main-menu .main-menu-item:nth-of-type(2) a');
  224. if (target.length != 1) {
  225. return;
  226. }
  227. if (VE.tmp.form_changed) {
  228. VE.helpers.createConfirmationDialog(
  229. $('.js-confirm-dialog-redirect'),
  230. '',
  231. target.attr('href')
  232. );
  233. } else {
  234. location.href = target.attr('href');
  235. }
  236. },
  237. {
  238. type: 'keydown',
  239. propagate: false,
  240. disable_in_input: true,
  241. target: document,
  242. }
  243. );
  244. shortcut.add(
  245. '3',
  246. function () {
  247. var target = $('.main-menu .main-menu-item:nth-of-type(3) a');
  248. if (target.length != 1) {
  249. return;
  250. }
  251. if (VE.tmp.form_changed) {
  252. VE.helpers.createConfirmationDialog(
  253. $('.js-confirm-dialog-redirect'),
  254. '',
  255. target.attr('href')
  256. );
  257. } else {
  258. location.href = target.attr('href');
  259. }
  260. },
  261. {
  262. type: 'keydown',
  263. propagate: false,
  264. disable_in_input: true,
  265. target: document,
  266. }
  267. );
  268. shortcut.add(
  269. '4',
  270. function () {
  271. var target = $('.main-menu .main-menu-item:nth-of-type(4) a');
  272. if (target.length != 1) {
  273. return;
  274. }
  275. if (VE.tmp.form_changed) {
  276. VE.helpers.createConfirmationDialog(
  277. $('.js-confirm-dialog-redirect'),
  278. '',
  279. target.attr('href')
  280. );
  281. } else {
  282. location.href = target.attr('href');
  283. }
  284. },
  285. {
  286. type: 'keydown',
  287. propagate: false,
  288. disable_in_input: true,
  289. target: document,
  290. }
  291. );
  292. shortcut.add(
  293. '5',
  294. function () {
  295. var target = $('.main-menu .main-menu-item:nth-of-type(5) a');
  296. if (target.length != 1) {
  297. return;
  298. }
  299. if (VE.tmp.form_changed) {
  300. VE.helpers.createConfirmationDialog(
  301. $('.js-confirm-dialog-redirect'),
  302. '',
  303. target.attr('href')
  304. );
  305. } else {
  306. location.href = target.attr('href');
  307. }
  308. },
  309. {
  310. type: 'keydown',
  311. propagate: false,
  312. disable_in_input: true,
  313. target: document,
  314. }
  315. );
  316. shortcut.add(
  317. '6',
  318. function () {
  319. var target = $('.main-menu .main-menu-item:nth-of-type(6) a');
  320. if (target.length != 1) {
  321. return;
  322. }
  323. if (VE.tmp.form_changed) {
  324. VE.helpers.createConfirmationDialog(
  325. $('.js-confirm-dialog-redirect'),
  326. '',
  327. target.attr('href')
  328. );
  329. } else {
  330. location.href = target.attr('href');
  331. }
  332. },
  333. {
  334. type: 'keydown',
  335. propagate: false,
  336. disable_in_input: true,
  337. target: document,
  338. }
  339. );
  340. shortcut.add(
  341. '7',
  342. function () {
  343. var target = $('.main-menu .main-menu-item:nth-of-type(7) a');
  344. if (target.length != 1) {
  345. return;
  346. }
  347. if (VE.tmp.form_changed) {
  348. VE.helpers.createConfirmationDialog(
  349. $('.js-confirm-dialog-redirect'),
  350. '',
  351. target.attr('href')
  352. );
  353. } else {
  354. location.href = target.attr('href');
  355. }
  356. },
  357. {
  358. type: 'keydown',
  359. propagate: false,
  360. disable_in_input: true,
  361. target: document,
  362. }
  363. );
  364. shortcut.add(
  365. 'h',
  366. function () {
  367. var shortcutsDialog = document.querySelector('.shortcuts');
  368. if (shortcutsDialog.open) {
  369. shortcutsDialog.close();
  370. } else {
  371. shortcutsDialog.showModal();
  372. }
  373. },
  374. {
  375. type: 'keydown',
  376. propagate: false,
  377. disable_in_input: true,
  378. target: document,
  379. }
  380. );
  381. shortcut.add(
  382. 'Esc',
  383. function () {
  384. var shortcutsDialog = document.querySelector('.shortcuts');
  385. if (shortcutsDialog.open) {
  386. shortcutsDialog.close();
  387. }
  388. $('input, checkbox, textarea, select').blur();
  389. },
  390. {
  391. type: 'keydown',
  392. propagate: false,
  393. disable_in_input: false,
  394. target: document,
  395. }
  396. );
  397. shortcut.add(
  398. 'Left',
  399. function () {
  400. VE.navigation.move_focus_left();
  401. },
  402. {
  403. type: 'keydown',
  404. propagate: false,
  405. disable_in_input: true,
  406. target: document,
  407. }
  408. );
  409. shortcut.add(
  410. 'Right',
  411. function () {
  412. VE.navigation.move_focus_right();
  413. },
  414. {
  415. type: 'keydown',
  416. propagate: false,
  417. disable_in_input: true,
  418. target: document,
  419. }
  420. );
  421. shortcut.add(
  422. 'down',
  423. function () {
  424. VE.navigation.move_focus_down();
  425. },
  426. {
  427. type: 'keydown',
  428. propagate: false,
  429. disable_in_input: true,
  430. target: document,
  431. }
  432. );
  433. shortcut.add(
  434. 'up',
  435. function () {
  436. VE.navigation.move_focus_up();
  437. },
  438. {
  439. type: 'keydown',
  440. propagate: false,
  441. disable_in_input: true,
  442. target: document,
  443. }
  444. );
  445. shortcut.add(
  446. 'l',
  447. function () {
  448. var elm = $('.units.active .l-unit.focus .shortcut-l');
  449. if (elm.length) {
  450. VE.navigation.shortcut(elm);
  451. }
  452. },
  453. {
  454. type: 'keydown',
  455. propagate: false,
  456. disable_in_input: true,
  457. target: document,
  458. }
  459. );
  460. shortcut.add(
  461. 's',
  462. function () {
  463. var elm = $('.units.active .l-unit.focus .shortcut-s');
  464. if (elm.length) {
  465. VE.navigation.shortcut(elm);
  466. }
  467. },
  468. {
  469. type: 'keydown',
  470. propagate: false,
  471. disable_in_input: true,
  472. target: document,
  473. }
  474. );
  475. shortcut.add(
  476. 'w',
  477. function () {
  478. var elm = $('.units.active .l-unit.focus .shortcut-w');
  479. if (elm.length) {
  480. VE.navigation.shortcut(elm);
  481. }
  482. },
  483. {
  484. type: 'keydown',
  485. propagate: false,
  486. disable_in_input: true,
  487. target: document,
  488. }
  489. );
  490. shortcut.add(
  491. 'd',
  492. function () {
  493. var elm = $('.units.active .l-unit.focus .shortcut-d');
  494. if (elm.length) {
  495. VE.navigation.shortcut(elm);
  496. }
  497. },
  498. {
  499. type: 'keydown',
  500. propagate: false,
  501. disable_in_input: true,
  502. target: document,
  503. }
  504. );
  505. shortcut.add(
  506. 'r',
  507. function () {
  508. var elm = $('.units.active .l-unit.focus .shortcut-r');
  509. if (elm.length) {
  510. VE.navigation.shortcut(elm);
  511. }
  512. },
  513. {
  514. type: 'keydown',
  515. propagate: false,
  516. disable_in_input: true,
  517. target: document,
  518. }
  519. );
  520. shortcut.add(
  521. 'n',
  522. function () {
  523. var elm = $('.units.active .l-unit.focus .shortcut-n');
  524. if (elm.length) {
  525. VE.navigation.shortcut(elm);
  526. }
  527. },
  528. {
  529. type: 'keydown',
  530. propagate: false,
  531. disable_in_input: true,
  532. target: document,
  533. }
  534. );
  535. shortcut.add(
  536. 'u',
  537. function () {
  538. var elm = $('.units.active .l-unit.focus .shortcut-u');
  539. if (elm.length) {
  540. VE.navigation.shortcut(elm);
  541. }
  542. },
  543. {
  544. type: 'keydown',
  545. propagate: false,
  546. disable_in_input: true,
  547. target: document,
  548. }
  549. );
  550. shortcut.add(
  551. 'Delete',
  552. function () {
  553. var elm = $('.units.active .l-unit.focus .shortcut-delete');
  554. if (elm.length) {
  555. VE.navigation.shortcut(elm);
  556. }
  557. },
  558. {
  559. type: 'keydown',
  560. propagate: false,
  561. disable_in_input: true,
  562. target: document,
  563. }
  564. );
  565. shortcut.add(
  566. 'Enter',
  567. function (evt) {
  568. if (evt.target.tagName == 'INPUT' && evt.target.form.id == 'vstobjects') {
  569. $('form#vstobjects').submit();
  570. }
  571. if (VE.tmp.form_changed) {
  572. if (!$('.ui-dialog').is(':visible')) {
  573. VE.helpers.createConfirmationDialog(
  574. $('.js-confirm-dialog-redirect')[0],
  575. '',
  576. $(VE.navigation.state.menu_selector + '.focus a').attr('href')
  577. );
  578. } else {
  579. // if dialog is opened - submitting confirm box by "enter" shortcut
  580. $('.ui-dialog button.submit').click();
  581. }
  582. } else {
  583. if (!$('.ui-dialog').is(':visible')) {
  584. var elm = $('.units.active .l-unit.focus .shortcut-enter');
  585. if (elm.length) {
  586. VE.navigation.shortcut(elm);
  587. } else {
  588. VE.navigation.enter_focused();
  589. }
  590. } else {
  591. // if dialog is opened - submitting confirm box by "enter" shortcut
  592. $('.ui-dialog button.submit').click();
  593. }
  594. }
  595. },
  596. {
  597. type: 'keydown',
  598. propagate: true,
  599. disable_in_input: false,
  600. target: document,
  601. }
  602. );
  603. $('.shortcuts-close').on('click', function () {
  604. var shortcutsDialog = document.querySelector('.shortcuts');
  605. if (shortcutsDialog.open) {
  606. shortcutsDialog.close();
  607. }
  608. });
  609. $('.js-shortcuts').on('click', function () {
  610. event.preventDefault();
  611. var shortcutsDialog = document.querySelector('.shortcuts');
  612. if (shortcutsDialog.open) {
  613. shortcutsDialog.close();
  614. } else {
  615. shortcutsDialog.showModal();
  616. }
  617. });
  618. $(document).click(function (evt) {
  619. //close notification popup
  620. if (
  621. !$(evt.target).hasClass('js-notifications') &&
  622. $(evt.target).parents('.top-bar-notifications-list').length == 0
  623. ) {
  624. $('.top-bar-notifications-list').addClass('u-hidden');
  625. $('.js-notifications').removeClass('active');
  626. }
  627. });
  628. // focusing on the first input at form
  629. if (location.href.indexOf('lead=') == -1 && !$('.ui-dialog').is(':visible')) {
  630. $('#vstobjects .form-control:not([disabled]), #vstobjects .form-select:not([disabled])')
  631. .first()
  632. .focus();
  633. }
  634. $('.js-notifications').click(function (evt) {
  635. if (!$('.js-notifications').hasClass('active')) {
  636. VE.notifications.get_list();
  637. $('.js-notifications').addClass('active');
  638. } else {
  639. $('.top-bar-notifications-list').addClass('u-hidden');
  640. $('.js-notifications').removeClass('active');
  641. }
  642. });
  643. $('.js-toggle-top-bar-menu').click(function (evt) {
  644. $(this).siblings('.top-bar-menu-list').toggle();
  645. });
  646. $('.js-toggle-main-menu').click(function (evt) {
  647. var $mainMenuList = $('.main-menu-list');
  648. var $toggleLabel = $('.main-menu-toggle-label');
  649. var openLabel = $toggleLabel.data('open-label');
  650. var closeLabel = $toggleLabel.data('close-label');
  651. $mainMenuList.slideToggle(200, function () {
  652. if ($mainMenuList.is(':visible')) {
  653. $toggleLabel.text(closeLabel);
  654. } else {
  655. $toggleLabel.text(openLabel);
  656. }
  657. });
  658. });
  659. $('.button.cancel').attr('title', 'ctrl+Backspace');
  660. VE.core.register();
  661. if (location.href.search(/list/) != -1) {
  662. var shift_select_ref = $('body').finderSelect({
  663. children: '.l-unit',
  664. onFinish: function () {
  665. // do nothing
  666. },
  667. toggleAllHook: function () {
  668. if ($('.l-unit').length == $('.ch-toggle:checked').length) {
  669. $('.l-unit.selected').removeClass('selected');
  670. $('.ch-toggle').prop('checked', false);
  671. $('#toggle-all').prop('checked', false);
  672. } else {
  673. $('.ch-toggle').prop('checked', true);
  674. $('#toggle-all').prop('checked', true);
  675. }
  676. },
  677. });
  678. $('table').on('mousedown', 'td', function (e) {
  679. if (e.ctrlKey) {
  680. e.preventDefault();
  681. }
  682. });
  683. }
  684. //
  685. $('form#objects').on('submit', function (evt) {
  686. $('.l-unit').find('.ch-toggle').prop('checked', false);
  687. $('.l-unit.selected').find('.ch-toggle').prop('checked', true);
  688. });
  689. // todo: maybe give the save button id?
  690. $('.button[data-id=vstobjects][data-action=submit]').on('click', function (ev) {
  691. let loadingAnimationEle = document.createElement('div');
  692. loadingAnimationEle.className = 'spinner';
  693. loadingAnimationEle.innerHTML =
  694. '<div class="spinner-inner"></div><div class="spinner-mask"></div> <div class="spinner-mask-two"></div>';
  695. // this both gives an indication that we've clicked and is loading, also prevents double-clicking/clicking-on-something-else while loading.
  696. $('.button[data-id=vstobjects][data-action=submit]').replaceWith(loadingAnimationEle);
  697. $('.button').replaceWith('');
  698. // workaround a render bug on Safari (loading icon doesn't render without this)
  699. ev.preventDefault();
  700. $('#vstobjects').submit();
  701. });
  702. });
  703. /**
  704. * generates a random string
  705. * using a cryptographically secure rng,
  706. * and ensuring it contains at least 1 lowercase, 1 uppercase, and 1 number.
  707. *
  708. * @param int length
  709. * @throws Error if length is too small to create a "sufficiently secure" string
  710. * @returns string
  711. */
  712. function randomString2(length = 16) {
  713. var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
  714. var secure_rng = function (min, max) {
  715. if (min < 0 || min > 0xffff) {
  716. throw new Error(
  717. 'minimum supported number is 0, this generator can only make numbers between 0-65535 inclusive.'
  718. );
  719. }
  720. if (max > 0xffff || max < 0) {
  721. throw new Error(
  722. 'max supported number is 65535, this generator can only make numbers between 0-65535 inclusive.'
  723. );
  724. }
  725. if (min > max) {
  726. throw new Error('dude min>max wtf');
  727. }
  728. // micro-optimization
  729. let randArr = max > 255 ? new Uint16Array(1) : new Uint8Array(1);
  730. let ret;
  731. let attempts = 0;
  732. for (;;) {
  733. crypto.getRandomValues(randArr);
  734. ret = randArr[0];
  735. if (ret >= min && ret <= max) {
  736. return ret;
  737. }
  738. ++attempts;
  739. if (attempts > 1000000) {
  740. // should basically never happen with max 0xFFFF/Uint16Array.
  741. throw new Error('tried a million times, something is wrong');
  742. }
  743. }
  744. };
  745. let attempts = 0;
  746. let minimumStrengthRegex = new RegExp(
  747. /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*\d)[a-zA-Z\d]{8,}$/
  748. );
  749. let randmax = chars.length - 1;
  750. for (;;) {
  751. let ret = '';
  752. for (let i = 0; i < length; ++i) {
  753. ret += chars[secure_rng(0, randmax)];
  754. }
  755. if (minimumStrengthRegex.test(ret)) {
  756. return ret;
  757. }
  758. ++attempts;
  759. if (attempts > 1000000) {
  760. throw new Error('tried a million times, something is wrong');
  761. }
  762. }
  763. }