app.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. (() => {
  2. // application/scripts/height_equaler.js
  3. var height_equaler = class {
  4. #to;
  5. #from;
  6. constructor(from, to) {
  7. this.#from = from;
  8. this.#to = to;
  9. this.#set_styles();
  10. new ResizeObserver(() => {
  11. this.#update();
  12. }).observe(from);
  13. setTimeout(() => {
  14. this.#update();
  15. }, 100);
  16. }
  17. get height() {
  18. return this.#from.offsetHeight;
  19. }
  20. #set_styles() {
  21. this.#to.style.height = "0px";
  22. this.#to.style.transition = "height 0.5s";
  23. }
  24. #update() {
  25. this.#to.style.height = this.height + "px";
  26. }
  27. };
  28. // application/scripts/product.js
  29. var product = class {
  30. name;
  31. description;
  32. author;
  33. image;
  34. stock_count;
  35. barcode;
  36. constructor(target) {
  37. this.name = null;
  38. this.description = null;
  39. this.author = null;
  40. this.image = null;
  41. this.stock_count = null;
  42. this.barcode = null;
  43. if ("name" in target) this.name = target["name"];
  44. if ("description" in target) this.description = target["description"];
  45. if ("author" in target) this.author = target["author"];
  46. if ("image" in target) this.image = target["image"];
  47. if ("stock_count" in target) this.stock_count = target["stock_count"];
  48. if ("barcode" in target) this.barcode = target["barcode"];
  49. }
  50. get dump() {
  51. return {
  52. "name": this.name,
  53. "description": this.description,
  54. "author": this.author,
  55. "image": this.image,
  56. "stock_count": this.stock_count,
  57. "barcode": this.barcode
  58. };
  59. }
  60. get ready() {
  61. if (this.name === null || this.description === null) return false;
  62. if (this.author === null || this.image === null) return false;
  63. if (this.stock_count === null || this.barcode === null) return false;
  64. return true;
  65. }
  66. };
  67. // application/scripts/products_loader.js
  68. var products_loader = class _products_loader {
  69. static async all() {
  70. const request = await fetch("/products/");
  71. const response = await request.json();
  72. return _products_loader.#response_to_collection(response);
  73. }
  74. static #response_to_collection(response) {
  75. const result = new Array();
  76. if (response.result !== "success") {
  77. return result;
  78. }
  79. response.collection.forEach((serialized) => {
  80. result.push(new product(serialized));
  81. });
  82. return result;
  83. }
  84. static async search_name(name) {
  85. return await _products_loader.#search(
  86. "/product/search/name",
  87. name
  88. );
  89. }
  90. static async search_author(author) {
  91. return await _products_loader.#search(
  92. "/product/search/author",
  93. author
  94. );
  95. }
  96. static async #search(path, parameter) {
  97. const coded = encodeURI(parameter);
  98. const request = await fetch(path + "/" + coded);
  99. const response = await request.json();
  100. return _products_loader.#response_to_collection(response);
  101. }
  102. };
  103. // application/scripts/fullscreen.js
  104. var fullscreen = class {
  105. #node;
  106. constructor() {
  107. this.#node = null;
  108. }
  109. get visible() {
  110. return this.#node !== null;
  111. }
  112. _build_node() {
  113. throw new TypeError("This is virtual method!");
  114. }
  115. get #opacity() {
  116. if (!this.visible) {
  117. throw new TypeError("Can not change opacity of not existed.");
  118. }
  119. return Number(this.#node.style.opacity);
  120. }
  121. get_query(selector) {
  122. if (!this.visible) {
  123. throw new TypeError("Can not get item from not visible.");
  124. }
  125. return this.#node.querySelector(selector);
  126. }
  127. get #close() {
  128. const close_button = document.createElement("button");
  129. close_button.classList.add("material-icons");
  130. close_button.classList.add("close");
  131. close_button.innerText = "close";
  132. close_button.addEventListener("click", () => {
  133. this.hide();
  134. });
  135. return close_button;
  136. }
  137. #prepare() {
  138. if (!this.visible) {
  139. throw new TypeError("Can not prepare not existed.");
  140. }
  141. this.#node.style.transition = "opacity 0.5s";
  142. this.#node.classList.add("fullscreen-viewer");
  143. this.#node.appendChild(this.#close);
  144. }
  145. set #opacity(target) {
  146. if (!this.visible) {
  147. throw new TypeError("Can not change opacity of not existed.");
  148. }
  149. this.#node.style.opacity = String(target);
  150. }
  151. hide() {
  152. if (!this.visible) {
  153. return;
  154. }
  155. this.#opacity = 0;
  156. setTimeout(() => {
  157. if (!this.visible) {
  158. return;
  159. }
  160. this.#node.remove();
  161. this.#node = null;
  162. }, 500);
  163. }
  164. show() {
  165. if (this.visible) {
  166. return;
  167. }
  168. this.#node = this._build_node();
  169. this.#prepare();
  170. this.#opacity = 0;
  171. document.querySelector("body").appendChild(this.#node);
  172. setTimeout(() => {
  173. this.#opacity = 1;
  174. }, 100);
  175. }
  176. };
  177. // application/scripts/product_fullscreen.js
  178. var product_fullscreen = class extends fullscreen {
  179. #target;
  180. constructor(target) {
  181. super();
  182. this.#target = target;
  183. }
  184. get target() {
  185. return this.#target;
  186. }
  187. _build_node() {
  188. const container = document.createElement("div");
  189. container.classList.add("product-fullscreen-viewer");
  190. const image = document.createElement("div");
  191. image.style.backgroundImage = 'url("' + this.target.image + '")';
  192. image.classList.add("image");
  193. container.appendChild(image);
  194. const title = document.createElement("div");
  195. title.classList.add("title");
  196. container.appendChild(title);
  197. const title_content = document.createElement("h1");
  198. title_content.innerText = this.target.name;
  199. title.appendChild(title_content);
  200. const bottom = document.createElement("div");
  201. bottom.classList.add("bottom-side");
  202. container.appendChild(bottom);
  203. const bottom_header = document.createElement("div");
  204. bottom_header.classList.add("bottom-header");
  205. bottom.appendChild(bottom_header);
  206. const barcode_icon = document.createElement("span");
  207. barcode_icon.classList.add("material-icons");
  208. barcode_icon.innerText = "qr_code_scanner";
  209. const barcode_content = document.createElement("span");
  210. barcode_content.innerText = this.target.barcode;
  211. barcode_content.classList.add("numbers");
  212. const barcode = document.createElement("p");
  213. barcode.appendChild(barcode_icon);
  214. barcode.appendChild(barcode_content);
  215. bottom_header.appendChild(barcode);
  216. const author_icon = document.createElement("span");
  217. author_icon.classList.add("material-icons");
  218. author_icon.innerText = "attribution";
  219. const author_content = document.createElement("span");
  220. author_content.innerText = this.target.author;
  221. const author = document.createElement("p");
  222. author.appendChild(author_icon);
  223. author.appendChild(author_content);
  224. bottom_header.appendChild(author);
  225. const description = document.createElement("div");
  226. description.classList.add("description");
  227. bottom.appendChild(description);
  228. const description_content = document.createElement("p");
  229. description_content.innerText = this.target.description;
  230. description.appendChild(description_content);
  231. return container;
  232. }
  233. };
  234. // application/scripts/user.js
  235. var user = class {
  236. #nick;
  237. #apikey;
  238. constructor(nick, apikey) {
  239. this.#nick = nick;
  240. this.#apikey = apikey;
  241. }
  242. get nick() {
  243. return this.#nick;
  244. }
  245. get apikey() {
  246. return this.#apikey;
  247. }
  248. };
  249. // application/scripts/login_manager.js
  250. var login_manager = class {
  251. get apikey() {
  252. return localStorage.getItem("apikey");
  253. }
  254. get logged_in() {
  255. return localStorage.getItem("apikey") !== null;
  256. }
  257. #create_request(data) {
  258. return {
  259. method: "POST",
  260. body: JSON.stringify(data),
  261. headers: {
  262. "Content-Type": "application/json"
  263. }
  264. };
  265. }
  266. async get_user() {
  267. if (!this.logged_in) {
  268. return null;
  269. }
  270. const request_data = this.#create_request({
  271. apikey: this.apikey
  272. });
  273. const request = await fetch("/user", request_data);
  274. const response = await request.json();
  275. if (response.result !== "success") {
  276. return null;
  277. }
  278. return new user(
  279. response.nick,
  280. response.apikey
  281. );
  282. }
  283. async login(nick, password) {
  284. const request_data = this.#create_request({
  285. nick,
  286. password
  287. });
  288. const request = await fetch("/user/login", request_data);
  289. const response = await request.json();
  290. if (response.result !== "success") {
  291. return false;
  292. }
  293. localStorage.setItem("apikey", response.apikey);
  294. return true;
  295. }
  296. logout() {
  297. localStorage.removeItem("apikey");
  298. }
  299. };
  300. // application/scripts/product_container.js
  301. var product_container = class {
  302. #target;
  303. #node;
  304. #login;
  305. constructor(target) {
  306. this.#target = new product(target.dump);
  307. this.#node = null;
  308. this.#login = new login_manager().logged_in;
  309. }
  310. get #header() {
  311. const header = document.createElement("div");
  312. header.classList.add("header");
  313. const title = document.createElement("h3");
  314. title.innerText = this.#target.name;
  315. header.appendChild(title);
  316. if (this.#login) {
  317. const manage = document.createElement("div");
  318. manage.classList.add("manage");
  319. header.appendChild(manage);
  320. manage.appendChild(this.#rent);
  321. manage.appendChild(this.#give_back);
  322. }
  323. return header;
  324. }
  325. get #rent() {
  326. const rent_button = document.createElement("button");
  327. rent_button.classList.add("material-icons");
  328. rent_button.classList.add("rent-button");
  329. rent_button.innerText = "backpack";
  330. return rent_button;
  331. }
  332. get #give_back() {
  333. const give_back_button = document.createElement("button");
  334. give_back_button.classList.add("material-icons");
  335. give_back_button.classList.add("rent-button");
  336. give_back_button.innerText = "save_alt";
  337. return give_back_button;
  338. }
  339. get #description() {
  340. const container = document.createElement("div");
  341. container.classList.add("description");
  342. const description = document.createElement("p");
  343. description.innerText = this.#target.description;
  344. description.classList.add("content");
  345. const author_container = document.createElement("div");
  346. author_container.classList.add("author");
  347. const author = document.createElement("span");
  348. author.innerText = this.#target.author;
  349. const author_icon = document.createElement("span");
  350. author_icon.classList.add("material-icons");
  351. author_icon.innerText = "attribution";
  352. author_container.appendChild(author_icon);
  353. author_container.appendChild(author);
  354. const stock_count = document.createElement("p");
  355. stock_count.classList.add("stock-count");
  356. stock_count.classList.add("material-icons");
  357. if (this.#target.stock_count > 0) {
  358. stock_count.innerText = "check_circle";
  359. stock_count.classList.add("avairable");
  360. } else {
  361. stock_count.innerText = "cancel";
  362. stock_count.classList.add("unavairable");
  363. }
  364. const barcode_container = document.createElement("p");
  365. barcode_container.classList.add("barcode");
  366. const barcode = document.createElement("span");
  367. barcode.innerText = this.#target.barcode;
  368. barcode.classList.add("numbers");
  369. const barcode_icon = document.createElement("span");
  370. barcode_icon.classList.add("material-icons");
  371. barcode_icon.innerText = "qr_code_scanner";
  372. barcode_container.appendChild(barcode_icon);
  373. barcode_container.appendChild(barcode);
  374. container.appendChild(description);
  375. container.appendChild(author_container);
  376. container.appendChild(barcode_container);
  377. container.appendChild(stock_count);
  378. return container;
  379. }
  380. get #image() {
  381. const image = document.createElement("img");
  382. image.classList.add("image");
  383. image.src = this.#target.image;
  384. image.alt = this.#target.name;
  385. image.addEventListener("click", () => {
  386. new product_fullscreen(this.#target).show();
  387. });
  388. return image;
  389. }
  390. get node() {
  391. if (this.#node !== null) {
  392. return this.#node;
  393. }
  394. const bottom_container = document.createElement("div");
  395. bottom_container.classList.add("bottom-container");
  396. bottom_container.appendChild(this.#description);
  397. bottom_container.appendChild(this.#image);
  398. const container = document.createElement("div");
  399. container.classList.add("product");
  400. container.appendChild(this.#header);
  401. container.appendChild(bottom_container);
  402. return this.#node = container;
  403. }
  404. add(target) {
  405. const node = this.node;
  406. node.style.opacity = "0";
  407. node.style.transition = "opacity 0.5s";
  408. target.appendChild(node);
  409. setTimeout(() => {
  410. node.style.opacity = "1";
  411. }, 50);
  412. }
  413. drop() {
  414. const container = this.#node;
  415. if (container === null) {
  416. throw new TypeError("It is not showed yet.");
  417. }
  418. container.style.opacity = "1";
  419. container.style.transition = "opacity 0.5s";
  420. setTimeout(() => {
  421. container.style.opacity = "0";
  422. }, 50);
  423. setTimeout(() => {
  424. this.#node = null;
  425. container.remove();
  426. }, 550);
  427. }
  428. };
  429. // application/scripts/product_containers.js
  430. var product_containers = class {
  431. #content;
  432. #where;
  433. #inserted;
  434. constructor(where) {
  435. this.#where = where;
  436. this.#content = new Array();
  437. this.#inserted = new Array();
  438. }
  439. add_list(target) {
  440. target.forEach((count) => {
  441. this.add(count);
  442. });
  443. return this;
  444. }
  445. add(target) {
  446. const current = new product_container(target);
  447. this.#content.push(current);
  448. return this;
  449. }
  450. clean() {
  451. this.#content = new Array();
  452. return this;
  453. }
  454. update() {
  455. this.#hide();
  456. setTimeout(() => {
  457. this.#content.forEach((count) => {
  458. this.#inserted.push(count);
  459. count.add(this.#where);
  460. });
  461. }, 500);
  462. return this;
  463. }
  464. #hide() {
  465. this.#inserted.forEach((count) => {
  466. if (!this.#content.includes(count)) {
  467. count.drop();
  468. }
  469. });
  470. this.#inserted = new Array();
  471. return this;
  472. }
  473. };
  474. // application/scripts/searcher.js
  475. var searcher = class {
  476. #input;
  477. #category;
  478. #manager;
  479. #result;
  480. constructor(search_form, manager, result) {
  481. this.#input = search_form.querySelector('input[type="text"]');
  482. this.#category = search_form.querySelector("select");
  483. this.#manager = manager;
  484. this.#result = result;
  485. this.#selector_complete();
  486. search_form.addEventListener("submit", (target) => {
  487. target.preventDefault();
  488. this.update();
  489. });
  490. }
  491. get categories() {
  492. return {
  493. "name": "Name",
  494. "author": "Author"
  495. };
  496. }
  497. #selector_complete() {
  498. const category = this.#category;
  499. const categories = this.categories;
  500. Object.keys(categories).forEach((name) => {
  501. const option = document.createElement("option");
  502. option.value = name;
  503. option.innerText = categories[name];
  504. category.appendChild(option);
  505. });
  506. }
  507. get #loader() {
  508. return {
  509. "name": products_loader.search_name,
  510. "author": products_loader.search_author
  511. }[this.category];
  512. }
  513. get category() {
  514. return this.#category.value;
  515. }
  516. get phrase() {
  517. return this.#input.value.trim();
  518. }
  519. get #result_title() {
  520. return this.#result.innerText;
  521. }
  522. set #result_title(target) {
  523. this.#result.innerText = target;
  524. }
  525. async update() {
  526. if (this.phrase.length === 0) {
  527. this.show_all();
  528. return;
  529. }
  530. this.#insert(await this.#loader(this.phrase));
  531. }
  532. #insert(list) {
  533. if (list.length === 0) {
  534. this.#result_title = "Not found anything.";
  535. } else {
  536. this.#result_title = "Browse our products!";
  537. }
  538. this.#manager.clean().add_list(list).update();
  539. }
  540. async show_all() {
  541. this.#insert(await products_loader.all());
  542. }
  543. };
  544. // application/scripts/login_prompt.js
  545. var login_prompt = class extends fullscreen {
  546. constructor(target) {
  547. super();
  548. target.addEventListener("click", () => {
  549. this.show();
  550. });
  551. }
  552. get _nick() {
  553. return this.get_query("#nick").value;
  554. }
  555. get _password() {
  556. return this.get_query("#password").value;
  557. }
  558. get _result() {
  559. return this.get_query("#result");
  560. }
  561. async _login() {
  562. const manager = new login_manager();
  563. const result = await manager.login(this._nick, this._password);
  564. if (result) {
  565. this._result.style.color = "green";
  566. this._result.innerText = "Login success!";
  567. setTimeout(() => {
  568. location.reload();
  569. }, 500);
  570. return;
  571. }
  572. this._result.style.color = "red";
  573. this._result.innerText = "Can not login! Check login and password.";
  574. }
  575. _build_node() {
  576. const container = document.createElement("div");
  577. container.classList.add("login-prompt");
  578. const center = document.createElement("form");
  579. center.classList.add("center");
  580. container.appendChild(center);
  581. const nick_label = document.createElement("label");
  582. nick_label.innerText = "Your nick:";
  583. nick_label.htmlFor = "nick";
  584. center.appendChild(nick_label);
  585. const nick = document.createElement("input");
  586. nick.type = "text";
  587. nick.name = "nick";
  588. nick.id = "nick";
  589. nick.placeholder = "Nick...";
  590. center.appendChild(nick);
  591. const password_label = document.createElement("label");
  592. password_label.innerText = "Your password:";
  593. password_label.htmlFor = "password";
  594. center.appendChild(password_label);
  595. const password = document.createElement("input");
  596. password.type = "password";
  597. password.name = "password";
  598. password.id = "password";
  599. password.placeholder = "Password...";
  600. center.appendChild(password);
  601. const submit = document.createElement("button");
  602. submit.type = "submit";
  603. submit.classList.add("material-icons");
  604. submit.innerText = "send";
  605. center.appendChild(submit);
  606. const result = document.createElement("p");
  607. result.id = "result";
  608. result.classList.add("result");
  609. center.appendChild(result);
  610. center.addEventListener("submit", (target) => {
  611. target.preventDefault();
  612. this._login();
  613. });
  614. return container;
  615. }
  616. };
  617. // application/scripts/product_adder.js
  618. var product_adder = class extends fullscreen {
  619. _build_node() {
  620. const container = document.createElement("div");
  621. container.classList.add("product-adder");
  622. const center = document.createElement("form");
  623. center.classList.add("center");
  624. container.appendChild(center);
  625. const label_name = document.createElement("label");
  626. label_name.setAttribute("for", "name");
  627. label_name.textContent = "Name:";
  628. center.appendChild(label_name);
  629. const name = document.createElement("input");
  630. name.type = "text";
  631. name.id = "name";
  632. name.name = "name";
  633. name.placeholder = "Sample...";
  634. center.appendChild(name);
  635. const label_description = document.createElement("label");
  636. label_description.setAttribute("for", "description");
  637. label_description.textContent = "Description:";
  638. center.appendChild(label_description);
  639. const description = document.createElement("input");
  640. description.type = "text";
  641. description.id = "description";
  642. description.name = "description";
  643. description.placeholder = "This is exa...";
  644. center.appendChild(description);
  645. const label_author = document.createElement("label");
  646. label_author.setAttribute("for", "author");
  647. label_author.textContent = "Author:";
  648. center.appendChild(label_author);
  649. const author = document.createElement("input");
  650. author.type = "text";
  651. author.id = "author";
  652. author.name = "author";
  653. author.placeholder = "John Snow...";
  654. center.appendChild(author);
  655. const label_barcode = document.createElement("label");
  656. label_barcode.setAttribute("for", "barcode");
  657. label_barcode.textContent = "Barcode:";
  658. center.appendChild(label_barcode);
  659. const barcode = document.createElement("input");
  660. barcode.type = "number";
  661. barcode.id = "barcode";
  662. barcode.name = "barcode";
  663. barcode.placeholder = "Enter EAN-12...";
  664. center.appendChild(barcode);
  665. const label_stock_count = document.createElement("label");
  666. label_stock_count.setAttribute("for", "stock-count");
  667. label_stock_count.textContent = "On stock:";
  668. center.appendChild(label_stock_count);
  669. const stock_count = document.createElement("input");
  670. stock_count.type = "number";
  671. stock_count.id = "stock-count";
  672. stock_count.name = "stock-count";
  673. stock_count.placeholder = "20...";
  674. center.appendChild(stock_count);
  675. const button = document.createElement("button");
  676. button.type = "submit";
  677. button.id = "add";
  678. button.name = "add";
  679. button.className = "material-icons";
  680. button.textContent = "add";
  681. center.appendChild(button);
  682. return container;
  683. }
  684. };
  685. // application/scripts/login_bar.js
  686. var login_bar = class {
  687. #manager;
  688. constructor(target) {
  689. this.#manager = new login_manager();
  690. if (!this.#manager.logged_in) {
  691. this.#not_logged(target);
  692. return;
  693. }
  694. this.#logged(target);
  695. }
  696. #not_login_propertly() {
  697. this.#manager.logout();
  698. location.reload();
  699. }
  700. async #logged(target) {
  701. const user2 = await this.#manager.get_user();
  702. if (user2 === null) {
  703. this.#not_login_propertly();
  704. }
  705. const info_icon = document.createElement("span");
  706. info_icon.classList.add("icon");
  707. info_icon.classList.add("material-icons");
  708. info_icon.innerText = "account_circle";
  709. const info_content = document.createElement("span");
  710. info_content.innerText = user2.nick;
  711. const info = document.createElement("p");
  712. info.classList.add("login-info");
  713. info.appendChild(info_icon);
  714. info.appendChild(info_content);
  715. target.appendChild(info);
  716. const logout_button = document.createElement("button");
  717. logout_button.innerText = "logout";
  718. logout_button.classList.add("logout-button");
  719. logout_button.classList.add("material-icons");
  720. target.appendChild(logout_button);
  721. const add_product_button = document.createElement("button");
  722. add_product_button.innerText = "add";
  723. add_product_button.classList.add("add-product-button");
  724. add_product_button.classList.add("material-icons");
  725. target.appendChild(add_product_button);
  726. add_product_button.addEventListener("click", () => {
  727. new product_adder().show();
  728. });
  729. logout_button.addEventListener("click", () => {
  730. this.#manager.logout();
  731. location.reload();
  732. });
  733. }
  734. #not_logged(target) {
  735. const login_button = document.createElement("button");
  736. login_button.innerText = "account_circle";
  737. login_button.classList.add("login-button");
  738. login_button.classList.add("material-icons");
  739. target.appendChild(login_button);
  740. new login_prompt(login_button);
  741. }
  742. };
  743. // application/scripts/core.js
  744. document.addEventListener("DOMContentLoaded", async () => {
  745. const top_bar_spacing = new height_equaler(
  746. document.querySelector(".top-bar"),
  747. document.querySelector(".top-bar-spacing")
  748. );
  749. const container = document.querySelector(".products");
  750. const search_bar = document.querySelector("form.search");
  751. const search_title = document.querySelector(".search-title");
  752. const login_space = document.querySelector(".top-bar .right");
  753. const manager = new product_containers(container);
  754. new login_bar(login_space);
  755. new searcher(search_bar, manager, search_title).show_all();
  756. });
  757. })();