init.js 18 KB

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