diff --git a/frontend/components/slider/slider.js b/frontend/components/slider/slider.js
deleted file mode 100644
index 8c0533d..0000000
--- a/frontend/components/slider/slider.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/* global $ */
-import convertRemToPixels from '../../scripts/convertRemToPixels';
-
-class Slider {
- constructor(element) {
- this.$element = $(element);
- this.$parent = this.$element.parent();
- this.$view = this.$parent.find('.js-slider__view');
- this.$line = this.$parent.find('.js-slider__line');
- this.sliderChange.call(this);
- this.$element.on('input.slider', this.sliderChange.bind(this));
- }
- sliderChange() {
- const { $element } = this;
- const width = $element.width() - convertRemToPixels(1.25);
- const value = $element.val();
- const min = this.$element.prop('min');
- const max = this.$element.prop('max');
- const newLeft = ((width / (max - min)) * (value - min)) - convertRemToPixels(0.625);
- this.$view.text(value).css({ left: newLeft });
- const newWidth = ((width / (max - min)) * (value - min)) + convertRemToPixels(0.625);
- this.$line.width(newWidth);
- }
-}
-
-let sliders = [];
-$('.js-slider__input').each((index, element) => sliders.push(new Slider(element)));
diff --git a/frontend/components/slider/slider.pug b/frontend/components/slider/slider.pug
index af116bf..c2e91a3 100644
--- a/frontend/components/slider/slider.pug
+++ b/frontend/components/slider/slider.pug
@@ -5,7 +5,7 @@ mixin slider(options)
- options.value = options.value || 0
- options.mix = options.mix || ''
- div(class = "slider slider_color_" + options.color + " " + options.mix)
+ div(class = "slider js-slider slider_color_" + options.color + " " + options.mix)
if (options.view)
.slider__view.js-slider__view #{options.value}
if (options.line)
diff --git a/frontend/components/slider/slider.ts b/frontend/components/slider/slider.ts
new file mode 100644
index 0000000..da43968
--- /dev/null
+++ b/frontend/components/slider/slider.ts
@@ -0,0 +1,31 @@
+
+import convertRemToPixels from '../../scripts/convertRemToPixels';
+
+class Slider {
+ $block: JQuery;
+ $slider: JQuery;
+ $view: JQuery;
+ $line: JQuery;
+ constructor(element) {
+ this.$block = $(element);
+ this.$slider = this.$block.find('.js-slider__input');
+ this.$view = this.$block.find('.js-slider__view');
+ this.$line = this.$block.find('.js-slider__line');
+ this.sliderChange.call(this);
+ this.$slider.on('input.slider', this.sliderChange.bind(this));
+ }
+ sliderChange(): void {
+ const { $slider } = this;
+ const width: number = $slider.width() - convertRemToPixels(1.25);
+ const value: number = Number($slider.val());
+ const min: number = Number(this.$slider.prop('min'));
+ const max: number = Number(this.$slider.prop('max'));
+ const newLeft: number = ((width / (max - min)) * (value - min)) - convertRemToPixels(0.625);
+ this.$view.text(value).css({ left: newLeft });
+ const newWidth: number = ((width / (max - min)) * (value - min)) + convertRemToPixels(0.625);
+ this.$line.width(newWidth);
+ }
+}
+
+let sliders: Slider[] = [];
+$('.js-slider').each((index, element) => { sliders.push(new Slider(element)); });
diff --git a/frontend/components/standart-button/standart-button.js b/frontend/components/standart-button/standart-button.ts
similarity index 51%
rename from frontend/components/standart-button/standart-button.js
rename to frontend/components/standart-button/standart-button.ts
index 9d729a5..c359054 100644
--- a/frontend/components/standart-button/standart-button.js
+++ b/frontend/components/standart-button/standart-button.ts
@@ -1,17 +1,19 @@
-/* global $ */
+
import convertRemToPixels from '../../scripts/convertRemToPixels';
class Button {
+ $element: JQuery;
+ size: number;
constructor(element) {
this.$element = $(element).on('click.standart-button', this.rippleEffect.bind(this));
this.size = convertRemToPixels(2);
}
- rippleEffect(event) {
- const $div = $('
').attr('id', 'button__ripple');
- $div.css({ top: `${event.offsetY - this.size}px`, left: `${event.offsetX - this.size}px` });
+ rippleEffect({ offsetX, offsetY }): void {
+ const $div: JQuery = $('').attr('id', 'button__ripple');
+ $div.css({ top: `${offsetY - this.size}px`, left: `${offsetX - this.size}px` });
this.$element.append($div);
setTimeout(() => $div.remove(), 550);
}
}
let buttons = [];
-$('.js-standart-button').each((index, element) => buttons.push(new Button(element)));
+$('.js-standart-button').each((index, element) => { buttons.push(new Button(element)); });
diff --git a/frontend/index.ts b/frontend/index.ts
index 6b1fee5..78a769b 100644
--- a/frontend/index.ts
+++ b/frontend/index.ts
@@ -1,7 +1,8 @@
import './index.styl';
import './favicons/favicons';
import './components/slider/slider';
-import Controller from './mvc/controller/Controller.ts';
+import './components/standart-button/standart-button';
+import Controller from './mvc/controller/Controller';
import Model from './mvc/model/Model';
import View from './mvc/view/View';
diff --git a/frontend/mvc/controller/Controller.ts b/frontend/mvc/controller/Controller.ts
index 9a61f91..9742f42 100644
--- a/frontend/mvc/controller/Controller.ts
+++ b/frontend/mvc/controller/Controller.ts
@@ -1,5 +1,6 @@
-import IModel from '../model/IModel';
-import IView from '../view/IView';
+import { IModel } from '../model/IModel';
+import { IView } from '../view/IView';
+
class Controller {
model: IModel;
@@ -15,34 +16,34 @@ class Controller {
this.setRunning(false);
}
setSubscription():void {
- this.model.matrixChanged.attach((sender, obj) => {
- if (obj.resized) { this.view.initTable(obj.matrix); }
- else { this.view.changeTable(obj.matrix); }
+ this.model.matrixChanged.attach((sender, { resized , matrix }) => {
+ if (resized) { this.view.initTable(matrix); }
+ else { this.view.changeTable(matrix); }
});
this.view.tableCellChanged.attach((sender, { row, cell }) => {
this.model.toggleCell(row, cell);
});
- this.view.startEvent.attach(() => {
+ this.view.started.attach(() => {
this.setRunning(true);
this.anim();
});
- this.view.pauseEvent.attach(() => {
+ this.view.paused.attach(() => {
this.setRunning(false);
});
- this.view.clearEvent.attach(() => {
+ this.view.cleared.attach(() => {
this.model.clearMatrix();
this.setRunning(false);
});
- this.view.speedChanged.attach((sender, options) => {
- this.fps = options.value;
+ this.view.speedChanged.attach((sender, value) => {
+ this.fps = value;
});
- this.view.widthChanged.attach((sender, options) => {
+ this.view.widthChanged.attach((sender, value) => {
this.setRunning(false);
- this.model.setWidthMatrix(options.value);
+ this.model.setWidthMatrix(value);
});
- this.view.heightChanged.attach((sender, options) => {
+ this.view.heightChanged.attach((sender, value) => {
this.setRunning(false);
- this.model.setHeightMatrix(options.value);
+ this.model.setHeightMatrix(value);
});
}
setRunning(value: boolean): void {
diff --git a/frontend/mvc/model/IModel.ts b/frontend/mvc/model/IModel.ts
index 3024706..d3ceb81 100644
--- a/frontend/mvc/model/IModel.ts
+++ b/frontend/mvc/model/IModel.ts
@@ -1,8 +1,13 @@
import IEventSender from '../utils/IEventSender';
+type matrixChangedMessage = {
+ matrix: boolean[][];
+ resized?: boolean;
+};
+
interface IModel {
matrix: boolean[][];
- matrixChanged: IEventSender;
+ matrixChanged: IEventSender;
setWidthMatrix(newValue: number): void;
setHeightMatrix(newValue: number): void;
clearMatrix(): void;
@@ -11,4 +16,4 @@ interface IModel {
toggleCell(row: number, column: number): void;
}
-export default IModel;
+export { IModel, matrixChangedMessage };
diff --git a/frontend/mvc/model/Model.ts b/frontend/mvc/model/Model.ts
index bebd095..4433dcb 100644
--- a/frontend/mvc/model/Model.ts
+++ b/frontend/mvc/model/Model.ts
@@ -1,19 +1,19 @@
-import Event from '../utils/EventSender';
-import IModel from './IModel';
+import EventSender from '../utils/EventSender';
+import { IModel, matrixChangedMessage } from './IModel';
import '../../scripts/arrayFrom-polyfill';
class Model implements IModel{
matrix: boolean[][];
rows: number;
columns: number;
- listOldMatrix: boolean[][][];
- matrixChanged: Event;
+ stateHistory: boolean[][][];
+ matrixChanged: EventSender;
constructor(rows: number = 10, columns: number = 10) {
this.initMatrix(rows, columns);
this.rows = rows;
this.columns = columns;
- this.listOldMatrix = [];
- this.matrixChanged = new Event(this);
+ this.stateHistory = [];
+ this.matrixChanged = new EventSender(this);
}
initMatrix(rows: number, columns: number): void {
this.matrix = Array.from(Array(rows), () => Array.from(Array(columns), () => false));
@@ -29,7 +29,7 @@ class Model implements IModel{
return row.slice(0, newWidth);
});
this.columns = newWidth;
- this.listOldMatrix = [];
+ this.stateHistory = [];
this.matrixChanged.notify({ matrix: this.matrix, resized: true });
}
setHeightMatrix(newHeight: number): void {
@@ -38,12 +38,12 @@ class Model implements IModel{
return this.getNewRow(this.columns);
});
this.rows = newHeight;
- this.listOldMatrix = [];
+ this.stateHistory = [];
this.matrixChanged.notify({ matrix: this.matrix, resized: true });
}
clearMatrix(): void {
this.initMatrix(this.rows, this.columns);
- this.listOldMatrix = [];
+ this.stateHistory = [];
this.matrixChanged.notify({ matrix: this.matrix });
}
calculateMatrix(): void {
@@ -53,15 +53,15 @@ class Model implements IModel{
this.matrixChanged.notify({ matrix: this.matrix });
}
isRepeatMatrix(): boolean {
- const result: boolean = this.listOldMatrix.some((matrix: boolean[][]) =>
+ const result: boolean = this.stateHistory.some((matrix: boolean[][]) =>
matrix.every((row: boolean[], i: number) =>
row.every((cell: boolean, j: number) =>
(cell === this.matrix[i][j]),
),
),
);
- if (result) { this.listOldMatrix = []; }
- else { this.listOldMatrix.push(this.matrix); }
+ if (result) { this.stateHistory = []; }
+ else { this.stateHistory.push(this.matrix); }
return result;
}
calculateCell(row: number, column: number): boolean {
diff --git a/frontend/mvc/utils/EventSender.ts b/frontend/mvc/utils/EventSender.ts
index 260a8db..a701ea8 100644
--- a/frontend/mvc/utils/EventSender.ts
+++ b/frontend/mvc/utils/EventSender.ts
@@ -1,16 +1,16 @@
import IEventSender from './IEventSender';
-class EventSender implements IEventSender {
+class EventSender implements IEventSender {
sender: object;
- listeners: Array<(a, b) => void>;
+ listeners: Array<(a: object, b: T) => void>;
constructor(sender: object) {
this.sender = sender;
this.listeners = [];
}
- attach(listener: (a, b) => void): void {
+ attach(listener: (a: object, b: T) => void): void {
this.listeners.push(listener);
}
- notify(args: object): void {
+ notify(args: T): void {
this.listeners.forEach((listener) => {
listener(this.sender, args);
});
diff --git a/frontend/mvc/utils/IEventSender.ts b/frontend/mvc/utils/IEventSender.ts
index 41127cf..088a716 100644
--- a/frontend/mvc/utils/IEventSender.ts
+++ b/frontend/mvc/utils/IEventSender.ts
@@ -1,5 +1,5 @@
-interface IEventSender {
- attach(listener: (a, b) => void): void;
- notify(args: object): void;
+interface IEventSender {
+ attach(listener: (a: object, b: T) => void): void;
+ notify(args: T): void;
}
export default IEventSender;
diff --git a/frontend/mvc/view/IView.ts b/frontend/mvc/view/IView.ts
index c37cb64..fd8964b 100644
--- a/frontend/mvc/view/IView.ts
+++ b/frontend/mvc/view/IView.ts
@@ -1,16 +1,22 @@
import IEventSender from '../utils/IEventSender';
+type tableCellAddress = {
+ row: number;
+ cell:number;
+};
+
+
interface IView {
- tableCellChanged: IEventSender;
- startEvent: IEventSender;
- pauseEvent: IEventSender;
- clearEvent: IEventSender;
- widthChanged: IEventSender;
- heightChanged: IEventSender;
- speedChanged: IEventSender;
+ tableCellChanged: IEventSender;
+ started: IEventSender;
+ paused: IEventSender;
+ cleared: IEventSender;
+ widthChanged: IEventSender;
+ heightChanged: IEventSender;
+ speedChanged: IEventSender;
setStatus(running: boolean): void;
initTable(matrix: boolean[][]): void;
changeTable(matrix: boolean[][]): void;
}
-export default IView;
+export { IView, tableCellAddress };
diff --git a/frontend/mvc/view/View.ts b/frontend/mvc/view/View.ts
index 12e39eb..16d7061 100644
--- a/frontend/mvc/view/View.ts
+++ b/frontend/mvc/view/View.ts
@@ -1,5 +1,5 @@
import EventSender from '../utils/EventSender';
-import IView from './IView';
+import { IView, tableCellAddress } from './IView';
const CLASS_CEIL = 'game__ceil';
const CLASS_CEIL_LIVE = 'game__ceil_live';
@@ -15,13 +15,13 @@ class View implements IView{
$sliderHeight: JQuery;
$status: JQuery;
- tableCellChanged: EventSender;
- startEvent: EventSender;
- pauseEvent: EventSender;
- clearEvent: EventSender;
- widthChanged: EventSender;
- heightChanged: EventSender;
- speedChanged: EventSender;
+ tableCellChanged: EventSender;
+ started: EventSender;
+ paused: EventSender;
+ cleared: EventSender;
+ widthChanged: EventSender;
+ heightChanged: EventSender;
+ speedChanged: EventSender;
constructor() {
this.initDOMElements();
this.initEvents();
@@ -39,13 +39,13 @@ class View implements IView{
this.$status = this.$controls.find('.js-game__status');
}
initEvents(): void {
- this.tableCellChanged = new EventSender(this);
- this.startEvent = new EventSender(this);
- this.pauseEvent = new EventSender(this);
- this.clearEvent = new EventSender(this);
- this.widthChanged = new EventSender(this);
- this.heightChanged = new EventSender(this);
- this.speedChanged = new EventSender(this);
+ this.tableCellChanged = new EventSender(this);
+ this.started = new EventSender(this);
+ this.paused = new EventSender(this);
+ this.cleared = new EventSender(this);
+ this.widthChanged = new EventSender(this);
+ this.heightChanged = new EventSender(this);
+ this.speedChanged = new EventSender(this);
}
initHandlers(): void {
this.$table.on('click.view', 'td', ({ target }) => {
@@ -54,25 +54,25 @@ class View implements IView{
this.tableCellChanged.notify({ row, cell });
});
this.$buttonStart.on('click.view', () => {
- this.startEvent.notify({});
+ this.started.notify(null);
});
this.$buttonPause.on('click.view', () => {
- this.pauseEvent.notify({});
+ this.paused.notify(null);
});
this.$buttonClear.on('click.view', () => {
- this.clearEvent.notify({});
+ this.cleared.notify(null);
});
this.$sliderSpeed.on('change.view', ({ target }) => {
const value: number = Number($(target).val());
- this.speedChanged.notify({ value });
+ this.speedChanged.notify(value);
});
this.$sliderWidth.on('change.view', ({ target }) => {
const value: number = Number($(target).val());
- this.widthChanged.notify({ value });
+ this.widthChanged.notify(value);
});
this.$sliderHeight.on('change.view', ({ target }) => {
const value: number = Number($(target).val());
- this.heightChanged.notify({ value });
+ this.heightChanged.notify(value);
});
}
setButtons(running: boolean): void {
diff --git a/frontend/scripts/convertRemToPixels.js b/frontend/scripts/convertRemToPixels.js
deleted file mode 100644
index c3d9325..0000000
--- a/frontend/scripts/convertRemToPixels.js
+++ /dev/null
@@ -1,4 +0,0 @@
-const convertRemToPixels = function convertRemToPixels(rem) {
- return rem * parseFloat(getComputedStyle(document.documentElement).fontSize);
-};
-export default convertRemToPixels;
diff --git a/frontend/scripts/convertRemToPixels.ts b/frontend/scripts/convertRemToPixels.ts
new file mode 100644
index 0000000..d1c641c
--- /dev/null
+++ b/frontend/scripts/convertRemToPixels.ts
@@ -0,0 +1,3 @@
+const convertRemToPixels = (rem: number): number =>
+ rem * parseFloat(getComputedStyle(document.documentElement).fontSize);
+export default convertRemToPixels;