diff --git a/Calendar.html b/Calendar.html
new file mode 100644
index 0000000..2090a39
--- /dev/null
+++ b/Calendar.html
@@ -0,0 +1,80 @@
+
+
+
+
+ Календарь
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Фильтрация текущей коллекции
+
+
+
+
+
+ Текущее состояние коллекции
+
+
\ No newline at end of file
diff --git a/Collection.js b/Collection.js
new file mode 100644
index 0000000..d4709d0
--- /dev/null
+++ b/Collection.js
@@ -0,0 +1,84 @@
+/*jslint plusplus: true, browser: true, devel: true */
+// абстрактная коллекция Collection, представляющая из себя набор объектов Model
+/**
+* @constructor
+* @param {Object} items
+**/
+var Collection = function (items) {
+ "use strict";
+ this.items = [];
+ this.check = true;// флажок. равен false, если читаем сохраненные данные из файла. Иначе - true
+ 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);
+ if (this.check === true) {
+ this.sendCurrentState();
+ }
+};
+
+/**
+ * @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);
+};
+
+Collection.prototype.serialise = function () {// сериализует данные коллекции в JSON
+ "use strict";
+ return JSON.stringify(this.items);
+};
+
+Collection.prototype.sendCurrentState = function (item) {
+ "use strict";
+ var data = this.serialise();
+
+ // POST запрос
+ $.post('current-event.json', data);
+};
\ No newline at end of file
diff --git a/CreateCalendar.js b/CreateCalendar.js
new file mode 100644
index 0000000..2d14d39
--- /dev/null
+++ b/CreateCalendar.js
@@ -0,0 +1,97 @@
+/*jslint plusplus: true, browser: true, devel: true */
+var currentEvents = new Events();
+
+$.get('current-event.json', null, function (data, textStatus, jqXHR) {
+ "use strict";
+ if (textStatus === "success") {
+ var newEvents = JSON.parse(jqXHR.responseText),
+ newEvent,
+ n = newEvents.length,
+ i;
+ currentEvents.check = false;
+ for (i = 0; i < n; i++) {
+ newEvent = new Event(newEvents[i]);
+ currentEvents.add(newEvent);
+ }
+ WriteCalendar();
+ currentEvents.check = true;
+ }
+});
+
+function WriteCalendar() {
+ "use strict";
+ var filterEvents = currentEvents,
+ filter1,
+ filter2,
+ $sort,
+ bool,
+ sortBy,
+ res;
+
+ filter1 = $(".filter1").prop("checked");
+ filter2 = $(".filter2").prop("checked");
+ bool = false; // флажок. если =true, выдаем отфильтрованную коллекцию. иначе - всю.
+ if (filter1 === true) {
+ filterEvents = currentEvents.findFutureEvents();
+ bool = !bool;
+ }
+ if (filter2 === true) {
+ filterEvents = currentEvents.findPastEvents();
+ bool = !bool;
+ }
+
+ sortBy = "";
+ $sort = $(".filterCollection").find('[name="sort"]');
+ $sort.each(function (index, element) {
+ if ($(element).prop("checked") === true) {
+ sortBy = $(element).val();
+ }
+ });
+
+ if (bool) {
+ res = new Events(filterEvents.sortBy(sortBy).items);
+ } else {
+ res = new Events(currentEvents.sortBy(sortBy).items);
+ }
+ res.write();
+}
+
+function CreateCalendar() {
+ "use strict";
+ var date = $(".start_date").val(),// строка даты
+ time = $(".start_time").val(), // строка времени
+ startEv = date + "T" + time + ":00",
+ endEv,
+ element;
+
+ date = $(".end_date").val();
+ time = $(".end_time").val();
+ endEv = date + "T" + time + ":00";
+ element = new Event({
+ start: startEv,
+ end: endEv,
+ name: $(".New_Event").val(),
+ place: $(".plase_event").val(),
+ rating: parseFloat($(".rating_event").val().charAt(0)),
+ comment: $(".comment_event").val(),
+ link: $(".link_event").val()
+ });
+ element.validate();
+ currentEvents.add(element);
+
+ WriteCalendar();
+}
+$(document).ready(function () {
+ "use strict";
+ var $button = $(".add_event"),
+ $filter = $(".filterCollection").find('[name="filter"]'),
+ $sort = $(".filterCollection").find('[name="sort"]'),
+ i;
+ $button.click(CreateCalendar);
+ $filter.each(function (index, element) {
+ $(element).change(WriteCalendar);
+ });
+ $sort.each(function (index, element) {
+ $(element).change(WriteCalendar);
+ });
+});
\ No newline at end of file
diff --git a/Event.js b/Event.js
new file mode 100644
index 0000000..04b8258
--- /dev/null
+++ b/Event.js
@@ -0,0 +1,70 @@
+/*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");
+ }
+};
+
+$.template("eventTemplate", "Событие: ${Name}
Начало: ${Start}
Конец: ${End}
Продолжительность: ${Length}
Рейтинг: ${Rating}
Место: ${Place}
Комментарий: ${Comment}
Сcылка: ${Link}
");
+
+Event.prototype.createSection = function () {
+ "use strict";
+ var $el,
+ event_temp = [{Name: this.name, Start: this.start, End: this.end, Length: hours(this.end - this.start), Rating: this.rating, Place: this.place, Comment: this.comment, Link: this.link}];
+ $el = $('');
+ $.tmpl("eventTemplate", event_temp).appendTo($el);
+ return $el;
+};
\ No newline at end of file
diff --git a/Events.js b/Events.js
new file mode 100644
index 0000000..e6aaf0a
--- /dev/null
+++ b/Events.js
@@ -0,0 +1,94 @@
+/*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";
+
+ $("section").remove();
+
+ var $fragment = $(''); // фрагмент новых элементов
+ this.items.forEach(function (NewEvent) {
+ $fragment.append(NewEvent.createSection());
+ });
+ $fragment.appendTo(document.body);
+};
+
+/**
+ * показывает все будующие события
+ * @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/Model.js b/Model.js
new file mode 100644
index 0000000..b9f6cb8
--- /dev/null
+++ b/Model.js
@@ -0,0 +1,53 @@
+/*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)) {
+ if (keyName === "start" || keyName === "end") {
+ this[keyName] = new Date(data[keyName]);
+ } else {
+ 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/choose.css b/choose.css
new file mode 100644
index 0000000..c7e9fd8
--- /dev/null
+++ b/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;
+ }
diff --git a/current-event.json b/current-event.json
new file mode 100644
index 0000000..b0bc010
--- /dev/null
+++ b/current-event.json
@@ -0,0 +1 @@
+[{"name":"pewpew","start":"2012-11-07T10:18:39.207Z","end":"2012-11-07T10:18:39.207Z","rating":1}]
\ No newline at end of file
diff --git a/es5-shim.js b/es5-shim.js
new file mode 100644
index 0000000..3107ec4
--- /dev/null
+++ b/es5-shim.js
@@ -0,0 +1,981 @@
+// Copyright 2009-2012 by contributors, MIT License
+// vim: ts=4 sts=4 sw=4 expandtab
+
+// Module systems magic dance
+(function (definition) {
+ // RequireJS
+ if (typeof define == "function") {
+ define(definition);
+ // YUI3
+ } else if (typeof YUI == "function") {
+ YUI.add("es5", definition);
+ // CommonJS and