├── images └── glanceyear.png ├── example.html ├── glanceyear.css ├── README.md ├── jquery.glanceyear.min.js └── jquery.glanceyear.js /images/glanceyear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kraigo/glanceyear/HEAD/images/glanceyear.png -------------------------------------------------------------------------------- /example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | Glance Year 12 | 13 | 14 | 15 |
16 |

Glance Year 17 | 18 |

19 |
20 |
21 | 22 |
23 |
24 | Less  25 | 26 | 27 | 28 | 29 |  More 30 |
31 | Calendar with map data entered
32 | 33 |
34 |
35 | 36 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /glanceyear.css: -------------------------------------------------------------------------------- 1 | body { font-family: Arial, serif; } 2 | .glanceyear-container { 3 | border: 1px solid #D8D8D8; 4 | border-radius: 5px; 5 | margin: 0 auto; 6 | max-width: 683px; 7 | } 8 | .glanceyear-header { 9 | position: relative; 10 | background-color: #F5F5F5; 11 | border-bottom: 1px solid #D8D8D8; 12 | border-radius: 5px 5px 0 0; 13 | color: #000; 14 | font-size: 15px; 15 | font-weight: bold; 16 | margin: 0; 17 | padding: 7px 10px; 18 | } 19 | .glanceyear-quantity { 20 | position: absolute; 21 | right: 10px; 22 | top: 10px; 23 | color:#aaa; 24 | font-size: 10px; 25 | } 26 | .glanceyear-content { padding: 10px; } 27 | .glanceyear-text { 28 | color: #aaa; 29 | font-size: 12px; 30 | font-weight: normal; 31 | margin: 0 0; 32 | padding: 0; 33 | } 34 | .glanceyear-summary { color: #aaa; font-size: 12px; margin: 0 10px 10px; } 35 | 36 | .glanceyear-legend { 37 | color: #aaa; 38 | float: right; 39 | font-size: 12px; 40 | text-align: middle; 41 | text-wrap: none; 42 | } 43 | .glanceyear-legend span { display: inline-block; height: 10px; width: 10px; } 44 | 45 | svg rect.day { fill: #eee; shape-rendering: crispedges; } 46 | svg rect.day:hover { stroke: #aaa; stroke-width: 1px; } 47 | svg rect.day[data-count] { fill: #3d9692; } 48 | svg rect.day[data-count='1'] { fill: #c3dbda; } 49 | svg rect.day[data-count='2'] { fill: #5caeaa; } 50 | svg rect.day[data-count='3'] { fill: #277672; } 51 | 52 | svg text { fill: #CCC; font-size: 9px; } 53 | svg text.month { fill: #AAA; } 54 | 55 | .svg-tag { 56 | background-color: rgba(0,0,0,0.8); 57 | border-radius: 3px; 58 | color: #eee; 59 | font-size: 12px; 60 | line-height: 15px; 61 | padding: 5px 15px; 62 | position: absolute; 63 | text-align: center; 64 | } 65 | .svg-tag:after { 66 | border-color: rgba(0,0,0,0.8) transparent transparent transparent; 67 | border-style: solid; 68 | border-width: 5px 5px 0 5px; 69 | bottom: -5px; 70 | content: ""; 71 | height: 0; 72 | left: 50%; 73 | margin-left: -5px; 74 | position: absolute; 75 | width: 0; 76 | } 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | glanceyear 2 | ========== 3 | 4 | JQuery data visualization / Glance Year 5 | 6 | *Need [JQuery](http://jquery.com/download/)* 7 | 8 | [Check live demo](http://codepen.io/Kraigo/full/Hpuyw) 9 | 10 | ![alt tag](https://raw.github.com/kraigo/glanceyear/master/images/glanceyear.png) 11 | 12 | ##### Version 0.4.1 (2014.03.27) 13 | - Added version tag in script file. 14 | 15 | ##### Version 0.4 (2014.11.26) 16 | - New parameter "today"; 17 | - Fix bug with first month. 18 | 19 | ##### Version 0.3 20 | - Every instance fill your own data; 21 | - New parameter "showToday"; 22 | - Fix bug with 54 weeks; 23 | - Added minified script. 24 | 25 | ##### Version 0.2 26 | - rebuild mouseover and mouseleave event and now work faster; 27 | - new event 'eventClick'. 28 | 29 | ### How to Use 30 | ```javascript 31 | var massive = [ 32 | {date: '2014-8-3', value:'1'}, 33 | {date: '2014-8-4', value:'2'}, 34 | {date: '2014-9-3', value:'3'}, 35 | {date: '2014-10-14', value:'2'}, 36 | {date: '2014-10-13', value:'8'}, 37 | {date: '2014-7-3', value:'1'}, 38 | {date: '2014-7-4', value:'2'}, 39 | {date: '2014-7-7', value:'3'}, 40 | {date: '2014-7-14', value:'2'}, 41 | {date: '2014-6-3', value:'1'}, 42 | {date: '2014-6-4', value:'2'}, 43 | {date: '2014-6-5', value:'3'}, 44 | {date: '2014-6-14', value:'2'} 45 | ]; 46 | ``` 47 | 48 | ##### Simple initialization plugin 49 | ```javascript 50 | $('div#js-glanceyear').glanceyear(massive); 51 | ``` 52 | 53 | ##### Initialization the plugin with additional parameters 54 | ```javascript 55 | $('div#js-glanceyear').glanceyear(massive, 56 | { 57 | eventClick: function(e) { $('#debug').html('Date: '+ e.date + ', Count: ' + e.count); }, 58 | months: ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"], 59 | weeks: ['M','T','W','T','F','S', 'S'], 60 | showToday: false, 61 | today: new Date() 62 | }); 63 | ``` 64 | 65 | - **eventClick** - Event, after click on day [Function]; 66 | - **month** - name of month [Array with string]; 67 | - **weeks** - name of weeks [Array with string]; 68 | - **showToday** - display present day or not [Boolean]; 69 | - **today** - change current date [Date]. -------------------------------------------------------------------------------- /jquery.glanceyear.min.js: -------------------------------------------------------------------------------- 1 | !function(a){a.fn.glanceyear=function(b,c){function w(a,b){var c=document.createElementNS("http://www.w3.org/2000/svg",a);for(var d in b)c.setAttribute(d,b[d]);return c}function x(b){var c=0;for(var f in b)d.find('rect.day[data-date="'+b[f].date+'"]').attr("data-count",b[f].value),c+=parseInt(b[f].value);a(e.targetQuantity).text(b.length+" days, "+c+" scores")}function y(a){return e.months[a]}function z(a){return e.weeks[a]}function A(a){return y(a.getMonth())+" "+a.getDate()+", "+a.getFullYear()}function B(a){return 32-new Date(a.getFullYear(),a.getMonth(),32).getDate()}for(var j,d=a(this),e=a.extend({eventClick:function(a){alert("Date: "+a.date+", Count:"+a.count)},months:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],weeks:["M","T","W","T","F","S","S"],targetQuantity:".glanceyear-quantity",tagId:"glanceyear-svgTag",showToday:!1,today:new Date},c),f=w("svg",{width:663,height:99}),g=w("g",{transform:"translate(15, 15)"}),h=a("
").addClass("svg-tag").attr("id",e.tagId).appendTo(a("body")).hide(),i=366,k=0;54>k;k++){var l=w("g",{transform:"translate("+12*k+",0)"}),m=new Date;m.setMonth(e.today.getMonth()),m.setFullYear(e.today.getFullYear()),m.setDate(e.today.getDate()-i-1);for(var n=B(m)-m.getDate(),o=m.getDay();7>o;o++){var p=new Date;if(p.setMonth(e.today.getMonth()),p.setFullYear(e.today.getFullYear()),p.setDate(e.today.getDate()-i),p.getMonth()!=j&&52>k&&o>3&&n>7){var q=w("text",{x:12*k,y:"-6","class":"month"});q.textContent=y(p.getMonth()),g.appendChild(q),j=p.getMonth()}if(i--,i>=0||e.showToday&&i>=-1){var r=w("rect",{"class":"day",width:"10px",height:"10px","data-date":p.getFullYear()+"-"+(p.getMonth()+1)+"-"+p.getDate(),y:12*o});r.onmouseover=function(){var b=a(this).attr("data-date").split("-"),c=new Date(b[0],b[1]-1,b[2]),d=A(c),e=a(this).attr("data-count"),f=a(this).attr("data-count");e=f?f>1?a(this).attr("data-count")+" scores":a(this).attr("data-count")+" score":"No scores",h.html(""+e+" on "+d).show().css({left:a(this).offset().left-h.outerWidth()/2+5,top:a(this).offset().top-33})},r.onmouseleave=function(){h.text("").hide()},r.onclick=function(){e.eventClick({date:a(this).attr("data-date"),count:a(this).attr("data-count")||0})},l.appendChild(r)}}g.appendChild(l)}var s=w("text",{x:"-14",y:"8"});s.textContent=z(0),g.appendChild(s);var t=w("text",{x:"-14",y:"32"});t.textContent=z(2),g.appendChild(t);var u=w("text",{x:"-14",y:"56"});u.textContent=z(4),g.appendChild(u);var v=w("text",{x:"-14",y:"80"});v.textContent=z(6),g.appendChild(v),f.appendChild(g),d.append(f),x(b)}}(jQuery); -------------------------------------------------------------------------------- /jquery.glanceyear.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Glance Year, version 0.4.1 3 | * https://github.com/Kraigo/glanceyear 4 | * Author: Kraigo 5 | */ 6 | 7 | (function($) { 8 | $.fn.glanceyear = function(massive, options) { 9 | 10 | var $_this = $(this); 11 | 12 | var settings = $.extend({ 13 | eventClick: function(e) { alert('Date: ' + e.date + ', Count:' + e.count); }, 14 | months: ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"], 15 | weeks: ['M','T','W','T','F','S', 'S'], 16 | targetQuantity: '.glanceyear-quantity', 17 | tagId: 'glanceyear-svgTag', 18 | showToday: false, 19 | today: new Date() 20 | }, options ); 21 | 22 | var svgElement = createElementSvg('svg', {'width': 54*12+15, 'height': 7*12+15 } ); 23 | 24 | var gElementContainer = createElementSvg('g', {'transform': 'translate(15, 15)'} ); 25 | 26 | var $_tag = $('
') 27 | .addClass('svg-tag') 28 | .attr('id', settings.tagId) 29 | .appendTo( $('body') ) 30 | .hide(); 31 | 32 | var dayCount = 366; 33 | var monthCount; 34 | 35 | 36 | //Weeks 37 | for (var i=0; i<54; i++) { 38 | var gElement = createElementSvg('g', {'transform': 'translate('+(12*i)+',0)'} ); 39 | var firstDate = new Date(); 40 | firstDate.setMonth(settings.today.getMonth()); 41 | firstDate.setFullYear(settings.today.getFullYear()); 42 | firstDate.setDate(settings.today.getDate() - dayCount-1); 43 | 44 | var daysLeft = daysInMonth(firstDate) - firstDate.getDate(); 45 | 46 | // Days in week 47 | for (var j=firstDate.getDay(); j<7 ; j++) { 48 | 49 | var rectDate = new Date(); 50 | rectDate.setMonth(settings.today.getMonth()); 51 | rectDate.setFullYear(settings.today.getFullYear()); 52 | rectDate.setDate(settings.today.getDate() - dayCount); 53 | 54 | if ( rectDate.getMonth() != monthCount && i < 52 && j > 3 && daysLeft > 7) { 55 | //new Month 56 | var textMonth = createElementSvg('text', {'x': 12*i, 'y':'-6', 'class':'month'} ); 57 | textMonth.textContent = getNameMonth(rectDate.getMonth()); 58 | gElementContainer.appendChild(textMonth); 59 | monthCount = rectDate.getMonth(); 60 | } 61 | 62 | dayCount--; 63 | if (dayCount>=0 || (settings.showToday && dayCount>=-1)) { 64 | // Day-obj factory 65 | 66 | var rectElement = createElementSvg('rect', { 67 | 'class': 'day', 68 | 'width': '10px', 69 | 'height': '10px', 70 | 'data-date': rectDate.getFullYear()+'-'+(rectDate.getMonth()+1)+'-'+rectDate.getDate(), 71 | 'y': 12*j 72 | }); 73 | 74 | rectElement.onmouseover = function() { 75 | var dateString = $(this).attr('data-date').split('-'); 76 | var date = new Date(dateString[0], dateString[1]-1, dateString[2]); 77 | 78 | var tagDate = getBeautyDate(date); 79 | var tagCount = $(this).attr('data-count'); 80 | var tagCountData = $(this).attr('data-count'); 81 | 82 | if (tagCountData) { 83 | if (tagCountData > 1 ) 84 | tagCount = $(this).attr('data-count')+' scores'; 85 | else 86 | tagCount = $(this).attr('data-count')+' score'; 87 | } else { 88 | tagCount = 'No scores'; 89 | } 90 | 91 | $_tag.html( '' + tagCount + ' on ' + tagDate) 92 | .show() 93 | .css({ 94 | 'left': $(this).offset().left - $_tag.outerWidth()/2+5, 95 | 'top': $(this).offset().top-33 96 | }); 97 | }; 98 | 99 | rectElement.onmouseleave = function() { 100 | $_tag.text('').hide(); 101 | } 102 | 103 | rectElement.onclick = function() { 104 | settings.eventClick( 105 | { 106 | date: $(this).attr('data-date'), 107 | count: $(this).attr('data-count') || 0 108 | } 109 | ); 110 | 111 | } 112 | 113 | gElement.appendChild(rectElement); 114 | } 115 | } 116 | 117 | gElementContainer.appendChild(gElement); 118 | } 119 | var textM = createElementSvg('text', {'x':'-14', 'y':'8'} ); 120 | textM.textContent = getNameWeek(0); 121 | gElementContainer.appendChild(textM); 122 | var textW = createElementSvg('text', {'x':'-14', 'y':'32'} ); 123 | textW.textContent = getNameWeek(2); 124 | gElementContainer.appendChild(textW); 125 | var textF = createElementSvg('text', {'x':'-14', 'y':'56'} ); 126 | textF.textContent = getNameWeek(4); 127 | gElementContainer.appendChild(textF); 128 | var textS = createElementSvg('text', {'x':'-14', 'y':'80'} ); 129 | textS.textContent = getNameWeek(6); 130 | gElementContainer.appendChild(textS); 131 | 132 | svgElement.appendChild(gElementContainer); 133 | 134 | // Append Calendar to document; 135 | $_this.append(svgElement); 136 | 137 | fillData(massive); 138 | 139 | 140 | 141 | function createElementSvg(type, prop ) { 142 | var e = document.createElementNS('http://www.w3.org/2000/svg', type); 143 | for (var p in prop) { 144 | e.setAttribute(p, prop[p]); 145 | } 146 | return e; 147 | } 148 | 149 | 150 | function fillData(massive) { 151 | var scoreCount = 0; 152 | for (var m in massive) { 153 | $_this.find('rect.day[data-date="' + massive[m].date + '"]').attr('data-count', massive[m].value); 154 | scoreCount += parseInt(massive[m].value); 155 | } 156 | $(settings.targetQuantity).text(massive.length + ' days, ' + scoreCount + ' scores'); 157 | 158 | } 159 | 160 | function getNameMonth(a) { 161 | return settings.months[a]; 162 | } 163 | function getNameWeek(a) { 164 | return settings.weeks[a]; 165 | } 166 | function getBeautyDate(a) { 167 | return getNameMonth(a.getMonth()) + ' ' + a.getDate() + ', ' + a.getFullYear(); 168 | } 169 | function daysInMonth(d) { 170 | return 32 - new Date(d.getFullYear(), d.getMonth(), 32).getDate(); 171 | } 172 | }; 173 | })(jQuery); 174 | --------------------------------------------------------------------------------