diff --git a/5/Calendar.html b/5/Calendar.html
new file mode 100644
index 0000000..dc8be21
--- /dev/null
+++ b/5/Calendar.html
@@ -0,0 +1,76 @@
+
+
+
+
+ Календарь
+
+
+
+
+
+
+
+
+
+
+
Фильтрация текущей коллекции
+
+
+
+
+
+ Текущее состояние коллекции
+
+
\ No newline at end of file
diff --git a/5/Collection.js b/5/Collection.js
new file mode 100644
index 0000000..138a148
--- /dev/null
+++ b/5/Collection.js
@@ -0,0 +1,67 @@
+/*jslint plusplus: true, browser: true, devel: true */
+// абстрактная коллекция Collection, представляющая из себя набор объектов Model
+/**
+* @constructor
+* @param {Object} items
+**/
+var Collection = function (items) {
+ "use strict";
+ this.items = [];
+ var keyName;
+ for (keyName in items) {
+ if (items.hasOwnProperty(keyName)) {
+ this.items.push(items[keyName]);
+ }
+ }
+};
+
+/**
+ * @param {Model} model
+ *
+ * @return {Collection}
+ */
+Collection.prototype.add = function (model) {
+ "use strict";
+ this.items.push(model);
+};
+
+/**
+ * @param {Function} selector
+ *
+ * @example
+ * new Collection().filter(function (item) {
+ * return item.get('attendee').indexOf("me") !== -1;
+ * });
+ * @return {Collection}
+ */
+Collection.prototype.filter = function (selector) {
+ "use strict";
+ return new Collection(this.items.filter(selector));
+};
+/**
+ * @param {String} fieldName параметр, по которому происходит сотрировка
+ * @return {Collection}
+ */
+Collection.prototype.sortBy = function (fieldName) {
+ "use strict";
+ var items;
+ if (fieldName === "start") { // сортировка по началу события
+ items = this.items.sort(function (Event1, Event2) {
+ return Event1.start - Event2.start;
+ });
+ }
+ if (fieldName === "length") {//сортировка по длине события
+ items = this.items.sort(function (Event1, Event2) {
+ return (Event1.end - Event1.start) - (Event2.end - Event2.start);
+ });
+ }
+ if (fieldName === "rating") {//сортировка по рейтингу события
+ items = this.items.sort(function (Event1, Event2) {
+ return Event1.rating - Event2.rating;
+ }).reverse();
+ }
+ if (fieldName === "") {
+ items = this.items;
+ }
+ return new Collection(items);
+};
diff --git a/5/CreateCalendar.js b/5/CreateCalendar.js
new file mode 100644
index 0000000..ae6ac4c
--- /dev/null
+++ b/5/CreateCalendar.js
@@ -0,0 +1,77 @@
+/*jslint plusplus: true, browser: true, devel: true */
+var currentEvents = new Events();
+function WriteCalendar() {
+ "use strict";
+ var filterEvents = currentEvents,
+ filter1,
+ filter2,
+ bool,
+ s,
+ res;
+
+ filter1 = document.querySelector('input[class="filter1"]:checked');
+ filter2 = document.querySelector('input[class="filter2"]:checked');
+ bool = false; // флажок. если =true, выдаем отфильтрованную коллекцию. иначе - всю.
+ if (filter1 !== null && filter1.value === "on") {
+ filterEvents = currentEvents.findFutureEvents();
+ bool = !bool;
+ }
+ if (filter2 !== null && filter2.value === "on") {
+ filterEvents = currentEvents.findPastEvents();
+ bool = !bool;
+ }
+
+ s = "";
+ if (document.querySelector('input[name="sort"]:checked') !== null) {
+ s = document.querySelector('input[name="sort"]:checked').value;
+ }
+
+ if (bool) {
+ res = new Events(filterEvents.sortBy(s).items);
+ } else {
+ res = new Events(currentEvents.sortBy(s).items);
+ }
+ res.write();
+}
+
+function CreateCalendar() {
+ "use strict";
+ var s = (document.getElementsByName("start_date")[0]).value,// строка даты
+ st = (document.getElementsByName("start_time")[0]).value, // строка времени
+ startEv = s + " " + st + ":00",
+ endEv,
+ element;
+
+ s = (document.getElementsByName("end_date")[0]).value;
+ st = (document.getElementsByName("end_time")[0]).value;
+ endEv = s + " " + st + ":00";
+
+ element = new Event({
+ start: new Date(startEv),
+ end: new Date(endEv),
+ name: (document.getElementsByName("New_Event")[0]).value,
+ place: (document.getElementsByName("plase_event")[0]).value,
+ rating: parseFloat((document.getElementsByName("rating_event")[0]).value[0]),
+ comment: (document.getElementsByName("comment_event")[0]).value,
+ link: (document.getElementsByName("link_event")[0]).value
+ });
+ element.validate();
+ currentEvents.add(element);
+
+ WriteCalendar();
+}
+
+var addListener = function () {
+ "use strict";
+ var button = document.getElementsByName("add_event")[0],
+ filter = document.getElementsByName("filter"),
+ sort = document.getElementsByName("sort"),
+ i;
+ button.addEventListener('click', CreateCalendar);
+ for (i = 0; i < filter.length; i++) {
+ filter[i].addEventListener('change', WriteCalendar);
+ }
+ for (i = 0; i < sort.length; i++) {
+ sort[i].addEventListener('change', WriteCalendar);
+ }
+};
\ No newline at end of file
diff --git a/5/Event.js b/5/Event.js
new file mode 100644
index 0000000..3b4d514
--- /dev/null
+++ b/5/Event.js
@@ -0,0 +1,104 @@
+/*jslint plusplus: true, browser: true, devel: true */
+
+function datatype(data) {// возвращает true, если data имеет тип дата и она корректна
+ "use strict";
+ if (typeof data === 'undefined') {
+ return false;
+ }
+ if (!data.getTime) {
+ return false;
+ }
+ if ('Invalid Date' === data) {
+ return false;
+ }
+ return true;
+}
+
+function ratingtype(rating) {// возвращает true, если rating - число от 0 до 5
+ "use strict";
+ if (typeof rating !== 'number') {
+ return false;
+ }
+ if (rating > 5 || rating < 0) {
+ return false;
+ }
+ return true;
+}
+
+function inherits(Constructor, SuperConstructor) {
+ "use strict";
+ var F = function () {};
+
+ F.prototype = SuperConstructor.prototype;
+
+ Constructor.prototype = new F();
+}
+
+
+// наследуем от Абстракнтого конструктора Model объект Event
+var Event = function (data) {
+ "use strict";
+ Model.apply(this, arguments);
+};
+inherits(Event, Model);
+
+Event.prototype.validate = function () {//проверяет корректность переданных данных.
+ "use strict";
+ if (!datatype(this.start)) {
+ throw new Error(this.start + " не является датой!");
+ }
+ if (!datatype(this.end)) {
+ throw new Error(this.end + " не является датой!");
+ }
+ if (this.start.getTime() - this.end.getTime() > 0) {
+ throw new Error("некорректное событие: не может закончиться раньше, чем начаться!!!");
+ }
+ if (!ratingtype(this.rating)) {
+ throw new Error("введите рейтинг от 0 до 5");
+ }
+};
+
+Event.prototype.createSection = function () {
+ "use strict";
+ var el, line, clone1, clone2, clone3, clone4, clone5, clone6, clone7;
+ el = document.createElement('section');
+ line = document.createElement('p');
+ line.textContent = "Событие: " + this.name;
+ el.appendChild(line);
+
+ clone1 = line.cloneNode(true);
+ clone1.textContent = "Начало: " + this.start;
+ el.appendChild(clone1);
+
+ clone2 = line.cloneNode(true);
+ clone2.textContent = "Конец: " + this.end;
+ el.appendChild(clone2);
+
+ clone3 = line.cloneNode(true);
+ clone3.textContent = "Продолжительность: " + hours(this.end - this.start);
+ el.appendChild(clone3);
+
+ clone4 = line.cloneNode(true);
+ clone4.textContent = "Рейтинг: " + this.rating;
+ el.appendChild(clone4);
+
+ if (this.place !== '') {
+ clone5 = line.cloneNode(true);
+ clone5.textContent = "Место: " + this.place;
+ el.appendChild(clone5);
+ }
+
+ if (this.comment !== '') {
+ clone6 = line.cloneNode(true);
+ clone6.textContent = "Комментарий: " + this.comment;
+ el.appendChild(clone6);
+ }
+
+ if (this.link !== '') {
+ clone7 = line.cloneNode(true);
+ clone7.textContent = "Ссылка: " + this.link;
+ el.appendChild(clone7);
+ }
+ el.appendChild(document.createElement('br'));
+ return el;
+};
\ No newline at end of file
diff --git a/5/Events.js b/5/Events.js
new file mode 100644
index 0000000..8b67bf2
--- /dev/null
+++ b/5/Events.js
@@ -0,0 +1,98 @@
+/*jslint plusplus: true, browser: true, devel: true */
+
+
+function getRandomInt(min, max) {//Случайное целое число между min и max
+ "use strict";
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+}
+
+var today = new Date();
+
+function addDay(n) {// прибавляет к текущей дате n дней
+ "use strict";
+ return new Date(today.getTime() + (86400000 * n));
+}
+function nDay(n) {// возвращает n-ый день от текущей даты в 00часов 00минут
+ "use strict";
+ var Day, a, b;
+ Day = addDay(n);
+ a = Day.getTime();
+ b = Day.getMilliseconds() + (Day.getHours() * 3600000) + (Day.getMinutes() * 60000) + (Day.getSeconds() * 1000);
+ return new Date(a - b);
+}
+function hours(milis) {// переводит миллисекунда в часы. Возвращает строку
+ "use strict";
+ var hour, minute, s;
+ hour = Math.floor(milis / 3600000);
+ minute = Math.floor((milis - (hour * 3600000)) / 60000);
+ s = hour + "ч " + minute + "мин";
+ return s;
+}
+var week = addDay(7);
+var maxdate = addDay(31);
+var mindate = addDay(-31);
+
+
+// наследуем коллекцию событий Events от абстрактной коллекции Collection
+var Events = function (items) {
+ "use strict";
+ Collection.apply(this, arguments);
+};
+inherits(Events, Collection);
+
+Events.prototype.write = function () {//выводит на экран все элементы коллекции
+ "use strict";
+ var el = document.getElementsByTagName('section')[0];
+ while (typeof el !== 'undefined') {
+ document.body.removeChild(el);
+ el = document.getElementsByTagName('section')[0];
+ }
+
+ var fragment = document.createDocumentFragment('section'); // фрагмент новых элементов
+
+ this.items.forEach(function (NewEvent) {
+ fragment.appendChild(NewEvent.createSection());
+ });
+ document.body.appendChild(fragment);
+};
+
+/**
+ * показывает все будующие события
+ * @return {Events}
+ */
+Events.prototype.findFutureEvents = function () {
+ "use strict";
+ return new Events((this.filter(function (NewEvent) {return (NewEvent.start > today); })).items);
+};
+/**
+ * показывает все прошедшие события
+ * @return {Events}
+ */
+Events.prototype.findPastEvents = function () {
+ "use strict";
+ return new Events((this.filter(function (NewEvent) {return (NewEvent.start < today); })).items);
+};
+/**
+ * сортировка по началу события
+ * @return {Events}
+ */
+Events.prototype.sortByStart = function () {
+ "use strict";
+ return new Events((this.sortBy("start")).items);
+};
+/**
+ * сортировка по продолжительности события
+ * @return {Events}
+ */
+Events.prototype.sortByLength = function () {
+ "use strict";
+ return new Events((this.sortBy("length")).items);
+};
+/**
+ * сортировка по рейтингу события
+ * @return {Events}
+ */
+Events.prototype.sortByRating = function () {
+ "use strict";
+ return new Events((this.sortBy("rating")).items);
+};
diff --git a/5/Model.js b/5/Model.js
new file mode 100644
index 0000000..411d740
--- /dev/null
+++ b/5/Model.js
@@ -0,0 +1,49 @@
+/*jslint plusplus: true, browser: true, devel: true */
+
+/**
+* Абстрактный конструктор Model
+*
+* @constructor
+* @param {Object} data
+**/
+
+var Model = function (data) {
+ "use strict";
+ var keyName;
+ for (keyName in data) {
+ if (data.hasOwnProperty(keyName)) {
+ this[keyName] = data[keyName];
+ }
+ }
+};
+/**
+ * @param {Object} attributes
+ *
+ * @example
+ * item.set({title: "March 20", content: "In his eyes she eclipses..."});
+ */
+
+Model.prototype.set = function (attributes) {
+ "use strict";
+ var keyName;
+ for (keyName in attributes) {
+ if (attributes.hasOwnProperty(keyName)) {
+ this[keyName] = attributes[keyName];
+ }
+ }
+};
+/**
+ * возвращает аттрибут объекта, если это его собственное свойсово
+ * @param {String} attribute атрибуты объекта, которые получаем
+ */
+
+Model.prototype.get = function (attribute) {
+ "use strict";
+ if (this.hasOwnProperty(attribute)) {
+ return this[attribute];
+ }
+};
+/**
+ * @param {Object} attributes
+ */
+Model.prototype.validate = function (attributes) {"use strict"; throw new Error('this is Abstract method'); };
\ No newline at end of file
diff --git a/5/choose.css b/5/choose.css
new file mode 100644
index 0000000..c7e9fd8
--- /dev/null
+++ b/5/choose.css
@@ -0,0 +1,16 @@
+
+label {
+ display: block;
+ }
+form label input {
+ position: absolute;
+ left: 300px;
+ }
+form label select {
+ position: absolute;
+ left: 300px;
+ }
+form label textarea {
+ position: absolute;
+ left: 300px;
+ }