index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. // Control, крутилки регулировки RGB и Audio
  2. function Control(
  3. el,
  4. {
  5. value = 0,
  6. min = 0,
  7. max = 100,
  8. minAngle = 0,
  9. maxAngle = 360,
  10. wheelSpeed = 0.1,
  11. step = 1,
  12. } = {}
  13. ) {
  14. const img = document.createElement("img");
  15. img.src = "wheel.png";
  16. el.append(img);
  17. const ratio = (maxAngle - minAngle) / (max - min);
  18. const getAngle = () => (value - min) * ratio + minAngle;
  19. this.setValue = (newValue) => {
  20. if (newValue > max) {
  21. newValue = max;
  22. }
  23. if (newValue < min) {
  24. newValue = min;
  25. }
  26. value = newValue;
  27. img.style.transform = `rotate(${getAngle()}deg)`;
  28. if (this.onchange && typeof this.onchange === "function") {
  29. this.onchange(value);
  30. }
  31. };
  32. this.getValue = () => value;
  33. img.onmousewheel = (e) => {
  34. const { deltaY } = e;
  35. const newValue = value + deltaY * wheelSpeed;
  36. this.setValue(newValue);
  37. e.preventDefault();
  38. };
  39. img.onclick = (e) => {
  40. const { width } = img;
  41. const { layerX } = e;
  42. if (layerX > width / 2) {
  43. this.setValue(value + step);
  44. } else {
  45. this.setValue(value - step);
  46. }
  47. };
  48. const toDeg = (rad) => ((rad * 180) / Math.PI + 360 + 90) % 360;
  49. let prevMouseAngle = null;
  50. img.onmousedown = (e) => {
  51. const y = e.layerY - img.height / 2;
  52. const x = e.layerX - img.width / 2;
  53. prevMouseAngle = toDeg(Math.atan2(y, x));
  54. e.preventDefault();
  55. };
  56. img.onmousemove = (e) => {
  57. if (prevMouseAngle === null) return;
  58. const y = e.layerY - img.height / 2;
  59. const x = e.layerX - img.width / 2;
  60. let currentMouseAngle = toDeg(Math.atan2(y, x));
  61. let moveAngleDiff = currentMouseAngle - prevMouseAngle;
  62. this.setValue(value + moveAngleDiff / ratio);
  63. prevMouseAngle = currentMouseAngle;
  64. };
  65. img.ommouseout = img.onmouseup = () => {
  66. prevMouseAngle = null;
  67. };
  68. this.setValue(value);
  69. }
  70. function changeVolume() {
  71. let control = document.querySelector("#myPlayer");
  72. let volumeValue = volumeControl.getValue() * 0.01;
  73. control.volume = volumeValue;
  74. }
  75. const volumeControl = new Control(container1, { min: 0, max: 100 });
  76. volumeControl.onchange = changeVolume;
  77. function setRGB() {
  78. let color = document.querySelector("#colorChange");
  79. let redValue = red.getValue();
  80. let greenValue = green.getValue();
  81. let blueValue = blue.getValue();
  82. color.style.backgroundColor =
  83. "rgb(" + redValue + "," + greenValue + "," + blueValue + ")";
  84. }
  85. const red = new Control(container2, { min: 0, max: 255 });
  86. red.onchange = setRGB;
  87. const green = new Control(container2, { min: 0, max: 255 });
  88. green.onchange = setRGB;
  89. const blue = new Control(container2, { min: 0, max: 255 });
  90. blue.onchange = setRGB;
  91. // ДЗ: Functional OOP
  92. // Password
  93. function Password(parent = document.body, open = false) {
  94. let passInput = document.createElement("input");
  95. let check = document.createElement("input");
  96. check.type = "checkbox";
  97. check.id = "showhide";
  98. check.checked = open;
  99. parent.append(check);
  100. passInput.type = check.checked ? "text" : "password";
  101. parent.append(passInput);
  102. // get input value
  103. this.getValue = () => passInput.value;
  104. // set input value
  105. this.setValue = (newValue) => {
  106. passInput.value = newValue;
  107. };
  108. // read the openness of the text in the input field
  109. this.getOpen = () => check.checked;
  110. // set the openness of the text in the input field
  111. this.setOpen = () =>
  112. check.checked ? (passInput.type = "text") : (passInput.type = "password");
  113. // sending text out
  114. passInput.oninput = () => {
  115. if (this.onChange && typeof this.onChange === "function") {
  116. this.onChange(this.getValue());
  117. }
  118. };
  119. // triggered by changing the password open state
  120. check.oninput = () => {
  121. this.getOpen() ? this.setOpen(true) : this.setOpen(false);
  122. if (typeof this.onOpenChange === "function") {
  123. this.onOpenChange(this.getOpen());
  124. }
  125. if (this.onOpenChange && typeof this.onOpenChange === "function") {
  126. this.onOpenChange(this.getOpen());
  127. }
  128. };
  129. }
  130. let p = new Password(container3, true);
  131. p.onChange = (data) => console.log(data);
  132. p.onOpenChange = (open) => console.log(open);
  133. p.setValue("qwertyasd");
  134. console.log(p.getValue());
  135. p.setOpen(false);
  136. console.log(p.getOpen());
  137. // LoginForm
  138. function LoginForm(parent = formContainer, disabled = true) {
  139. const login = document.createElement("input");
  140. const loginBtn = document.createElement("button");
  141. login.type = "text";
  142. loginBtn.disabled = disabled;
  143. loginBtn.innerText = "Login";
  144. this.getValue = () => login.value;
  145. this.setValue = (newValue) => (login.value = newValue);
  146. this.getOpen = () => loginBtn.disabled;
  147. this.setOpen = (check) => (loginBtn.disabled = check);
  148. login.oninput = () => this.onChange();
  149. parent.append(login);
  150. parent.append(loginBtn);
  151. }
  152. let loginForm = new LoginForm(formContainer, true);
  153. let password = new Password(formContainer, true);
  154. function check() {
  155. loginForm.getValue() !== "" && password.getValue() !== ""
  156. ? loginForm.setOpen(false)
  157. : password.setOpen(true);
  158. }
  159. loginForm.onChange = check;
  160. password.onChange = check;
  161. // Password Verify
  162. function passChange() {
  163. const secondPassword = document.createElement("input");
  164. password.onOpenChange = (check) => {
  165. if (!check) {
  166. secondPassword.type = password.setOpen();
  167. secondPassword.value = password.getValue();
  168. secondPassword.checked = password.getOpen();
  169. formContainer.append(secondPassword);
  170. } else {
  171. secondPassword.remove();
  172. }
  173. };
  174. }
  175. passChange();
  176. // Form
  177. function Form(el = sFormContainer, data, okCallback, cancelCallback) {
  178. let initState = data;
  179. let flags = {};
  180. for (let key in data) {
  181. key[0] !== "*" ? (flags[key] = true) : (flags[key.slice(1)] = false);
  182. }
  183. let formBody = document.createElement("div");
  184. formBody.id = "formBody";
  185. let table = document.createElement("table");
  186. table.setAttribute("border", "1");
  187. formBody.append(table);
  188. let buttons = document.createElement("div");
  189. let okButton = document.createElement("button");
  190. okButton.innerHTML = "OK";
  191. okButton.disabled = true;
  192. let cancelButton = document.createElement("button");
  193. cancelButton.innerHTML = "Cancel";
  194. this.validators = {};
  195. let inputCreators = {
  196. String(key, value, oninput) {
  197. let input = document.createElement("input");
  198. input.type = /[*]/g.test(value) ? "password" : "text";
  199. input.value = /[*]/g.test(value) ? "" : value;
  200. input.placeholder = key[0] === "*" ? key.slice(1) : key;
  201. input.oninput = () => oninput(input.value);
  202. return input;
  203. },
  204. Boolean(key, value, oninput) {
  205. let input = document.createElement("input");
  206. input.type = "checkbox";
  207. input.checked = value;
  208. input.oninput = () => oninput(input.checked);
  209. return input;
  210. },
  211. Date(key, value, oninput) {
  212. let input = document.createElement("input");
  213. input.type = "datetime-local";
  214. input.value = new Date(value - new Date().getTimezoneOffset() * 60 * 1000)
  215. .toISOString()
  216. .slice(0, -1);
  217. input.oninput = () => oninput(new Date(input.value));
  218. return input;
  219. },
  220. Number(key, value, oninput) {
  221. let input = document.createElement("input");
  222. input.type = "number";
  223. input.placeholder = key[0] === "*" ? key.slice(1) : key;
  224. input.value = value;
  225. input.oninput = () => oninput(input.value);
  226. return input;
  227. },
  228. };
  229. let flagsArray = [];
  230. for (let [key, value] of Object.entries(data)) {
  231. const tr = document.createElement("tr");
  232. const th = document.createElement("th");
  233. th.innerHTML =
  234. key[0] === "*"
  235. ? `<span style="color: red">${key[0]}</span> ${key.slice(1)}`
  236. : key;
  237. const td = document.createElement("td");
  238. const error = document.createElement("span");
  239. error.style.color = "red";
  240. const input = inputCreators[value.constructor.name](
  241. key,
  242. value,
  243. (valueInput) => {
  244. value = valueInput;
  245. }
  246. );
  247. td.append(input);
  248. tr.append(th);
  249. tr.append(td);
  250. if (key[0] === "*" && value === "") {
  251. flags[key.slice(1)] = false;
  252. error.innerText = `Required ${key.slice(1)} field is not filled`;
  253. td.append(error);
  254. }
  255. if (key[0] === "*" && value.length > 0) {
  256. flags[key.slice(1)] = true;
  257. }
  258. flagsArray = Object.values(flags);
  259. function checkButtons(callback, nameCallback, flags) {
  260. if (typeof callback === "function") {
  261. if (nameCallback === "okCallback") {
  262. buttons.appendChild(okButton);
  263. formBody.appendChild(buttons);
  264. if (flags.some((e) => e === false)) {
  265. okButton.disabled = true;
  266. } else {
  267. okButton.disabled = false;
  268. callback(data);
  269. okButton.onclick = (e) => {
  270. callback(e);
  271. };
  272. }
  273. }
  274. if (nameCallback === "cancelCallback") {
  275. buttons.appendChild(cancelButton);
  276. formBody.appendChild(buttons);
  277. cancelButton.onclick = () => {
  278. formBody.remove();
  279. buttons.remove();
  280. Form(
  281. sFormContainer,
  282. initState,
  283. () => console.log("ok"),
  284. () => console.log("cancel")
  285. );
  286. callback();
  287. };
  288. }
  289. }
  290. }
  291. checkButtons(okCallback, "okCallback", flagsArray);
  292. checkButtons(cancelCallback, "cancelCallback", flagsArray);
  293. input.onchange = () => {
  294. let keyCheck = key[0] === "*" ? key.slice(1) : key;
  295. if (
  296. Object.keys(this.validators).length !== 0 &&
  297. keyCheck in this.validators
  298. ) {
  299. let check = this.validators[keyCheck](value, key, data, input);
  300. if (check) {
  301. flags[keyCheck] = true;
  302. input.style.border = "";
  303. error.innerText = "";
  304. } else {
  305. flags[keyCheck] = false;
  306. input.style.border = "1px solid red";
  307. error.innerText = `Invalid ${keyCheck} entered or a required field is missing`;
  308. }
  309. td.append(error);
  310. tr.append(td);
  311. flagsArray = Object.values(flags);
  312. }
  313. checkButtons(okCallback, "okCallback", flagsArray);
  314. checkButtons(cancelCallback, "cancelCallback", flagsArray);
  315. };
  316. table.append(tr);
  317. }
  318. el.appendChild(formBody);
  319. el.appendChild(buttons);
  320. this.okCallback = okCallback;
  321. this.cancelCallback = cancelCallback;
  322. this.data = data;
  323. }
  324. let form = new Form(
  325. sFormContainer,
  326. {
  327. "*name": "Anakin",
  328. "*surname": "Skywalker",
  329. "*password": "****************",
  330. married: true,
  331. birthday: new Date(new Date().getTime() - 86400000 * 30 * 365),
  332. },
  333. () => console.log("ok"),
  334. () => console.log("cancel")
  335. );
  336. form.okCallback = () => console.log("ok2");
  337. form.cancelCallback = () => console.log("cancel2");
  338. form.validators.name = (value, key, data, input) => {
  339. if (key[0] === "*") {
  340. if (
  341. value.length > 3 &&
  342. value[0].toUpperCase() === value[0] &&
  343. !value.includes(" ")
  344. ) {
  345. return true;
  346. } else {
  347. return false;
  348. }
  349. } else {
  350. return true;
  351. }
  352. };
  353. form.validators.surname = (value, key, data, input) => {
  354. if (key[0] === "*") {
  355. if (
  356. value.length > 3 &&
  357. value[0].toUpperCase() === value[0] &&
  358. !value.includes(" ")
  359. ) {
  360. return true;
  361. } else {
  362. return false;
  363. }
  364. } else {
  365. return true;
  366. }
  367. };
  368. form.validators.password = (value, key, data, input) => {
  369. if (key[0] === "*") {
  370. if (value.length > 7 && !value.includes(" ")) {
  371. return true;
  372. } else {
  373. return false;
  374. }
  375. } else {
  376. return true;
  377. }
  378. };