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