[
  {
    "path": ".gitignore",
    "content": "# See http://help.github.com/ignore-files/ for more about ignoring files.\n#\n# If you find yourself ignoring temporary files generated by your text editor\n# or operating system, you probably want to add a global ignore instead:\n# git config --global core.excludesfile ~/.gitignore_global\n\n# Ignore bundler config\n/.bundle\n\n# Ignore the build directory\n/build\n\n# Ignore cache\n/.sass-cache\n/.cache\n\n# Built gh-pages\n/gh-pages\n\n# Ignore .DS_store file\n.DS_Store\n\n# Ignore Node.js modules\nnode_modules\n"
  },
  {
    "path": ".jshintignore",
    "content": ""
  },
  {
    "path": ".jshintrc",
    "content": "{\n  \"bitwise\": false,\n  \"boss\": true,\n  \"browser\": true,\n  \"camelcase\": true,\n  \"curly\": true,\n  \"devel\": true,\n  \"eqeqeq\": true,\n  \"es3\": true,\n  \"expr\": true,\n  \"forin\": true,\n  \"freeze\": true,\n  \"globalstrict\": false,\n  \"immed\": true,\n  \"indent\": 2,\n  \"jquery\": true,\n  \"latedef\": true,\n  \"laxcomma\": true,\n  \"multistr\": false,\n  \"newcap\": true,\n  \"noarg\": true,\n  \"noempty\": true,\n  \"nonew\": true,\n  \"notypeof\": false,\n  \"plusplus\": false,\n  \"quotmark\": \"single\",\n  \"regexp\": true,\n  \"strict\": true,\n  \"trailing\": true,\n  \"undef\": true,\n  \"unused\": true,\n  \"maxparams\": 5,\n  \"maxdepth\": 4,\n  \"maxstatements\": 20,\n  \"maxcomplexity\": 10,\n  \"globals\": {\"module\": true, \"require\": true, \"suite\": true, \"test\": true, \"__dirname\": true}\n}\n"
  },
  {
    "path": "Gruntfile.js",
    "content": "module.exports = function(grunt) {\n\t'use strict';\n\n\tvar fs = require('fs');\n\n\tgrunt.initConfig({\n\t\tuglify: {\n\t\t\toptions: {\n\t\t\t\tmangle: false\n\t\t\t},\n\t\t\tmy_target: {\n\t\t\t\tfiles: {\n\t\t\t\t\t'dist/timesheet.min.js': ['source/javascripts/timesheet.js']\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tsass: {\n\t\t\tgh: {\n\t\t\t\toptions: {\n\t\t\t\t\tstyle: 'compressed'\n\t\t\t\t},\n\t\t\t\tfiles: {\n\t\t\t\t\t'gh-pages/styles/style.css': 'source/stylesheets/style.sass'\n\t\t\t\t}\n\t\t\t},\n\t\t\tdist: {\n\t\t\t\toptions: {\n\t\t\t\t\tstyle: 'compressed'\n\t\t\t\t},\n\t\t\t\tfiles: {\n\t\t\t\t\t'dist/timesheet.min.css': 'source/stylesheets/timesheet.sass',\n\t\t\t\t\t'dist/timesheet-white.min.css': 'source/stylesheets/timesheet-white.sass'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tjshint: {\n\t\t\tall: {\n\t\t\t\tsrc: [\n\t\t\t\t\t'source/javascripts/*.js'\n\t\t\t\t],\n\t\t\t\toptions: {\n\t\t\t\t\tjshintrc: '.jshintrc'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tsimplemocha: {\n\t\t\toptions: {\n\t\t\t\tglobals: ['should'],\n\t\t\t\ttimeout: 3000,\n\t\t\t\tignoreLeaks: false,\n\t\t\t\tgrep: '',\n\t\t\t\tui: 'tdd',\n\t\t\t\treporter: 'spec'\n\t\t\t},\n\t\t\tall: { src: ['test/**/*.js'] }\n\t\t},\n\t\texpress: {\n\t\t\toptions: {\n\t\t\t\tport: 8080\n\t\t\t},\n\t\t\tdev: {\n\t\t\t\toptions: {\n\t\t\t\t\tscript: __dirname + '/serve.js'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\twatch: {\n\t\t\tscripts: {\n\t\t\t\tfiles: 'source/javascripts/*.js',\n\t\t\t\ttasks: ['simplemocha', 'jshint', 'uglify'],\n\t\t\t\toptions: {\n\t\t\t\t\tinterrupt: true,\n\t\t\t\t}\n\t\t\t},\n\t\t\tstyles: {\n\t\t\t\tfiles: 'source/stylesheets/*.sass',\n\t\t\t\ttasks: ['sass'],\n\t\t\t\toptions: {\n\t\t\t\t\tinterrupt: true,\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\thaml: {\n\t\t\tgh: {\n\t\t\t\tfiles: {\n\t\t\t\t\t'gh-pages/index.html': 'source/index.haml'\n\t\t\t\t},\n\t\t\t\toptions: {\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\tcode: fs.readFileSync(__dirname + '/source/snippets/example-date.js')\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcopy: {\n\t\t\tgh: {\n\t\t\t\tfiles: [\n\t\t\t\t\t{expand: false, src: __dirname + '/source/javascripts/lib.js', \t\t\t\t dest: __dirname + '/gh-pages/script/lib.js'},\n\t\t\t\t\t{expand: false, src: __dirname + '/source/javascripts/main.js',\t\t\t\tdest: __dirname + '/gh-pages/script/main.js'},\n\t\t\t\t\t{expand: false, src: __dirname + '/dist/timesheet.min.js',\t\t\t      dest: __dirname + '/gh-pages/script/timesheet.min.js'},\n\t\t\t\t\t{expand: false, src: __dirname + '/dist/timesheet.min.css', \t\t\t\t\t dest: __dirname + '/gh-pages/styles/timesheet.css'},\n\t\t\t\t\t{expand: false, src: __dirname + '/dist/timesheet-white.min.css',\t\t\tdest: __dirname + '/gh-pages/styles/timesheet-white.css'},\n\t\t\t\t\t{expand: false, src: __dirname + '/dist/timesheet.min.css.map', \t\t\t dest: __dirname + '/gh-pages/styles/timesheet.css.map'},\n\t\t\t\t\t{expand: false, src: __dirname + '/dist/timesheet-white.min.css.map',\tdest: __dirname + '/gh-pages/styles/timesheet-white.css.map'}\n\t\t\t\t]\n\t\t\t}\n\t\t}\n\t});\n\n\tgrunt.loadNpmTasks('grunt-contrib-jshint');\n\tgrunt.loadNpmTasks('grunt-contrib-watch');\n\tgrunt.loadNpmTasks('grunt-simple-mocha');\n\n\tgrunt.loadNpmTasks('grunt-contrib-copy');\n\n\tgrunt.loadNpmTasks('grunt-contrib-uglify');\n\tgrunt.loadNpmTasks('grunt-contrib-sass');\n\n\tgrunt.loadNpmTasks('grunt-express-server');\n\n\tgrunt.loadNpmTasks('grunt-haml');\n\n\t// Default task\n\tgrunt.registerTask('default', \t['build']);\n\tgrunt.registerTask('build', \t\t['simplemocha', 'jshint', 'uglify', 'sass']);\n\tgrunt.registerTask('server', \t\t['express:dev', 'watch' ])\n\tgrunt.registerTask('gh', \t\t\t\t['build', 'haml:gh', 'sass:gh', 'copy:gh']);\n\n};\n"
  },
  {
    "path": "LICENSE.md",
    "content": "# The MIT License (MIT)\n\nCopyright (c) 2014-2015 Sebastian Müller\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Timesheet.js\n\nSimple JavaScript library to create HTML time sheets. Wrapped in an example project using Middleman …\n\n![https://sbstjn.github.io/timesheet.js](https://raw.githubusercontent.com/sbstjn/timesheet.js/master/screen.png)\n\nYou only have to include `dist/timesheet.js` and `dist/timesheet.css` in your HTML and initialize Timesheet.js with:\n\n```HTML\n<div id=\"timesheet\"></div>\n```\n\n```javascript\nnew Timesheet('timesheet', 2002, 2013, [\n  ['2002', '09/2002', 'A freaking awesome time', 'lorem'],\n  ['06/2002', '09/2003', 'Some great memories', 'ipsum'],\n  ['2003', 'Had very bad luck'],\n  ['10/2003', '2006', 'At least had fun', 'dolor'],\n  ['02/2005', '05/2006', 'Enjoyed those times as well', 'ipsum'],\n  ['07/2005', '09/2005', 'Bad luck again', 'default'],\n  ['10/2005', '2008', 'For a long time nothing happened', 'dolor'],\n  ['01/2008', '05/2009', 'LOST Season #4', 'lorem'],\n  ['01/2009', '05/2009', 'LOST Season #4', 'lorem'],\n  ['02/2010', '05/2010', 'LOST Season #5', 'lorem'],\n  ['09/2008', '06/2010', 'FRINGE #1 & #2', 'ipsum']\n]);\n```\n\n### Bower\n\n`$ > bower install https://github.com/sbstjn/timesheet.js.git`\n\n## Grunt commands\n\nUse `grunt` to build all JavaScript and StyleSheet files located inside `dist/`. \n\nUse `grunt server` to start a local web server on [localhost:8080](http://localhost:8080) to customize Timesheet.js, afterwards run `grunt` to compile all needed files.\n\nUse `grunt gh` to generate the site and files available at [sbstjn.github.io/timesheet.js](http://sbstjn.github.io/timesheet.js) into the `gh-pages` folder.\n\n## License\n\nTimesheet.js is licensed under MIT License.\n"
  },
  {
    "path": "bower.json",
    "content": "{\n  \"name\": \"timesheet.js\",\n  \"homepage\": \"https://sbstjn.github.io/timesheet.js/\",\n  \"authors\": [\n    \"sbstjn <mail@sbstjn.com>\"\n  ],\n  \"description\": \"With Timesheet.js you can easily create simple time and data sheets or timelines using HTML5, JavaScript and CSS3. Yep, it's a Vanilla JS library!\",\n  \"main\": [\"dist/timesheet.min.js\", \"dist/timesheet.min.css\"],\n  \"moduleType\": [\n    \"amd\"\n  ],\n  \"keywords\": [\n    \"timeline\",\n    \"timesheet\",\n    \"timebar\",\n    \"line\",\n    \"bar\",\n    \"graph\",\n    \"visualize\",\n    \"chart\"\n  ],\n  \"license\": \"MIT\",\n  \"ignore\": [\n    \"**/.*\",\n    \"node_modules\",\n    \"bower_components\",\n    \"test\",\n    \"tests\",\n    \"screen.png\",\n    \"source\",\n    \"Gruntfile.js\",\n    \"package.json\"\n  ]\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"timesheet.js\",\n  \"version\": \"1.0.1\",\n  \"description\": \"With Timesheet.js you can easily create simple time and data sheets or timelines using HTML5, JavaScript and CSS3. Yep, it's a Vanilla JS library!\",\n  \"author\": \"sbstjn <mail@sbstjn.com>\",\n  \"devDependencies\": {\n    \"consolidate\": \"^0.13.1\",\n    \"express\": \"^4.12.4\",\n    \"grunt\": \"~0.4.1\",\n    \"grunt-cli\": \"~0.1.11\",\n    \"grunt-contrib-copy\": \"^0.8.0\",\n    \"grunt-contrib-jshint\": \"~0.7.2\",\n    \"grunt-contrib-sass\": \"^0.7.3\",\n    \"grunt-contrib-uglify\": \"^0.4.0\",\n    \"grunt-contrib-watch\": \"^0.6.1\",\n    \"grunt-express-server\": \"^0.5.1\",\n    \"grunt-haml\": \"^0.9.0\",\n    \"grunt-jslint\": \"~1.1.1\",\n    \"grunt-simple-mocha\": \"^0.4.0\",\n    \"haml\": \"^0.4.3\",\n    \"hamljs\": \"^0.6.2\",\n    \"node-sass\": \"^3.2.0\"\n  }\n}\n"
  },
  {
    "path": "serve.js",
    "content": "var express = require('express');\nvar sass = require('node-sass');\nvar fs = require('fs');\nvar app = express();\nvar engines = require('consolidate');\n\napp.engine('haml', engines.haml);\napp.set('views', __dirname + '/source');\n\napp.get('/script/lib.js', function(req, res) { \n  res.end(fs.readFileSync(__dirname + '/source/javascripts/lib.js'));\n});\n\napp.get('/script/main.js', function(req, res) { \n  res.end(fs.readFileSync(__dirname + '/source/javascripts/main.js'));\n});\n\napp.get('/script/timesheet.min.js', function(req, res) { \n  res.end(fs.readFileSync(__dirname + '/dist/timesheet.min.js'));\n});\n\napp.get('/styles/timesheet.css', function(req, res) {\n  res.end(fs.readFileSync(__dirname + '/dist/timesheet.min.css'));\n});\n\napp.get('/styles/timesheet-white.css', function(req, res) {\n  res.end(fs.readFileSync(__dirname + '/dist/timesheet-white.min.css'));\n});\n\napp.get('/styles/style.css', function(req, res) {\n  sass.render({\n    file: __dirname + '/source/stylesheets/style.sass',\n    outputStyle: req.query.style || \"\"\n  }, function(err, result) {\n    res.end(result.css.toString());\n  });\n});\n\napp.get('/', function (req, res) {\n  res.render('index.haml', {\n    code: fs.readFileSync(__dirname + '/source/snippets/example-date.js') + ''\n  });\n});\n\nvar server = app.listen(process.env.PORT || 3000, function () {\n  var host = server.address().address;\n  var port = server.address().port;\n\n  console.log('Example app listening at http://%s:%s', host, port);\n});\n"
  },
  {
    "path": "source/index.haml",
    "content": "!!! 5\n%html\n  %head\n    %title Timesheet.js - Beautiful time tables with HTML, JavaScript and CSS …\n  \n    %meta{charset: 'utf-8'}\n    %meta{content: 'IE=edge,chrome=1', 'http-equiv': 'X-UA-Compatible'}\n    \n    %meta{property: 'og:title',         content: 'Timesheet.js - Beautiful time tables with HTML, JavaScript and CSS …'}\n    %meta{property: 'og:description',   content: 'With Timesheet.js you can easily create simple time and data sheets or timelines using HTML5, JavaScript and CSS3. Yep, it\\'s a Vanilla JS library!'}\n    %meta{property: 'og:url',           content: 'https://sbstjn.github.io/timesheet.js/'}\n    %meta{property: 'og:image',         content: 'https://raw.githubusercontent.com/sbstjn/timesheet.js/master/screen.png'}\n    %meta{property: 'fb:admins',        content: '669118929'}\n    \n    %script{type: 'text/javascript', src: './script/lib.js'}\n    %script{type: 'text/javascript', src: './script/timesheet.min.js'}\n    %script{type: 'text/javascript', src: './script/main.js'}\n    \n    %link{rel: 'stylesheet', type: \"text/css\", href: \"./styles/style.css\"}\n    %link{rel: 'stylesheet', type: \"text/css\", href: \"./styles/timesheet.css\"}\n    %link{rel: 'stylesheet', type: \"text/css\", href: \"./styles/timesheet-white.css\"}\n    \n    %link{rel: 'stylesheet', type: \"text/css\", href: \"https://fonts.jimstatic.com/css?family=Oxygen+Mono:400,600,800\"}\n    %link{rel: 'stylesheet', type: \"text/css\", href: \"https://fonts.jimstatic.com/css?family=Open+Sans:400,600,800\"}\n    %link{rel: 'stylesheet', type: \"text/css\", href: \"https://fonts.jimstatic.com/css?family=Signika+Negative:300,400,600,700\"}\n    \n  %body.black\n    #box\n      #box-inner\n        %h1\n          Timesheet<span>.js</span>\n        %p Visualize your data and events with sexy <span>HTML5</span> and <span>CSS3</span>. Create simple time sheets with sneaky JavaScript. Style them with CSS and have mobile fun as well …\n        #timesheet-default\n        %p Just include Timesheet.js and configure your data. No external dependencies, no jQuery needed and of course no Angular.JS! Just a few lines JavaScript to generate a beautiful HTML5 layout and some really delicious CSS to be customized by almighty you.\n        %code\n          %pre!='&lt;script src=\"/javascripts/timesheet.js\" type=\"text/javascript\" /&gt;'\n        %p Create a simple time sheet based on a JS array of events:\n        %code\n          %pre!=code\n        %p It's that simple to use <span>Timesheet.js</span>. So, have a nice day, thank you for smoking and maybe try using Timesheet.js with custom styles …\n        \n        %p.footer  <a href='https://github.com/sbstjn/timesheet.js'>Timesheet.js</a> is licensed under <a href='https://github.com/sbstjn/timesheet.js/blob/master/LICENSE.md'>MIT License</a><br />Cheers to <a href='https://twitter.com/cheeaun'>Cheeaun</a> and <a href='https://twitter.com/igrigorik/'>Ilya</a><br /><br /><br /><span><a href='http://S11K.com'>❤</a></span><br /><br /><a href='#dark' id='switch-dark'>dark</a> | <a href='#light' id='switch-light'>light</a>\n        \n    %span  <a href='https://github.com/sbstjn/timesheet.js'><img style='position: absolute; top: 0; right: 0; border: 0;' src='https://camo.githubusercontent.com/a6677b08c955af8400f44c6298f40e7d19cc5b2d/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f677261795f3664366436642e706e67' alt='Fork Timesheet.js on GitHub' data-canonical-src='https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png'></a>\n"
  },
  {
    "path": "source/javascripts/lib.js",
    "content": "(function() {\n  'use strict';\n\n  var Lib = {\n    /* http://www.dustindiaz.com/smallest-domready-ever */\n    /* jshint -W030 */\n    ready: function r(f){ /in/.test(document.readyState)?setTimeout(function () {Lib.ready(f);},9):f(); }\n  };\n\n  window.Lib = Lib;\n})();\n"
  },
  {
    "path": "source/javascripts/main.js",
    "content": "/* global Lib, Timesheet */\n\n(function(){\n  'use strict';\n  \n  Lib.ready(function() {\n    console.log('ads');\n    \n    /* jshint -W031 */\n    new Timesheet('timesheet-default', 2002, 2013, [\n      ['2002', '09/2002', 'A freaking awesome time', 'lorem'],\n      ['06/2002', '09/2003', 'Some great memories', 'ipsum'],\n      ['2003', 'Had very bad luck'],\n      ['10/2003', '2006', 'At least had fun', 'dolor'],\n      ['02/2005', '05/2006', 'Enjoyed those times as well', 'ipsum'],\n      ['07/2005', '09/2005', 'Bad luck again', 'default'],\n      ['10/2005', '2008', 'For a long time nothing happened', 'dolor'],\n      ['01/2008', '05/2009', 'LOST Season #4', 'lorem'],\n      ['01/2009', '05/2009', 'LOST Season #4', 'sit'],\n      ['02/2010', '05/2010', 'LOST Season #5', 'lorem'],\n      ['09/2008', '06/2010', 'FRINGE #1 & #2', 'ipsum']\n    ]);\n\n    document.querySelector('#switch-dark').addEventListener('click', function() {\n      document.querySelector('body').className = 'index black';\n    });\n\n    document.querySelector('#switch-light').addEventListener('click', function() {\n      document.querySelector('body').className = 'index white';\n    });\n  });\n})();\n"
  },
  {
    "path": "source/javascripts/timesheet.js",
    "content": "(function() {\n  'use strict';\n\n  /**\n   * Initialize a Timesheet\n   */\n  var Timesheet = function(container, min, max, data) {\n    this.data = [];\n    this.year = {\n      min: min,\n      max: max\n    };\n\n    this.parse(data || []);\n\n    if (typeof document !== 'undefined') {\n      this.container = (typeof container === 'string') ? document.querySelector('#'+container) : container;\n      this.drawSections();\n      this.insertData();\n    }\n  };\n\n  /**\n   * Insert data into Timesheet\n   */\n  Timesheet.prototype.insertData = function() {\n    var html = [];\n    var widthMonth = this.container.querySelector('.scale section').offsetWidth;\n\n    for (var n = 0, m = this.data.length; n < m; n++) {\n      var cur = this.data[n];\n      var bubble = this.createBubble(widthMonth, this.year.min, cur.start, cur.end);\n\n      var line = [\n        '<span style=\"margin-left: ' + bubble.getStartOffset() + 'px; width: ' + bubble.getWidth() + 'px;\" class=\"bubble bubble-' + (cur.type || 'default') + '\" data-duration=\"' + (cur.end ? Math.round((cur.end-cur.start)/1000/60/60/24/39) : '') + '\"></span>',\n        '<span class=\"date\">' + bubble.getDateLabel() + '</span> ',\n        '<span class=\"label\">' + cur.label + '</span>'\n      ].join('');\n\n      html.push('<li>' + line + '</li>');\n    }\n\n    this.container.innerHTML += '<ul class=\"data\">' + html.join('') + '</ul>';\n  };\n\n  /**\n   * Draw section labels\n   */\n  Timesheet.prototype.drawSections = function() {\n    var html = [];\n\n    for (var c = this.year.min; c <= this.year.max; c++) {\n      html.push('<section>' + c + '</section>');\n    }\n\n    this.container.className = 'timesheet color-scheme-default';\n    this.container.innerHTML = '<div class=\"scale\">' + html.join('') + '</div>';\n  };\n\n  /**\n   * Parse data string\n   */\n  Timesheet.prototype.parseDate = function(date) {\n    if (date.indexOf('/') === -1) {\n      date = new Date(parseInt(date, 10), 0, 1);\n      date.hasMonth = false;\n    } else {\n      date = date.split('/');\n      date = new Date(parseInt(date[1], 10), parseInt(date[0], 10)-1, 1);\n      date.hasMonth = true;\n    }\n\n    return date;\n  };\n\n  /**\n   * Parse passed data\n   */\n  Timesheet.prototype.parse = function(data) {\n    for (var n = 0, m = data.length; n<m; n++) {\n      var beg = this.parseDate(data[n][0]);\n      var end = data[n].length === 4 ? this.parseDate(data[n][1]) : null;\n      var lbl = data[n].length === 4 ? data[n][2] : data[n][1];\n      var cat = data[n].length === 4 ? data[n][3] : data[n].length === 3 ? data[n][2] : 'default';\n\n      if (beg.getFullYear() < this.year.min) {\n        this.year.min = beg.getFullYear();\n      }\n\n      if (end && end.getFullYear() > this.year.max) {\n        this.year.max = end.getFullYear();\n      } else if (beg.getFullYear() > this.year.max) {\n        this.year.max = beg.getFullYear();\n      }\n\n      this.data.push({start: beg, end: end, label: lbl, type: cat});\n    }\n  };\n\n  /**\n   * Wrapper for adding bubbles\n   */\n  Timesheet.prototype.createBubble = function(wMonth, min, start, end) {\n    return new Bubble(wMonth, min, start, end);\n  };\n\n  /**\n   * Timesheet Bubble\n   */\n  var Bubble = function(wMonth, min, start, end) {\n    this.min = min;\n    this.start = start;\n    this.end = end;\n    this.widthMonth = wMonth;\n  };\n\n  /**\n   * Format month number\n   */\n  Bubble.prototype.formatMonth = function(num) {\n    num = parseInt(num, 10);\n\n    return num >= 10 ? num : '0' + num;\n  };\n\n  /**\n   * Calculate starting offset for bubble\n   */\n  Bubble.prototype.getStartOffset = function() {\n    return (this.widthMonth/12) * (12 * (this.start.getFullYear() - this.min) + this.start.getMonth());\n  };\n\n  /**\n   * Get count of full years from start to end\n   */\n  Bubble.prototype.getFullYears = function() {\n    return ((this.end && this.end.getFullYear()) || this.start.getFullYear()) - this.start.getFullYear();\n  };\n\n  /**\n   * Get count of all months in Timesheet Bubble\n   */\n  Bubble.prototype.getMonths = function() {\n    var fullYears = this.getFullYears();\n    var months = 0;\n\n    if (!this.end) {\n      months += !this.start.hasMonth ? 12 : 1;\n    } else {\n      if (!this.end.hasMonth) {\n        months += 12 - (this.start.hasMonth ? this.start.getMonth() : 0);\n        months += 12 * (fullYears-1 > 0 ? fullYears-1 : 0);\n      } else {\n        months += this.end.getMonth() + 1;\n        months += 12 - (this.start.hasMonth ? this.start.getMonth() : 0);\n        months += 12 * (fullYears-1);\n      }\n    }\n\n    return months;\n  };\n\n  /**\n   * Get bubble's width in pixel\n   */\n  Bubble.prototype.getWidth = function() {\n    return (this.widthMonth/12) * this.getMonths();\n  };\n\n  /**\n   * Get the bubble's label\n   */\n  Bubble.prototype.getDateLabel = function() {\n    return [\n      (this.start.hasMonth ? this.formatMonth(this.start.getMonth() + 1) + '/' : '' ) + this.start.getFullYear(),\n      (this.end ? '-' + ((this.end.hasMonth ? this.formatMonth(this.end.getMonth() + 1) + '/' : '' ) + this.end.getFullYear()) : '')\n    ].join('');\n  };\n\n  window.Timesheet = Timesheet;\n})();"
  },
  {
    "path": "source/snippets/example-date.js",
    "content": "new Timesheet('timesheet-default', 2002, 2013, [\n  ['2002', '09/2002', 'A freaking awesome time', 'lorem'],\n  ['06/2002', '09/2003', 'Some great memories', 'ipsum'],\n  ['2003', 'Had very bad luck'],\n  ['10/2003', '2006', 'At least had fun', 'dolor'],\n  ['02/2005', '05/2006', 'Enjoyed those times as well', 'ipsum'],\n  ['07/2005', '09/2005', 'Bad luck again', 'default'],\n  ['10/2005', '2008', 'For a long time nothing happened', 'dolor'],\n  ['01/2008', '05/2009', 'LOST Season #4', 'lorem'],\n  ['01/2009', '05/2009', 'LOST Season #4', 'lorem'],\n  ['02/2010', '05/2010', 'LOST Season #5', 'lorem'],\n  ['09/2008', '06/2010', 'FRINGE #1 & #2', 'ipsum']\n]);"
  },
  {
    "path": "source/stylesheets/_normalize.sass",
    "content": "article, aside, details, figcaption, figure, footer, header, hgroup, nav, section, summary\n  display: block\n\naudio, canvas, video\n  display: inline-block\n\naudio:not([controls])\n  display: none\n  height: 0\n\n[hidden]\n  display: none\n\nhtml\n  font-family: sans-serif\n  -webkit-text-size-adjust: 100%\n  -ms-text-size-adjust: 100%\n\nhtml, body, p, ul, li, h1, h2, h3, h4, h5, img, fieldset, input, textarea, select\n  margin: 0\n  padding: 0\n  border: 0\n\na\n  &:focus\n    outline: 0\n  &:active, &:hover\n    outline: 0\n\nh1\n  font-size: 2em\n\nh2\n  font-size: 1em\n\nstrong\n  font-weight: bold\n\ndfn\n  font-style: italic\n\ncode, kbd, pre, samp\n  font-family: monospace, serif\n  font-size: 1em\n\npre\n  white-space: pre\n  white-space: pre-wrap\n  word-wrap: break-word\n\nq\n  quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"\n\nsmall\n  font-size: 80%\n\nsub\n  font-size: 75%\n  line-height: 0\n  position: relative\n  vertical-align: baseline\n  bottom: -0.25em\n\nsup\n  font-size: 75%\n  line-height: 0\n  position: relative\n  vertical-align: baseline\n  top: -0.5em\n\nimg\n  border: 0\n\nlegend\n  border: 0\n  padding: 0\n\nbutton, input, select, textarea\n  font-size: 100%\n\ntextarea, input\n  outline: none\n\ninput\n  line-height: normal\n\nul, ul li\n  list-style-type: none\n  margin: 0\n  padding: 0\n\nbutton::-moz-focus-inner, input::-moz-focus-inner\n  border: 0\n  padding: 0\n\ntextarea\n  overflow: auto\n  vertical-align: top\n\ntable\n  border-collapse: collapse\n  border-spacing: 0\n"
  },
  {
    "path": "source/stylesheets/style.sass",
    "content": "@import 'normalize'\n\nhtml, body\n  margin: 0\n  padding: 0\n  width: 100%\n  height: 100%\n\n*\n  transition: all 0.5s ease\n\nbody.black\n  background-color: rgba(61, 61, 61, 1)\n\nbody.white\n  background-color: rgba(230, 230, 230, 1)\n\n#box\n  width: 100%\n  height: 100%\n\n#box-inner\n  height: 100%\n  text-align: center\n  vertical-align: middle\n\nh1\n  font-family: 'Open Sans'\n  font-size: 60pt\n  font-weight: 800\n  line-height: 240px\n\np\n  width: 680px\n  text-align: left\n  font-family: 'Open Sans'\n  font-weight: 400\n  margin: 20px auto\n  line-height: 24px\n\ncode\n  pre\n    margin: 0 auto\n    width: 670px\n    padding: 10px 8px\n    font-family: 'Oxygen Mono'\n    font-size: 11px\n    font-weight: 600\n\ncode, pre\n  text-align: left\n\n.footer\n  margin-top: 65px\n  text-align: center\n  font-size: 12px\n  font-weight: 300\n\n  a\n    font-weight: 300\n\n  a, a:hover, a:active, a:visited\n    font-weight: 300\n\na, a:hover, a:visited, a:active\n  font-weight: 600\n  text-decoration: none\n\n\n.center\n  text-align: center\n\n.white\n  h1\n    color: RGBA(29, 175, 234, 1)\n\n  p\n    color: rgba(100, 100, 100, 1)\n\n  p span\n    color: RGBA(29, 175, 234, 1)\n    font-weight: 600\n\n  code\n    pre\n      color: rgba(40, 40, 40, 1)\n      background-color: rgba(250, 250, 250, 1)\n\n  .footer\n    color: rgba(100, 100, 100, 1)\n\n    a\n      color: rgba(100, 100, 100, 1)\n\n    span\n      a\n        color: RGBA(29, 175, 234, 1)\n\n.black\n  h1\n    color: rgba(255, 145, 18, 1)\n\n  p\n    color: rgba(220, 220, 220, 1)\n\n  code\n    pre\n      background-color: rgba(100, 100, 100, 1)\n      color: rgba(190, 190, 190, 1)\n\n  a, a:hover, a:visited, a:active, p span\n    color: rgba(255, 145, 18, 1)\n\n  .footer\n    color: rgba(100, 100, 100, 1)\n\n    a\n      color: rgba(100, 100, 100, 1)\n\n    span\n      a\n        color: rgba(255, 145, 18, 1)\n\n\n\n  #example-data\n    margin: 0 auto\n    width: 680px\n    height: 300px\n    background-color: rgba(100, 100, 100, 1)\n\n    p\n      text-align: right\n      font-size: 12px\n      a\n        color: rgba(255, 145, 18, 1)\n        text-decoration: none\n\n\n  .version\n    font-size: 12px\n    line-height: 17px\n    margin: 80px auto\n\n    a, a:visited, a:hover, a:active\n      font-family: 'Open Sans'\n      color: rgba(255, 145, 18, 1)\n      text-decoration: none\n\n    span\n      font-weight: 600\n      color: white\n\n\n    span\n      color: rgba(255, 145, 18, 1)\n      font-weight: 600\n"
  },
  {
    "path": "source/stylesheets/timesheet-white.sass",
    "content": "\n.white\n  .timesheet\n    width: 720px\n    height: 292px\n    margin: 0 auto\n  \n  .timesheet\n    border-top: 1px solid rgba(60, 60, 60, 0.3)\n    background-color: rgba(251, 251, 251, 1)\n    position: relative\n  \n    &.color-scheme-default\n      .bubble-default\n        background-color: RGBA(252, 70, 74, 1) // red\n      .bubble-lorem\n        background-color: RGBA(154, 202, 39, 1) // green\n      .bubble-ipsum\n        background-color: RGBA(60, 182, 227, 1) // blue\n      .bubble-dolor\n        background-color: RGBA(244, 207, 48, 1) // yellow\n      .bubble-sit\n        background-color: RGBA(169, 105, 202, 1) // cyan\n  \n    &.color-scheme-alternative\n      .bubble-default\n        background-color: rgba(243, 85, 46, 1)\n      .bubble-lorem\n        background-color: rgba(136, 195, 58, 1)\n      .bubble-ipsum\n        background-color: rgba(67, 106, 224, 1)\n      .bubble-dolor\n        background-color: rgba(244, 210, 52, 1)\n      .bubble-sit\n        background-color: rgba(112, 125, 134, 1)\n  \n  \n    .scale\n      height: 100%\n      position: absolute\n      top: 0\n      left: 0\n      float: left\n  \n      section\n        float: left\n        width: 59px\n        color: rgba(50, 50, 50, 0.8)\n        font-family: 'Signika Negative'\n        font-size: 13px\n        line-height: 24px\n        font-weight: 300\n        border-left: 1px dashed rgba(50, 50, 50, 0.1)\n        height: 100%\n  \n    .data\n      margin: 28px 0 0 0\n      padding: 0\n      text-align: left\n      list-style-type: none\n      color: rgba(250, 250, 250, 0.8)\n      font-family: 'Signika Negative'\n      font-size: 13px\n      overflow: hidden\n  \n      li\n        margin: 0 0 3px 0\n        line-height: 22px\n        height: 21px\n        display: block\n        cursor: pointer\n        clear: both\n        position: relative\n        white-space: nowrap\n  \n        &:hover\n          .bubble\n            opacity: 1\n  \n        .date\n          color: rgba(121, 121, 121, 1)\n          font-size: 14px\n  \n        .label\n          font-weight: lighter\n          font-size: 14px\n          padding-left: 5px\n          line-height: 21px\n          color: rgba(51, 51, 50, 1)\n          white-space: nowrap\n  \n        .bubble\n          width: 24px\n          height: 7px\n          display: block\n          float: left\n          position: relative\n          top: 7px\n          border-radius: 4px\n          margin: 0 10px 0 0\n          opacity: 0.7\n"
  },
  {
    "path": "source/stylesheets/timesheet.sass",
    "content": ".timesheet\n  width: 720px\n  height: 292px\n  margin: 0 auto\n\n.timesheet\n  border-top: 1px solid rgba(250, 250, 250, 0.5)\n  background-color: rgba(51, 51, 51, 1)\n  position: relative\n\n  &.color-scheme-default\n    .bubble-default\n      background-color: RGBA(252, 70, 74, 1) // red\n    .bubble-lorem\n      background-color: RGBA(154, 202, 39, 1) // green\n    .bubble-ipsum\n      background-color: RGBA(60, 182, 227, 1) // blue\n    .bubble-dolor\n      background-color: RGBA(244, 207, 48, 1) // yellow\n    .bubble-sit\n      background-color: RGBA(169, 105, 202, 1) // cyan\n\n  &.color-scheme-alternative\n    .bubble-default\n      background-color: rgba(243, 85, 46, 1)\n    .bubble-lorem\n      background-color: rgba(136, 195, 58, 1)\n    .bubble-ipsum\n      background-color: rgba(67, 106, 224, 1)\n    .bubble-dolor\n      background-color: rgba(244, 210, 52, 1)\n    .bubble-sit\n      background-color: rgba(112, 125, 134, 1)\n\n\n  .scale\n    height: 100%\n    position: absolute\n    top: 0\n    left: 0\n    float: left\n\n    section\n      float: left\n      width: 59px\n      text-align: center\n      color: rgba(250, 250, 250, 0.8)\n      font-family: 'Signika Negative'\n      font-size: 13px\n      line-height: 24px\n      font-weight: lighter\n      border-left: 1px dashed rgba(250, 250, 250, 0.2)\n      height: 100%\n\n  .data\n    margin: 28px 0 0 0\n    padding: 0\n    text-align: left\n    list-style-type: none\n    color: rgba(250, 250, 250, 0.8)\n    font-family: 'Signika Negative'\n    font-size: 13px\n    overflow: hidden\n\n    li\n      margin: 0 0 3px 0\n      line-height: 22px\n      height: 21px\n      display: block\n      clear: both\n      position: relative\n      white-space: nowrap\n\n      &:hover\n        .bubble\n          opacity: 1\n\n      .date\n        color: rgba(181, 181, 181, 1)\n        font-size: 14px\n\n      .label\n        font-weight: lighter\n        font-size: 14px\n        padding-left: 5px\n        line-height: 21px\n        color: rgba(151, 151, 150, 1)\n        white-space: nowrap\n\n      .bubble\n        width: 24px\n        height: 7px\n        display: block\n        float: left\n        position: relative\n        top: 7px\n        border-radius: 4px\n        margin: 0 10px 0 0\n        opacity: 0.7\n\n#timesheet-alternative\n  background-color: RGBA(247, 247, 247, 1)\n  border-radius: 5px\n\n  section\n    color: RGBA(63, 68, 72, 1)\n    border-left: 1px dashed RGBA(63, 68, 72, 0.2)\n\n    &:first-child\n      border-left: 1px dashed transparent\n\n  .date\n    display: none\n\n  .bubble\n    margin-right: 7px\n\n  .label\n    padding-left: 0px\n    color: RGBA(48, 48, 48, 1)\n"
  },
  {
    "path": "test/timesheet.js",
    "content": "/**\n * Load Timesheet lib and fake a window object …\n */\nwindow = {};\nrequire(__dirname + '/../source/javascripts/timesheet.js');\n\nvar assert = require('assert');\nsuite('Timesheet', function() {\n  test('Calculation', function(done) {\n    var TS = new window.Timesheet();\n\n    assert.equal(12,  (TS.createBubble(60, 2012, TS.parseDate('2002'), TS.parseDate('2002'))).getMonths());\n    assert.equal(12,  (TS.createBubble(60, 2012, TS.parseDate('2002'), TS.parseDate('2003'))).getMonths());\n    assert.equal(24,  (TS.createBubble(60, 2012, TS.parseDate('2002'), TS.parseDate('2004'))).getMonths());\n\n    assert.equal(9,   (TS.createBubble(60, 2012, TS.parseDate('04/2002'), TS.parseDate('2002'))).getMonths());\n    assert.equal(9,   (TS.createBubble(60, 2012, TS.parseDate('04/2002'), TS.parseDate('2003'))).getMonths());\n    assert.equal(21,  (TS.createBubble(60, 2012, TS.parseDate('04/2002'), TS.parseDate('2004'))).getMonths());\n\n    assert.equal(13,  (TS.createBubble(60, 2012, TS.parseDate('04/2002'), TS.parseDate('04/2003'))).getMonths());\n\n    assert.equal(25,  (TS.createBubble(60, 2012, TS.parseDate('04/2002'), TS.parseDate('04/2004'))).getMonths());\n\n    assert.equal(1,   (TS.createBubble(60, 2012, TS.parseDate('04/2002'))).getMonths());\n    assert.equal(12,  (TS.createBubble(60, 2012, TS.parseDate('2002'))).getMonths());\n\n    done();\n  });\n});\n"
  }
]