index.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /*Person Constructor
  2. Переделайте задание createPerson на функцию конструктор Person.
  3. const a = new Person("Вася", "Пупкин")
  4. const b = new Person("Анна", "Иванова")
  5. const c = new Person("Елизавета", "Петрова")
  6. console.log(a.getFullName()) //Вася Пупкин
  7. a.fatherName = 'Иванович' //Вася Иванович Пупкин
  8. console.log(b.getFullName()) //Анна Иванова
  9. Для этого методы и свойства заносите не в создаваемый объект, а в this внутри конструктора.*/
  10. {
  11. const a = new Person("Вася", "Пупкин")
  12. const b = new Person("Анна", "Иванова")
  13. const c = new Person("Елизавета", "Петрова")
  14. console.log(a.getFullName()) //Вася Пупкин
  15. a.fatherName = 'Иванович' //Вася Иванович Пупкин
  16. console.log(b.getFullName()) //Анна Иванова
  17. function Person(name, surname) {
  18. this.name = name,
  19. this.surname = surname,
  20. this.getFullName = () => `${this.name} ${this.fatherName || ""} ${this.surname}`
  21. }
  22. }
  23. /*Person Prototype
  24. Переделайте предыдущее задание, вынеся методы в прототип. Для этого вместо присвоения в this занесите их в объект Person.prototype. После этой переделки все должно работать по старому:
  25. const a = createPerson("Вася", "Пупкин")
  26. const b = createPerson("Анна", "Иванова")
  27. const c = createPerson("Елизавета", "Петрова")
  28. console.log(a.getFullName()) //Вася Пупкин
  29. a.fatherName = 'Иванович' //Вася Иванович Пупкин
  30. console.log(b.getFullName()) //Анна Иванова*/
  31. {
  32. const a = new Person("Вася", "Пупкин")
  33. const b = new Person("Анна", "Иванова")
  34. const c = new Person("Елизавета", "Петрова")
  35. console.log(a.getFullName()) //Вася Пупкин
  36. a.fatherName = 'Иванович' //Вася Иванович Пупкин
  37. console.log(a.getFullName())
  38. console.log(b.getFullName()) //Анна Иванова
  39. function Person(name, surname) {
  40. Person.prototype.getFullName = function () { return `${this.name} ${this.fatherName || ""} ${this.surname}` }
  41. this.name = name
  42. this.surname = surname
  43. }
  44. }
  45. /*Store (код работает в index.html)
  46. Переделайте функцию createStore (та, которая хранилище Redux) на конструктор Store. Прототип не используйте; оставьте переменные state, cbs и reducer замкнутыми. Соответственно методы subscribe, dispatch и getState должны быть объявлены внутри функции-конструктора и не могут быть в прототипе. Проверьте переделанный конструктор на вашем ДЗ по ларьку;*/
  47. {
  48. function reducer(state, { type, productName, productQuantity, summ }) { //объект action деструктуризируется на три переменных
  49. if (!state) { //начальная уборка в ларьке:
  50. return {
  51. пиво: {
  52. quantity: 100,
  53. price: 30,
  54. },
  55. чипсы: {
  56. quantity: 100,
  57. price: 52,
  58. },
  59. сиги: {
  60. quantity: 100,
  61. price: 89,
  62. },
  63. касса: 0
  64. }
  65. }
  66. if (type === 'КУПИТЬ' && productQuantity <= state[productName].quantity && summ >= state[productName].price * productQuantity) { //если тип action - КУПИТЬ, то:
  67. return {
  68. ...state, //берем все что было из ассортимента
  69. [productName]: {
  70. quantity: state[productName].quantity - productQuantity,
  71. price: state[productName].price
  72. },
  73. касса: state.касса + state[productName].price * productQuantity
  74. //и уменьшаем то, что покупается на количество
  75. }
  76. }
  77. return state //если мы не поняли, что от нас просят в `action` - оставляем все как есть
  78. }
  79. /*Store (код работает в index.html)
  80. Переделайте функцию createStore (та, которая хранилище Redux) на конструктор Store. Прототип не используйте; оставьте переменные state, cbs и reducer замкнутыми. Соответственно методы subscribe, dispatch и getState должны быть объявлены внутри функции-конструктора и не могут быть в прототипе. Проверьте переделанный конструктор на вашем ДЗ по ларьку;*/
  81. function createStore(reducer) {
  82. let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
  83. let cbs = [] //массив подписчиков
  84. this.getState = () => state //функция, возвращающая переменную из замыкания + добавление функции getState в результирующий объект
  85. this.dispatch = action => {
  86. const newState = reducer(state, action) //пробуем запустить редьюсер
  87. if (newState !== state) { //проверяем, смог ли редьюсер обработать action
  88. state = newState //если смог, то обновляем state
  89. for (let cb of cbs) cb() //и запускаем подписчиков
  90. }
  91. }
  92. this.subscribe = cb => (cbs.push(cb), //запоминаем подписчиков в массиве
  93. () => cbs = cbs.filter(c => c !== cb)) //добавление subscribe в объект
  94. }
  95. function actionCreator(type, productName, productQuantity, summ) {
  96. return {
  97. type,
  98. productName,
  99. productQuantity,
  100. summ
  101. }
  102. }
  103. const store = new createStore(reducer)
  104. myState = store.getState()
  105. const showcase = document.createElement('section')
  106. document.body.append(showcase)
  107. showcase.classList.add('showcase')
  108. const orderSection = document.createElement('section')
  109. document.body.append(orderSection)
  110. orderSection.classList.add('orderSection')
  111. const orderSelectProd = document.createElement('select')
  112. orderSection.append(orderSelectProd)
  113. const orderInputQuantity = document.createElement('input')
  114. orderInputQuantity.type = 'number'
  115. orderInputQuantity.min = '0'
  116. orderSection.append(orderInputQuantity)
  117. const orderInputQuantityName = document.createElement('div')
  118. orderInputQuantity.before(orderInputQuantityName)
  119. orderInputQuantityName.innerText = 'количество товара:'
  120. const orderSendMoney = document.createElement('input')
  121. orderSendMoney.type = 'number'
  122. orderSendMoney.min = '0'
  123. orderSection.append(orderSendMoney)
  124. const orderSendMoneyName = document.createElement('div')
  125. orderSendMoney.before(orderSendMoneyName)
  126. orderSendMoneyName.innerText = 'сумма:'
  127. const orderBuyButton = document.createElement('input')
  128. orderBuyButton.type = 'button'
  129. orderBuyButton.value = 'КУПИТЬ'
  130. orderSection.append(orderBuyButton)
  131. orderBuyButton.onclick = () => { store.dispatch(actionCreator(orderBuyButton.value, orderSelectProd.value, +orderInputQuantity.value, +orderSendMoney.value)) }
  132. for (const elemProduct in store.getState()) {
  133. if (elemProduct === 'касса') continue
  134. const productCard = document.createElement('div')
  135. const productName = document.createElement('h2')
  136. const productPrice = document.createElement('div')
  137. const productQuantity = document.createElement('div')
  138. productCard.append(productName)
  139. productCard.append(productQuantity)
  140. productCard.append(productPrice)
  141. showcase.append(productCard)
  142. productCard.classList.add('productCard')
  143. productName.classList.add('productName')
  144. productPrice.classList.add('productPrice')
  145. productQuantity.classList.add('productQuantity')
  146. productName.innerText = elemProduct
  147. productPrice.innerText = store.getState()[elemProduct].price + ' грн'
  148. productQuantity.innerText = store.getState()[elemProduct].quantity + ' шт\nв наличии'
  149. const selectProdOption = document.createElement('option')
  150. selectProdOption.value = selectProdOption.innerText = elemProduct
  151. orderSelectProd.append(selectProdOption)
  152. const productPriceUnsubscribe = store.subscribe(() => {
  153. productPrice.innerText = store.getState()[elemProduct].price + ' грн'
  154. })
  155. const productQuantityUnsubscribe = store.subscribe(() => {
  156. productQuantity.innerText = store.getState()[elemProduct].quantity + ' шт\nв наличии'
  157. })
  158. }
  159. }
  160. /*Password*/
  161. {
  162. function Password(parent, open) {
  163. const inputPass = document.createElement('input')
  164. parent.append(inputPass)
  165. const checkboxPass = document.createElement('input')
  166. checkboxPass.type = 'checkbox'
  167. parent.append(checkboxPass)
  168. this.setValue = (value) => {
  169. inputPass.value = value
  170. if (typeof this.onChange === 'function') this.onChange(this.getValue()) // запускается по событию oninput в поле ввода, передает текст в колбэк
  171. } //задает значение
  172. this.getValue = () => inputPass.value //читает значение
  173. this.setOpen = (open) => {
  174. if (open) {
  175. checkboxPass.checked = true
  176. inputPass.type = "text"
  177. }
  178. if (!open) {
  179. checkboxPass.checked = false
  180. inputPass.type = "password"
  181. }
  182. if (typeof this.onOpenChange === 'function') this.onOpenChange(this.getOpen()) // запускается по изменению состояния открытости пароля
  183. } //задает открытость текста в поле ввода
  184. this.getOpen = () => checkboxPass.checked //читает открытость текста в поле ввода
  185. this.setOpen(open)
  186. inputPass.oninput = () => this.setValue(this.getValue())
  187. checkboxPass.oninput = () => this.setOpen(this.getOpen())
  188. }
  189. let p = new Password(document.body, true)
  190. p.onChange = data => console.log(data)
  191. p.onOpenChange = open => console.log(open)
  192. p.setValue('qwerty')
  193. console.log(p.getValue())
  194. p.setOpen(false)
  195. console.log(p.getOpen())
  196. }
  197. /*
  198. Напишите функцию конструктор Password, которая будет в родительском элементе создавать поле ввода для пароля и кнопку/иконку/чекбокс, который будет переключать режим просмотра пароля в поле ввода. (видимый пароль или нет, input type='text' или же input type='password')
  199. Параметры:
  200. parent - родительский элемент
  201. open - стартовое состояние
  202. Методы:
  203. setValue/getValue - задают/читают значения
  204. setOpen/getOpen - задают/читают открытость текста в поле ввода
  205. Колбэки (функции обратного вызова, который возможно, будут заданы снаружи конструктора):
  206. onChange - запускается по событию oninput в поле ввода, передает текст в колбэк
  207. onOpenChange - запускается по изменению состояния открытости пароля
  208. */
  209. /* LoginForm
  210. С помощью предыдущего кода Password сделайте форму логина, кнопка в которой будет активна только если и login и пароль не пусты.
  211. "С помощью предыдущего кода" значит что в коде формы логина вы используете объект, сконструированный конструктором Password - const password = new Password(........) */
  212. {
  213. function Password(parent, open) {
  214. const inputPass = document.createElement('input')
  215. parent.append(inputPass)
  216. const checkboxPass = document.createElement('input')
  217. checkboxPass.type = 'checkbox'
  218. parent.append(checkboxPass)
  219. this.setValue = (value) => {
  220. inputPass.value = value
  221. if (typeof this.onChange === 'function') this.onChange(this.getValue()) // запускается по событию oninput в поле ввода, передает текст в колбэк
  222. } //задает значение
  223. this.getValue = () => inputPass.value //читает значение
  224. this.setOpen = (open) => {
  225. if (open) {
  226. checkboxPass.checked = true
  227. inputPass.type = "text"
  228. }
  229. if (!open) {
  230. checkboxPass.checked = false
  231. inputPass.type = "password"
  232. }
  233. if (typeof this.onOpenChange === 'function') this.onOpenChange(this.getOpen()) // запускается по изменению состояния открытости пароля
  234. } //задает открытость текста в поле ввода
  235. this.getOpen = () => checkboxPass.checked //читает открытость текста в поле ввода
  236. this.setOpen(open)
  237. inputPass.oninput = () => this.setValue(this.getValue())
  238. checkboxPass.oninput = () => this.setOpen(this.getOpen())
  239. }
  240. const LoginForm = document.createElement('div')
  241. document.body.append(LoginForm)
  242. const inputLogin = document.createElement('input')
  243. LoginForm.append(inputLogin)
  244. let p = new Password(LoginForm, false)
  245. const inputButton = document.createElement('input')
  246. inputButton.type = 'button'
  247. inputButton.value = 'войти'
  248. LoginForm.append(inputButton)
  249. inputButton.disabled = true
  250. p.onChange = () => checkButtonDisabled()
  251. inputLogin.oninput = () => checkButtonDisabled()
  252. function checkButtonDisabled () {
  253. if (p.getValue() && inputLogin.value) inputButton.disabled = false
  254. else inputButton.disabled = true
  255. }
  256. }
  257. /*LoginForm Constructor
  258. оформите предыдущую задачу как функцию-конструктор. Продумайте и предусмотрите геттеры, сеттеры и колбэки.*/
  259. {
  260. function LoginForm(parent, passOpenDefault){
  261. function Password(parent, open) {
  262. const inputPass = document.createElement('input')
  263. parent.append(inputPass)
  264. const checkboxPass = document.createElement('input')
  265. checkboxPass.type = 'checkbox'
  266. parent.append(checkboxPass)
  267. this.setValue = (value) => {
  268. inputPass.value = value
  269. if (typeof this.onChange === 'function') this.onChange(this.getValue()) // запускается по событию oninput в поле ввода, передает текст в колбэк
  270. } //задает значение
  271. this.getValue = () => inputPass.value //читает значение
  272. this.setOpen = (open) => {
  273. if (open) {
  274. checkboxPass.checked = true
  275. inputPass.type = "text"
  276. }
  277. if (!open) {
  278. checkboxPass.checked = false
  279. inputPass.type = "password"
  280. }
  281. if (typeof this.onOpenChange === 'function') this.onOpenChange(this.getOpen()) // запускается по изменению состояния открытости пароля
  282. } //задает открытость текста в поле ввода
  283. this.getOpen = () => checkboxPass.checked //читает открытость текста в поле ввода
  284. this.setOpen(open)
  285. inputPass.oninput = () => this.setValue(this.getValue())
  286. checkboxPass.oninput = () => this.setOpen(this.getOpen())
  287. }
  288. const LoginForm = document.createElement('div')
  289. parent.append(LoginForm)
  290. const inputLogin = document.createElement('input')
  291. LoginForm.append(inputLogin)
  292. let p = new Password(LoginForm, passOpenDefault)
  293. const inputButton = document.createElement('input')
  294. inputButton.type = 'button'
  295. inputButton.value = 'войти'
  296. LoginForm.append(inputButton)
  297. inputButton.disabled = true
  298. p.onChange = () => checkButtonDisabled()
  299. inputLogin.oninput = () => checkButtonDisabled()
  300. function checkButtonDisabled () {
  301. if (p.getValue() && inputLogin.value) inputButton.disabled = false
  302. else inputButton.disabled = true
  303. }
  304. this.getLogin = () => inputLogin.value
  305. this.setLogin = (value) => {
  306. inputLogin.value = value
  307. checkButtonDisabled()
  308. }
  309. this.getPass = () => p.getValue()
  310. this.setPass = (value) => {
  311. p.setValue(value)
  312. checkButtonDisabled()
  313. }
  314. inputButton.onclick = () => {
  315. if (typeof this.inputButtonOnclick === 'function') this.inputButtonOnclick() //функция при нажатии на кнопку войти
  316. }
  317. }
  318. const t = new LoginForm (document.body, false)
  319. t.setPass("1111")
  320. t.setLogin("Абырвалг")
  321. t.inputButtonOnclick = () => alert ('заходи - не бойся, выходи - не плачь')
  322. }
  323. /*Password Verify
  324. С помощью Password сделайте пару инпутов, которые проверяют введеный пароль (в двух полях ввода) на совпадение. Подсвечивайте поля красным цветом/бордером когда пароли не совпадают При открытом пароле в первом поле ввода (которое реализуется с помощью объекта класса Password второе поле вводы должно пропадать с экрана Таким образом:
  325. Когда Password в скрытом режиме - появляется второй инпут (<input type='password'>) с паролем в скрытом режиме
  326. Когда Password в открытом режиме - второй инпут пропадает*/
  327. {
  328. function Password(parent, open) {
  329. const inputPass = document.createElement('input')
  330. parent.append(inputPass)
  331. const checkboxPass = document.createElement('input')
  332. checkboxPass.type = 'checkbox'
  333. parent.append(checkboxPass)
  334. this.setValue = (value) => {
  335. inputPass.value = value
  336. if (typeof this.onChange === 'function') this.onChange(this.getValue()) // запускается по событию oninput в поле ввода, передает текст в колбэк
  337. } //задает значение
  338. this.getValue = () => inputPass.value //читает значение
  339. this.setOpen = (open) => {
  340. if (open) {
  341. checkboxPass.checked = true
  342. inputPass.type = "text"
  343. }
  344. if (!open) {
  345. checkboxPass.checked = false
  346. inputPass.type = "password"
  347. }
  348. if (typeof this.onOpenChange === 'function') this.onOpenChange(this.getOpen()) // запускается по изменению состояния открытости пароля
  349. } //задает открытость текста в поле ввода
  350. this.getOpen = () => checkboxPass.checked //читает открытость текста в поле ввода
  351. this.getinputPass = () => inputPass
  352. this.setOpen(open)
  353. inputPass.oninput = () => this.setValue(this.getValue())
  354. checkboxPass.oninput = () => this.setOpen(this.getOpen())
  355. }
  356. const pass1 = document.createElement('div')
  357. document.body.append(pass1)
  358. const pass2 = document.createElement('div')
  359. document.body.append(pass2)
  360. const p1 = new Password (pass1, false)
  361. const p2 = new Password (pass2, false)
  362. Password.prototype.onChange = function () { passInputEqalityCheck(p1, p2) }
  363. const passInputEqalityCheck = (pass1, pass2) => {
  364. if ( pass1.getValue() !== pass2.getValue() ) {
  365. pass1.getinputPass().style.borderColor = 'red'
  366. pass2.getinputPass().style.borderColor = 'red'
  367. } else {
  368. pass1.getinputPass().style.borderColor = 'green'
  369. pass2.getinputPass().style.borderColor = 'green'
  370. }
  371. }
  372. const pass2Open = (pass1GetOpen) => {
  373. if (pass1GetOpen === true) pass2.style.display = 'none'
  374. else pass2.style.display = 'block'
  375. }
  376. p1.onOpenChange = function () {
  377. pass2Open (this.getOpen() )
  378. }
  379. }