(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define("Gantt", [], factory); else if(typeof exports === 'object') exports["Gantt"] = factory(); else root["Gantt"] = factory(); })(this, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ function(module, exports, __webpack_require__) { 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = Gantt; __webpack_require__(1); var _moment = __webpack_require__(5); var _moment2 = _interopRequireDefault(_moment); var _snapsvg = __webpack_require__(126); var _snapsvg2 = _interopRequireDefault(_snapsvg); var _Bar = __webpack_require__(127); var _Bar2 = _interopRequireDefault(_Bar); var _Arrow = __webpack_require__(128); var _Arrow2 = _interopRequireDefault(_Arrow); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } _moment2.default.locale('zh-cn'); /* global moment, Snap */ /** * Gantt: * element: querySelector string, HTML DOM or SVG DOM element, required * tasks: array of tasks, required * task: { id, name, start, end, progress, dependencies, custom_class } * config: configuration options, optional * */ function Gantt(element, tasks, config) { var self = {}; function init() { set_defaults(); // expose methods self.change_view_mode = change_view_mode; self.unselect_all = unselect_all; self.view_is = view_is; self.get_bar = get_bar; self.trigger_event = trigger_event; self.refresh = refresh; // initialize with default view mode change_view_mode(self.config.view_mode); } function set_defaults() { var defaults = { header_height: 50, column_width: 30, step: 24, view_modes: ['Quarter Day', 'Half Day', 'Day', 'Week', 'Month'], bar: { height: 20, borderRadius: 0 }, arrow: { curve: 5 }, padding: 18, view_mode: 'Day', date_format: 'YYYY-MM-DD', // auto location to today when init. loc_to_today: true, custom_popup_html: null }; self.config = Object.assign({}, defaults, config); reset_variables(tasks); } function reset_variables(tasks) { if (typeof element === 'string') { self.element = document.querySelector(element); } else if (element instanceof SVGElement) { self.element = element; } else if (element instanceof HTMLElement) { self.element = element.querySelector('svg'); } else { throw new TypeError('Frappé Gantt only supports usage of a string CSS selector,' + ' HTML DOM element or SVG DOM element for the \'element\' parameter'); } if (!self.fixedDateDom) { var divDom = document.createElement('div'); var parentElement = self.element.parentNode; divDom.className = 'fixed-date'; divDom.style.width = parentElement.offsetWidth - getScrollbarWidth() + 'px'; divDom.style.height = self.config.header_height + 10 + 'px'; self.fixedDateDom = document.createElementNS("http://www.w3.org/2000/svg", "svg"); divDom.appendChild(self.fixedDateDom); parentElement.insertBefore(divDom, self.element); } self._tasks = tasks; self._bars = []; self._arrows = []; self.element_groups = {}; } function refresh(updated_tasks) { reset_variables(updated_tasks); change_view_mode(self.config.view_mode); } function change_view_mode(mode) { set_scale(mode); prepare(); render(); // fire viewmode_change event trigger_event('view_change', [mode]); } function prepare() { prepare_tasks(); prepare_dependencies(); prepare_dates(); prepare_canvas(); } function prepare_tasks() { // prepare tasks self.tasks = self._tasks.map(function (task, i) { // momentify task._start = (0, _moment2.default)(task.start, self.config.date_format); task._end = (0, _moment2.default)(task.end, self.config.date_format); // cache index task._index = i; // invalid dates if (!task.start && !task.end) { task._start = (0, _moment2.default)().startOf('day'); task._end = (0, _moment2.default)().startOf('day').add(2, 'days'); } if (!task.start && task.end) { task._start = task._end.clone().add(-2, 'days'); } if (task.start && !task.end) { task._end = task._start.clone().add(2, 'days'); } // invalid flag if (!task.start || !task.end) { task.invalid = true; } // dependencies if (typeof task.dependencies === 'string' || !task.dependencies) { var deps = []; if (task.dependencies) { deps = task.dependencies.split(',').map(function (d) { return d.trim(); }).filter(function (d) { return d; }); } task.dependencies = deps; } // uids if (!task.id) { task.id = generate_id(task); } return task; }); } function prepare_dependencies() { self.dependency_map = {}; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = self.tasks[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var t = _step.value; var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = t.dependencies[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var d = _step2.value; self.dependency_map[d] = self.dependency_map[d] || []; self.dependency_map[d].push(t.id); } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } function prepare_dates() { self.gantt_start = self.gantt_end = null; var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = self.tasks[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var task = _step3.value; // set global start and end date if (!self.gantt_start || task._start < self.gantt_start) { self.gantt_start = task._start; } if (!self.gantt_end || task._end > self.gantt_end) { self.gantt_end = task._end; } } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } set_gantt_dates(); setup_dates(); } function prepare_canvas() { if (self.canvas) return; self.canvas = (0, _snapsvg2.default)(self.element).addClass('gantt'); self.fixedDateCanvas = (0, _snapsvg2.default)(self.fixedDateDom).addClass('gantt-fixed-date'); } function render() { clear(); setup_groups(); make_grid(); make_dates(); make_bars(); make_arrows(); map_arrows_on_bars(); set_width(); set_scroll_position(); bind_grid_click(); } function clear() { self.canvas.clear(); self.fixedDateCanvas.clear(); self._bars = []; self._arrows = []; } function destroy() { clear(); } function set_gantt_dates() { if (view_is(['Quarter Day', 'Half Day'])) { self.gantt_start = self.gantt_start.clone().subtract(7, 'day'); self.gantt_end = self.gantt_end.clone().add(7, 'day'); } else if (view_is('Month')) { self.gantt_start = self.gantt_start.clone().startOf('year'); self.gantt_end = self.gantt_end.clone().endOf('month').add(1, 'year'); } else { self.gantt_start = self.gantt_start.clone().startOf('month').subtract(1, 'month'); self.gantt_end = self.gantt_end.clone().endOf('month').add(1, 'month'); } } function setup_dates() { self.dates = []; var cur_date = null; while (cur_date === null || cur_date < self.gantt_end) { if (!cur_date) { cur_date = self.gantt_start.clone(); } else { cur_date = view_is('Month') ? cur_date.clone().add(1, 'month') : cur_date.clone().add(self.config.step, 'hours'); } self.dates.push(cur_date); } } function setup_groups() { var groups = ['grid', 'arrow', 'progress', 'bar', 'details']; // make group layers var _iteratorNormalCompletion4 = true; var _didIteratorError4 = false; var _iteratorError4 = undefined; try { for (var _iterator4 = groups[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { var group = _step4.value; self.element_groups[group] = self.canvas.group().attr({ 'id': group }); } // for fixed date views } catch (err) { _didIteratorError4 = true; _iteratorError4 = err; } finally { try { if (!_iteratorNormalCompletion4 && _iterator4.return) { _iterator4.return(); } } finally { if (_didIteratorError4) { throw _iteratorError4; } } } self.element_groups['date'] = self.fixedDateCanvas.group().attr('id', 'date'); } function set_scale(scale) { self.config.view_mode = scale; if (scale === 'Day') { self.config.step = 24; self.config.column_width = 38; } else if (scale === 'Half Day') { self.config.step = 24 / 2; self.config.column_width = 38; } else if (scale === 'Quarter Day') { self.config.step = 24 / 4; self.config.column_width = 38; } else if (scale === 'Week') { self.config.step = 24 * 7; self.config.column_width = 140; } else if (scale === 'Month') { self.config.step = 24 * 30; self.config.column_width = 120; } } function set_width() { var cur_width = self.canvas.node.getBoundingClientRect().width; var actual_width = self.canvas.select('#grid .grid-row').attr('width'); if (cur_width < actual_width) { self.canvas.attr('width', actual_width); } } function set_scroll_position() { var parent_element = self.element.parentElement; if (!parent_element) return; var scroll_pos = (self.config.loc_to_today ? (0, _moment2.default)() : get_min_date()).diff(self.gantt_start, 'hours') / self.config.step * self.config.column_width - Math.round(parent_element.offsetWidth / 2); parent_element.scrollLeft = scroll_pos; } function get_min_date() { var task = self.tasks.reduce(function (acc, curr) { return curr._start.isSameOrBefore(acc._start) ? curr : acc; }); return task._start; } function make_grid() { make_grid_background(); make_grid_rows(); make_grid_header(); make_grid_ticks(); make_grid_highlights(); } function make_grid_background() { var grid_width = self.dates.length * self.config.column_width, grid_height = self.config.header_height + self.config.padding + (self.config.bar.height + self.config.padding) * self.tasks.length; self.canvas.rect(0, 0, grid_width, grid_height).addClass('grid-background').appendTo(self.element_groups.grid); self.canvas.attr({ height: grid_height + self.config.padding, width: '100%' }); } function make_grid_header() { var header_width = self.dates.length * self.config.column_width, header_height = self.config.header_height + 10; self.canvas.rect(0, 0, header_width, header_height).addClass('grid-header').appendTo(self.element_groups.grid); self.fixedDateCanvas.attr({ height: header_height, width: header_width }); } function make_grid_rows() { var rows = self.canvas.group().appendTo(self.element_groups.grid), lines = self.canvas.group().appendTo(self.element_groups.grid), row_width = self.dates.length * self.config.column_width, row_height = self.config.bar.height + self.config.padding; var row_y = self.config.header_height + self.config.padding / 2; var _iteratorNormalCompletion5 = true; var _didIteratorError5 = false; var _iteratorError5 = undefined; try { for (var _iterator5 = self.tasks[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { var task = _step5.value; // eslint-disable-line self.canvas.rect(0, row_y, row_width, row_height).addClass('grid-row').appendTo(rows); self.canvas.line(0, row_y + row_height, row_width, row_y + row_height).addClass('row-line').appendTo(lines); row_y += self.config.bar.height + self.config.padding; } } catch (err) { _didIteratorError5 = true; _iteratorError5 = err; } finally { try { if (!_iteratorNormalCompletion5 && _iterator5.return) { _iterator5.return(); } } finally { if (_didIteratorError5) { throw _iteratorError5; } } } } function make_grid_ticks() { var tick_x = 0, tick_y = self.config.header_height + self.config.padding / 2, tick_height = (self.config.bar.height + self.config.padding) * self.tasks.length; var _iteratorNormalCompletion6 = true; var _didIteratorError6 = false; var _iteratorError6 = undefined; try { for (var _iterator6 = self.dates[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) { var date = _step6.value; var tick_class = 'tick'; // thick tick for monday if (view_is('Day') && date.day() === 1) { tick_class += ' thick'; } // thick tick for first week if (view_is('Week') && date.date() >= 1 && date.date() < 8) { tick_class += ' thick'; } // thick ticks for quarters if (view_is('Month') && date.month() % 3 === 0) { tick_class += ' thick'; } self.canvas.path(_snapsvg2.default.format('M {x} {y} v {height}', { x: tick_x, y: tick_y, height: tick_height })).addClass(tick_class).appendTo(self.element_groups.grid); if (view_is('Month')) { tick_x += date.daysInMonth() * self.config.column_width / 30; } else { tick_x += self.config.column_width; } } } catch (err) { _didIteratorError6 = true; _iteratorError6 = err; } finally { try { if (!_iteratorNormalCompletion6 && _iterator6.return) { _iterator6.return(); } } finally { if (_didIteratorError6) { throw _iteratorError6; } } } } function make_grid_highlights() { // highlight today's date if (view_is('Day')) { var x = (0, _moment2.default)().startOf('day').diff(self.gantt_start, 'hours') / self.config.step * self.config.column_width; var y = 0; var width = self.config.column_width; var height = (self.config.bar.height + self.config.padding) * self.tasks.length + self.config.header_height + self.config.padding / 2; self.canvas.rect(x, y, width, height).addClass('today-highlight').appendTo(self.element_groups.grid); } } function make_dates() { var _iteratorNormalCompletion7 = true; var _didIteratorError7 = false; var _iteratorError7 = undefined; try { for (var _iterator7 = get_dates_to_draw()[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) { var date = _step7.value; self.canvas.text(date.lower_x, date.lower_y, date.lower_text).addClass('lower-text').appendTo(self.element_groups.date); if (date.upper_text) { var $upper_text = self.canvas.text(date.upper_x, date.upper_y, date.upper_text).addClass('upper-text').appendTo(self.element_groups.date); // remove out-of-bound dates if ($upper_text.getBBox().x2 > self.element_groups.grid.getBBox().width) { $upper_text.remove(); } } } } catch (err) { _didIteratorError7 = true; _iteratorError7 = err; } finally { try { if (!_iteratorNormalCompletion7 && _iterator7.return) { _iterator7.return(); } } finally { if (_didIteratorError7) { throw _iteratorError7; } } } } function get_dates_to_draw() { var last_date = null; var dates = self.dates.map(function (date, i) { var d = get_date_info(date, last_date, i); last_date = date; return d; }); return dates; } function get_date_info(date, last_date, i) { if (!last_date) { //last_date = date.clone().add(1, 'year'); last_date = date.clone().add(1, 'days'); } var date_text = { 'Quarter Day_lower': date.format('HH'), 'Half Day_lower': date.format('HH'), 'Day_lower': date.date() !== last_date.date() ? date.format('D') : '', 'Week_lower': date.month() !== last_date.month() ? date.format('D MMM') : date.format('D'), 'Month_lower': date.format('MMMM'), 'Quarter Day_upper': date.date() !== last_date.date() ? date.format('D MMM') : '', 'Half Day_upper': date.date() !== last_date.date() ? date.month() !== last_date.month() ? date.format('D MMM') : date.format('D') : '', 'Day_upper': date.month() !== last_date.month() ? date.format('MMMM') : '', 'Week_upper': date.month() !== last_date.month() ? date.format('MMMM') : '', 'Month_upper': date.year() !== last_date.year() ? date.format('YYYY') : '' }; var base_pos = { x: i * self.config.column_width, lower_y: self.config.header_height, upper_y: self.config.header_height - 25 }; var x_pos = { 'Quarter Day_lower': self.config.column_width * 4 / 2, 'Quarter Day_upper': 0, 'Half Day_lower': self.config.column_width * 2 / 2, 'Half Day_upper': 0, 'Day_lower': self.config.column_width / 2, 'Day_upper': self.config.column_width * 30 / 2, 'Week_lower': 0, 'Week_upper': self.config.column_width * 4 / 2, 'Month_lower': self.config.column_width / 2, 'Month_upper': self.config.column_width * 12 / 2 }; return { upper_text: date_text[self.config.view_mode + '_upper'], lower_text: date_text[self.config.view_mode + '_lower'], upper_x: base_pos.x + x_pos[self.config.view_mode + '_upper'], upper_y: base_pos.upper_y, lower_x: base_pos.x + x_pos[self.config.view_mode + '_lower'], lower_y: base_pos.lower_y }; } function make_arrows() { self._arrows = []; var _iteratorNormalCompletion8 = true; var _didIteratorError8 = false; var _iteratorError8 = undefined; try { var _loop = function _loop() { var task = _step8.value; var arrows = []; arrows = task.dependencies.map(function (dep) { var dependency = get_task(dep); if (!dependency) return; var arrow = (0, _Arrow2.default)(self, // gt self._bars[dependency._index], // from_task self._bars[task._index] // to_task ); self.element_groups.arrow.add(arrow.element); return arrow; // eslint-disable-line }).filter(function (arr) { return arr; }); // filter falsy values self._arrows = self._arrows.concat(arrows); }; for (var _iterator8 = self.tasks[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) { _loop(); } } catch (err) { _didIteratorError8 = true; _iteratorError8 = err; } finally { try { if (!_iteratorNormalCompletion8 && _iterator8.return) { _iterator8.return(); } } finally { if (_didIteratorError8) { throw _iteratorError8; } } } } function make_bars() { self._bars = self.tasks.map(function (task) { var bar = (0, _Bar2.default)(self, task); self.element_groups.bar.add(bar.group); return bar; }); } function map_arrows_on_bars() { var _iteratorNormalCompletion9 = true; var _didIteratorError9 = false; var _iteratorError9 = undefined; try { var _loop2 = function _loop2() { var bar = _step9.value; bar.arrows = self._arrows.filter(function (arrow) { return arrow.from_task.task.id === bar.task.id || arrow.to_task.task.id === bar.task.id; }); }; for (var _iterator9 = self._bars[Symbol.iterator](), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) { _loop2(); } } catch (err) { _didIteratorError9 = true; _iteratorError9 = err; } finally { try { if (!_iteratorNormalCompletion9 && _iterator9.return) { _iterator9.return(); } } finally { if (_didIteratorError9) { throw _iteratorError9; } } } } function bind_grid_click() { self.element_groups.grid.click(function () { unselect_all(); self.element_groups.details.selectAll('.details-wrapper').forEach(function (el) { return el.addClass('hide'); }); }); } function unselect_all() { self.canvas.selectAll('.bar-wrapper').forEach(function (el) { el.removeClass('active'); }); } function view_is(modes) { if (typeof modes === 'string') { return self.config.view_mode === modes; } else if (Array.isArray(modes)) { var _iteratorNormalCompletion10 = true; var _didIteratorError10 = false; var _iteratorError10 = undefined; try { for (var _iterator10 = modes[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) { var mode = _step10.value; if (self.config.view_mode === mode) return true; } } catch (err) { _didIteratorError10 = true; _iteratorError10 = err; } finally { try { if (!_iteratorNormalCompletion10 && _iterator10.return) { _iterator10.return(); } } finally { if (_didIteratorError10) { throw _iteratorError10; } } } return false; } } function get_task(id) { return self.tasks.find(function (task) { return task.id === id; }); } function get_bar(id) { return self._bars.find(function (bar) { return bar.task.id === id; }); } function generate_id(task) { return task.name + '_' + Math.random().toString(36).slice(2, 12); } function trigger_event(event, args) { if (self.config['on_' + event]) { self.config['on_' + event].apply(null, args); } } // find from: https://stackoverflow.com/questions/13382516/getting-scroll-bar-width-using-javascript function getScrollbarWidth() { var outer = document.createElement("div"); outer.style.visibility = "hidden"; outer.style.width = "100px"; outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps document.body.appendChild(outer); var widthNoScroll = outer.offsetWidth; // force scrollbars outer.style.overflow = "scroll"; // add innerdiv var inner = document.createElement("div"); inner.style.width = "100%"; outer.appendChild(inner); var widthWithScroll = inner.offsetWidth; // remove divs outer.parentNode.removeChild(outer); return widthNoScroll - widthWithScroll; } init(); return self; } module.exports = exports['default']; /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { // style-loader: Adds some css to the DOM by adding a