diff --git a/build/css/ox.ui.css b/build/css/ox.ui.css index dbac9d51..eca5341a 100644 --- a/build/css/ox.ui.css +++ b/build/css/ox.ui.css @@ -102,6 +102,68 @@ Bars margin: 4px 0 0 4px; } +/* +================================================================================ +Calendar +================================================================================ +*/ + +.OxCalendar { + position: absolute; +} + +.OxCalendar > .OxCalendarContainer { + position: absolute; + left: 0; + right: 0; + overflow: hidden; +} + +.OxCalendar .OxLine { + position: absolute; +} + +.OxCalendar .OxDate { + position: absolute; + height: 16px; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + cursor: pointer; +} +.OxCalendar .OxLine:nth-child(even) .OxDate { + background-color: rgb(255, 0, 0); +} +.OxCalendar .OxLine:nth-child(odd) .OxDate { + background-color: rgb(255, 64, 64); +} +.OxCalendar .OxTimeline { + position: absolute; + height: 16px; + //overflow: hidden; +} + +.OxCalendar .OxTimeline .OxDate { + position: absolute; + border-radius: 0; + cursor: ew-resize; +} +.OxCalendar .OxOverlay { + position: absolute; + left: 0; + right: 0; + height: 16px; +} +.OxCalendar .OxOverlay div { + position: absolute; + height: 16px; + cursor: ew-resize; +} +.OxCalendar .OxOverlay div:nth-child(odd) { + background-color: rgba(0, 0, 0, 0.333); +} + + /* ================================================================================ Dialog diff --git a/build/css/ox.ui.modern.css b/build/css/ox.ui.modern.css index 59fe1a61..8667e419 100644 --- a/build/css/ox.ui.modern.css +++ b/build/css/ox.ui.modern.css @@ -31,6 +31,22 @@ Bars background-color: rgb(48, 48, 48); } +/* +================================================================================ +Calendar +================================================================================ +*/ + +.OxThemeModern .OxCalendar .OxTimeline > div.even { + background: -moz-linear-gradient(top, rgb(64, 64, 64), rgb(32, 32, 32)); + background: -webkit-gradient(linear, left top, left bottom, from(rgb(64, 64, 64)), to(rgb(32, 32, 32))); +} + +.OxThemeModern .OxCalendar .OxTimeline > div.odd { + background: -moz-linear-gradient(top, rgb(56, 56, 56), rgb(24, 24, 24)); + background: -webkit-gradient(linear, left top, left bottom, from(rgb(56, 56, 56)), to(rgb(24, 24, 24))); +} + /* ================================================================================ Dialog diff --git a/build/js/ox.js b/build/js/ox.js index 5323ea37..2e9dfbf0 100644 --- a/build/js/ox.js +++ b/build/js/ox.js @@ -43,6 +43,9 @@ Ox.MONTHS = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ]; +Ox.SHORT_MONTHS = Ox.MONTHS.map(function(val) { + return val.substr(0, 3); +}); Ox.PREFIXES = ['K', 'M', 'G', 'T', 'P']; Ox.SYMBOLS = { DOLLAR: '\u0024', @@ -77,6 +80,9 @@ Ox.VERSION = '0.1.2'; Ox.WEEKDAYS = [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ]; +Ox.SHORT_WEEKDAYS = Ox.WEEKDAYS.map(function(val) { + return val.substr(0, 3); +}); /* ================================================================================ @@ -491,9 +497,14 @@ Ox.len = function(obj) { return Ox.isObject(obj) ? Ox.values(obj).length : obj.length; }; -Ox.loop = function(num, fn) { - var i; - for (i = 0; i < num; i++) { +Ox.loop = function() { + var length = arguments.length, + fn = arguments[length - 1], + step = length == 4 ? arguments[2] : 1, + stop = arguments[length > 2 ? 1 : 0], + start = length > 2 ? arguments[0] : 0, + i; + for (i = start; i < stop; i += step) { fn(i); } }; @@ -957,6 +968,10 @@ Ox.getDaysInMonth = function(year, month) { //return Ox.DAYS[month - 1] + (month == 2 && Ox.isLeapYear(year)); } +Ox.getDaysInYear = function(year) { + return 365 + Ox.isLeapYear(year); +}; + Ox.getFirstDayOfTheYear = function(date) { /* Decimal weekday of January 1 (0-6, Sunday as first day) @@ -1610,10 +1625,10 @@ Ox.formatDate = function() { ["v", function() {return "%e-%b-%Y";}], ["\\+", function() {return "%a %b %e %H:%M:%S %Z %Y";}], ["A", function(d) {return Ox.WEEKDAYS[(d.getDay() + 6) % 7];}], - ["a", function(d) {return Ox.WEEKDAYS[(d.getDay() + 6) % 7].toString().substr(0, 3);}], + ["a", function(d) {return Ox.SHORT_WEEKDAYS[(d.getDay() + 6) % 7];}], ["B", function(d) {return Ox.MONTHS[d.getMonth()];}], - ["b", function(d) {return Ox.MONTHS[d.getMonth()].toString().substr(0, 3);}], - ["C", function(d) {return d.getFullYear().toString().substr(0, 2);}], + ["b", function(d) {return Ox.SHORT_MONTHS[d.getMonth()];}], + ["C", function(d) {return (d.getFullYear() / 100).toString();}], ["d", function(d) {return Ox.pad(d.getDate(), 2);}], ["e", function(d) {return Ox.pad(d.getDate(), 2, " ");}], ["G", function(d) {return Ox.getISOYear(d);}], @@ -1737,6 +1752,38 @@ Ox.formatNumber = function(num, dec) { return (num < 0 ? '-' : '') + spl.join('.'); }; +Ox.formatOrdinal = function(num) { + /* + >>> Ox.formatOrdinal(1) + "1st" + >>> Ox.formatOrdinal(2) + "2nd" + >>> Ox.formatOrdinal(3) + "3rd" + >>> Ox.formatOrdinal(4) + "4th" + >>> Ox.formatOrdinal(11) + "11th" + >>> Ox.formatOrdinal(12) + "12th" + >>> Ox.formatOrdinal(13) + "13th" + */ + var str = num.toString(), + end = str[str.length - 1], + ten = str.length > 1 && str[str.length - 2] == '1'; + if (end == '1' && !ten) { + str += 'st'; + } else if (end == '2' && !ten) { + str += 'nd'; + } else if (end == '3' && !ten) { + str += 'rd'; + } else { + str += 'th'; + } + return str; +}; + Ox.formatPercent = function(num, total, dec) { /* >>> Ox.formatPercent(1, 1000, 2) @@ -2245,6 +2292,17 @@ Ox.log = function(num, base) { return Math.log(num) / Math.log(base || Math.E); }; +Ox.mod = function(num, by) { + /* + >>> Ox.mod(11, 10) + 1 + >>> Ox.mod(-11, 10) + 9 + */ + var mod = num % by; + return mod >= 0 ? mod : mod + by; +}; + Ox.rad = function(deg) { /* >>> Ox.rad(360) diff --git a/build/js/ox.ui.js b/build/js/ox.ui.js index 39cefdb3..2aeb2d05 100644 --- a/build/js/ox.ui.js +++ b/build/js/ox.ui.js @@ -9858,7 +9858,7 @@ requires function initMap() { var mapBounds; - updateFormElements() + updateFormElements(); self.elevationService = new google.maps.ElevationService(); self.geocoder = new google.maps.Geocoder(); @@ -10760,16 +10760,17 @@ requires }; - /** - options - height image height (px) - places array of either names (''), points ([0, 0]), - or objects ({name, point, highlight}) - type map type ('hybrid', 'roadmap', 'satellite', 'terrain') - width image width (px) - */ Ox.MapImage = function(options, self) { + /** + options + height image height (px) + places array of either names (''), points ([0, 0]), + or objects ({name, point, highlight}) + type map type ('hybrid', 'roadmap', 'satellite', 'terrain') + width image width (px) + */ + var self = self || {}, that = new Ox.Element('img', self) .defaults({ @@ -10827,6 +10828,426 @@ requires }; + Ox.Calendar = function(options, self) { + + self = self || {}; + var that = new Ox.Element({}, self) + .defaults({ + date: new Date(), + dates: [], + height: 512, + range: [100, 5101], + width: 512, + zoom: 5 + }) + .options(options || {}) + .addClass('OxCalendar') + .css({ + width: self.options.width + 'px', + height: self.options.height + 'px' + }); + + self.overlayWidths = [Math.round(self.options.width / 16)]; + self.overlayWidths = [ + Math.floor((self.options.width - self.overlayWidths[0]) / 2), + self.overlayWidths[0], + Math.ceil((self.options.width - self.overlayWidths[0]) / 2), + ]; + self.units = [ + { + id: 'century', + seconds: 36524 * 86400, + date: function(i) { + return new Date((i + 19) + '00'); + }, + name: function(i) { + return Ox.formatOrdinal(i + 20) + ' century'; + }, + value: function(date) { + return Math.floor(date.getFullYear() / 100) - 19; + } + }, + { + id: 'decade', + seconds: 3652 * 86400, + date: function(i) { + return (i + 197) + '0' + }, + name: function(i) { + return (i + 197) + '0s' + }, + value: function(date) { + return Math.floor(date.getFullYear() / 10) - 197; + } + }, + { + id: 'year', + seconds: 365 * 86400, + date: function(i) { + return (i + 1970) + ''; + }, + name: function(i) { + return (i + 1970) + ''; + }, + value: function(date) { + return date.getFullYear() - 1970; + } + }, + { + id: 'month', + seconds: 28 * 86000, + date: function(i) { + return (Math.floor(i / 12) + 1970) + '-' + (Ox.mod(i, 12) + 1); + }, + name: function(i) { + return Ox.SHORT_MONTHS[Ox.mod(i, 12)] + ' ' + Math.floor(i / 12 + 1970) + }, + value: function(date) { + return (date.getFullYear() - 1970) * 12 + date.getMonth(); + } + }, + { + id: 'day', + seconds: 86400, + date: function(i) { + return i * 86400000; + }, + name: function(i) { + return Ox.formatDate(new Date(i * 86400000), '%a, %b %e, %Y'); + }, + value: function(date) { + return Math.floor(date / 86400000); + } + }, + { + id: 'hour', + seconds: 3600, + date: function(i) { + return i * 3600000; + }, + name: function(i) { + return Ox.formatDate(new Date(i * 3600000), '%b %e, %H:00'); + }, + value: function(date) { + return Math.floor(date / 3600000); + } + }, + { + id: 'minute', + seconds: 60, + date: function(i) { + return i * 60000; + }, + name: function(i) { + return Ox.formatDate(new Date(i * 60000), '%b %e, %H:%M'); + }, + value: function(date) { + return Math.floor(date / 60000); + } + }, + { + id: 'second', + seconds: 1, + date: function(i) { + return i * 1000; + }, + name: function(i) { + return Ox.formatDate(new Date(i * 1000), '%H:%M:%S'); + }, + value: function(date) { + return Math.floor(date / 1000); + } + } + ]; + + self.$container = new Ox.Element() + .addClass('OxCalendarContainer') + .css({ + top: '24px', + bottom: '40px' + }) + .bindEvent({ + dragstart: dragstart, + drag: drag, + dragend: dragend + }) + .appendTo(that); + + self.$content = new Ox.Element() + .addClass('OxCalendarContent') + .appendTo(self.$container) + + self.$scalebar = new Ox.Element() + .addClass('OxTimeline') + .css({ + posision: 'absolute', + }) + .appendTo(self.$content); + + self.$scrollbar = new Ox.Element() + .addClass('OxTimeline') + .css({ + posision: 'absolute', + bottom: '40px' + }) + .appendTo(that); + self.$overlay = new Ox.Element() + .addClass('OxOverlay') + .css({ + bottom: '40px' + }) + .append( + $('