From b29d59cb72a6365c67e3bc384a12f027e499c677 Mon Sep 17 00:00:00 2001 From: mapit_cpw Date: Wed, 10 Apr 2019 11:12:52 +0800 Subject: [PATCH 1/2] added timeScale for scaling the table by factor of 2. eg. timeScale = 2 have range by 30min, timeScale = 4 have range by 15min --- app/scripts/plugin.js | 74 ++++++++++++++++++++++--------------- app/styles/plugin.sass | 4 +- dist/scripts/timetable.js | 2 +- dist/styles/timetablejs.css | 2 +- 4 files changed, 48 insertions(+), 34 deletions(-) diff --git a/app/scripts/plugin.js b/app/scripts/plugin.js index cf31a5c..7f9be80 100644 --- a/app/scripts/plugin.js +++ b/app/scripts/plugin.js @@ -8,6 +8,7 @@ var Timetable = function() { hourEnd: 17 }; this.usingTwelveHour = false; + this.timeScale = 1; this.locations = []; this.events = []; }; @@ -107,21 +108,22 @@ Timetable.Renderer = function(tt) { } } - function prettyFormatHour(hour, usingTwelveHour) { + function prettyFormatHour(hour, minute, usingTwelveHour) { var prettyHour; - if(usingTwelveHour) { - var period = hour >= 12 ? 'PM':'AM'; - prettyHour = ((hour + 11) % 12 + 1) + ':00' + period; - } else { - var prefix = hour < 10 ? '0' : ''; - prettyHour = prefix + hour + ':00'; - } + var prefixHr = hour < 10 ? '0' : ''; + var prefixMn = minute < 10 ? '0' : ''; + if(usingTwelveHour) { + var period = hour >= 12 ? 'PM' : 'AM'; + prettyHour = ((hour + 11) % 12 + 1) + ':' + prefixMn + minute + period; + } else { + return prefixHr + hour + ':' + prefixMn + minute; + } return prettyHour; } Timetable.Renderer.prototype = { draw: function(selector) { - var timetable = this.timetable; + var timetable = this.timetable; function checkContainerPrecondition(container) { if (container === null) { @@ -134,7 +136,7 @@ Timetable.Renderer = function(tt) { appendRowHeaders(asideULNode); } function appendRowHeaders(ulNode) { - for (var k=0; k header @@ -131,7 +131,7 @@ $timetable-background-color: white !default transform-style: preserve-3d ul - display: flex + display: inline-flex height: $timetable-hour-row-height align-items: center diff --git a/dist/scripts/timetable.js b/dist/scripts/timetable.js index 4e45c77..94bb9af 100644 --- a/dist/scripts/timetable.js +++ b/dist/scripts/timetable.js @@ -1 +1 @@ -!function(e,t){"function"==typeof define&&define.amd?define(["exports"],t):t("undefined"!=typeof exports?exports:e.syncscroll={})}(this,function(e){var t="Width",n="Height",o="Top",r="Left",i="scroll",a="client",s=[],c=function(){var e,c,l,u,d,f=document.getElementsByClassName("syncscroll");for(d in s)if(s.hasOwnProperty(d))for(e=0;e=0&&e<24}function r(e,t){return t.indexOf(e)!==-1}function i(e,t){var n=e instanceof Date&&t instanceof Date,o=e=e?t-e:24+t-e}function s(e){for(;e.firstChild;)e.removeChild(e.firstChild)}function c(e,t){var n;if(t){var o=e>=12?"PM":"AM";n=(e+11)%12+1+":00"+o}else{var r=e<10?"0":"";n=r+e+":00"}return n}Timetable.prototype={setScope:function(t,n){if(!e(t,n))throw new RangeError("Timetable scope should consist of (start, end) in whole hours from 0 to 23");return this.scope.hourStart=t,this.scope.hourEnd=n,this},useTwelveHour:function(){this.usingTwelveHour=!0},addLocations:function(e){function t(){return e instanceof Array}var n=this.locations;if(!t())throw new Error("Tried to add locations in wrong format");return e.forEach(function(e){if(r(e,n))throw new Error("Location already exists");n.push(e)}),this},addEvent:function(e,t,n,o,a){if(!r(t,this.locations))throw new Error("Unknown location");if(!i(n,o))throw new Error("Invalid time range: "+JSON.stringify([n,o]));var s="[object Object]"===Object.prototype.toString.call(a);return this.events.push({name:e,location:t,startDate:n,endDate:o,options:s?a:void 0}),this}},Timetable.Renderer.prototype={draw:function(e){function t(e){if(null===e)throw new Error("Timetable container not found")}function n(e){var t=e.appendChild(document.createElement("aside")),n=t.appendChild(document.createElement("ul"));o(n)}function o(e){for(var t=0;t=0&&t<24}function r(t,e){return e.indexOf(t)!==-1}function i(t,e){var n=t instanceof Date&&e instanceof Date,o=t=t?e-t:24+e-t}function c(t){for(;t.firstChild;)t.removeChild(t.firstChild)}function s(t,e,n){var o,r=t<10?"0":"",i=e<10?"0":"";if(!n)return r+t+":"+i+e;var a=t>=12?"PM":"AM";return o=(t+11)%12+1+":"+i+e+a}Timetable.prototype={setScope:function(e,n){if(!t(e,n))throw new RangeError("Timetable scope should consist of (start, end) in whole hours from 0 to 23");return this.scope.hourStart=e,this.scope.hourEnd=n,this},useTwelveHour:function(){this.usingTwelveHour=!0},addLocations:function(t){function e(){return t instanceof Array}var n=this.locations;if(!e())throw new Error("Tried to add locations in wrong format");return t.forEach(function(t){if(r(t,n))throw new Error("Location already exists");n.push(t)}),this},addEvent:function(t,e,n,o,a){if(!r(e,this.locations))throw new Error("Unknown location");if(!i(n,o))throw new Error("Invalid time range: "+JSON.stringify([n,o]));var c="[object Object]"===Object.prototype.toString.call(a);return this.events.push({name:t,location:e,startDate:n,endDate:o,options:c?a:void 0}),this}},Timetable.Renderer.prototype={draw:function(t){function e(t){if(null===t)throw new Error("Timetable container not found")}function n(t){var e=t.appendChild(document.createElement("aside")),n=e.appendChild(document.createElement("ul"));o(n)}function o(t){for(var e=0;easide{flex:none;max-width:30%;padding:0!important;margin-top:46px;border-right:5px solid transparent;position:relative}.timetable>aside li{padding:0 15px;background-color:#efefef;line-height:46px}.timetable>aside li:not(:last-of-type){border-bottom:1px solid #fff}.timetable>aside .row-heading{display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal}.timetable>aside:before{content:"";display:block;background-color:#fff;height:46px;position:relative;margin-top:-46px;top:0}.timetable aside li,.timetable time li{height:46px}.timetable>section{flex:3 0 auto;width:0;padding:0!important}.timetable>section time{display:block;width:100%;overflow-x:scroll;-webkit-overflow-scrolling:touch}.timetable>section>header{position:relative;top:0;z-index:3;width:100%;overflow:hidden;background-color:#fff;transform-style:preserve-3d}.timetable>section>header ul{display:flex;height:46px;align-items:center}.timetable>section>header li{flex:none;display:block;position:relative;width:96px}.timetable>section>header li .time-label{display:block;position:absolute;left:0}.timetable>section>header li:not(:first-of-type) .time-label{transform:translateX(-50%)}.timetable>section>header li:last-of-type{width:0}.timetable>section>header li:last-of-type .time-label{transform:translateX(-100%)}.timetable ul.room-timeline{border-left:none;display:flex;flex-direction:column;align-items:stretch}.timetable ul.room-timeline li{position:relative;background-color:#f4f4f4;height:46px}.timetable ul.room-timeline li:nth-of-type(odd){background-color:#fdfdfd}.timetable ul.room-timeline li:first-of-type{border-top:1px solid #e5e5e5}.timetable ul.room-timeline li:last-of-type{border-bottom:1px solid #e5e5e5}.timetable ul.room-timeline li:not(:last-of-type){border-bottom:none}.timetable ul.room-timeline li:first-child .time-entry{height:44px}.timetable ul.room-timeline li:after,.timetable ul.room-timeline li:before{content:"";position:absolute;z-index:1;left:0;top:0;right:0;bottom:0}.timetable ul.room-timeline li:before{background-image:linear-gradient(90deg,#e5e5e5 1px,transparent 0);background-size:24px auto}.timetable ul.room-timeline li:after{background-image:linear-gradient(90deg,#e5e5e5,#e5e5e5 1px,#f4f4f4 0,#f4f4f4 2px,#e5e5e5 0,#e5e5e5 3px,transparent 0,transparent);background-size:96px auto;background-position:-2px 0}.timetable .time-entry{background-color:#ec6a5e;transition:background-color .2s;height:45px;display:block;position:absolute;z-index:2;padding:0 10px;white-space:normal;overflow:hidden;color:#fff;border:1px solid #e32c1b;transform-style:preserve-3d}.timetable .time-entry small{position:relative;top:50%;transform:translateY(-50%);display:block}.timetable .time-entry:hover{background-color:#e74030} \ No newline at end of file +.timetable{display:flex;align-items:stretch;width:100%;max-width:100%;box-sizing:border-box}.timetable *{box-sizing:inherit}.timetable li,.timetable ul{list-style-type:none;margin:0}.timetable li,.timetable ul{padding:0}.timetable>aside{flex:none;max-width:30%;padding:0!important;margin-top:46px;border-right:5px solid transparent;position:relative}.timetable>aside li{padding:0 15px;background-color:#efefef;line-height:46px}.timetable>aside li:not(:last-of-type){border-bottom:1px solid #fff}.timetable>aside .row-heading{display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal}.timetable>aside:before{content:"";display:block;background-color:#fff;height:46px;position:relative;margin-top:-46px;top:0}.timetable aside li,.timetable time li{height:46px}.timetable>section{flex:3 0 auto;width:0;padding:0!important}.timetable>section time{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.timetable>section>header{position:relative;top:0;z-index:3;width:100%;overflow:hidden;background-color:#fff;transform-style:preserve-3d}.timetable>section>header ul{display:inline-flex;height:46px;align-items:center}.timetable>section>header li{flex:none;display:block;position:relative;width:96px}.timetable>section>header li .time-label{display:block;position:absolute;left:0}.timetable>section>header li:not(:first-of-type) .time-label{transform:translateX(-50%)}.timetable>section>header li:last-of-type{width:0}.timetable>section>header li:last-of-type .time-label{transform:translateX(-100%)}.timetable ul.room-timeline{border-left:none;display:flex;flex-direction:column;align-items:stretch}.timetable ul.room-timeline li{position:relative;background-color:#f4f4f4;height:46px}.timetable ul.room-timeline li:nth-of-type(odd){background-color:#fdfdfd}.timetable ul.room-timeline li:first-of-type{border-top:1px solid #e5e5e5}.timetable ul.room-timeline li:last-of-type{border-bottom:1px solid #e5e5e5}.timetable ul.room-timeline li:not(:last-of-type){border-bottom:none}.timetable ul.room-timeline li:first-child .time-entry{height:44px}.timetable ul.room-timeline li:after,.timetable ul.room-timeline li:before{content:"";position:absolute;z-index:1;left:0;top:0;right:0;bottom:0}.timetable ul.room-timeline li:before{background-image:linear-gradient(90deg,#e5e5e5 1px,transparent 0);background-size:24px auto}.timetable ul.room-timeline li:after{background-image:linear-gradient(90deg,#e5e5e5,#e5e5e5 1px,#f4f4f4 0,#f4f4f4 2px,#e5e5e5 0,#e5e5e5 3px,transparent 0,transparent);background-size:96px auto;background-position:-2px 0}.timetable .time-entry{background-color:#ec6a5e;transition:background-color .2s;height:45px;display:block;position:absolute;z-index:2;padding:0 10px;white-space:normal;overflow:hidden;color:#fff;border:1px solid #e32c1b;transform-style:preserve-3d}.timetable .time-entry small{position:relative;top:50%;transform:translateY(-50%);display:block}.timetable .time-entry:hover{background-color:#e74030} \ No newline at end of file From 3ebb535efded133f7bb632120d30b3163a64ace7 Mon Sep 17 00:00:00 2001 From: mapit_cpw Date: Wed, 10 Apr 2019 11:16:23 +0800 Subject: [PATCH 2/2] updated README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e437b5b..7af5eea 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ Make a timetable object, optionally set the scope in hours (the visible hours in var timetable = new Timetable(); timetable.setScope(9, 17); // optional, only whole hours between 0 and 23 timetable.useTwelveHour(); //optional, displays hours in 12 hour format (1:00PM) +timetable.timeScale = 1; // optional, use factor of 2 (2 = 30min scale, 4 = 15min scale) ``` Add some locations: ```javascript @@ -47,7 +48,7 @@ var options = { id: 4, ticketType: 'VIP' }, - onClick: function(event, timetable, clickEvent) {} // custom click handler, which is passed the event object and full timetable as context + onClick: function(event, timetable, clickEvent) {} // custom click handler, which is passed the event object and full timetable as context }; timetable.addEvent('Jam Session', 'Nile', new Date(2015,7,17,21,15), new Date(2015,7,17,23,30), options); ``` @@ -87,7 +88,7 @@ $timetable-entry-padding: 10px !default $timetable-background-color: white !default ``` -The option `$timetable-use-sticky-header` makes the time indicator stick to the top of the screen while scrolling down, which can be very pleasant with large timetables or on mobile devices. Note that this is not yet widely supported in browsers, although all modern (non-IE) browsers support it. Browsers that don't support it will fall back to a non-sticky header automatically. [More info here](https://caniuse.com/#feat=css-sticky). +The option `$timetable-use-sticky-header` makes the time indicator stick to the top of the screen while scrolling down, which can be very pleasant with large timetables or on mobile devices. Note that this is not yet widely supported in browsers, although all modern (non-IE) browsers support it. Browsers that don't support it will fall back to a non-sticky header automatically. [More info here](https://caniuse.com/#feat=css-sticky). Alternatively you could override the css styles manually.