Skip to main content
Back to examples
Popular features/Export to PDF, PNG, and print
Loading live demo…from dhtmlxcode.com
Popular features

Export to PDF, PNG, and print

Export the live chart to PDF or PNG through a page-setup panel, or print it with a stylesheet that hides the demo chrome and renders every row.

gantt.plugins({ export_api: true, tooltip: true });

gantt.config.date_format         = "%Y-%m-%d";
gantt.config.auto_types          = true;
gantt.config.open_tree_initially = true;
gantt.config.grid_resize         = true;
gantt.config.row_height          = 34;
gantt.config.bar_height          = 22;

/* ---------------------------------------------------------------------------
 *  DATASET
 * ------------------------------------------------------------------------ */
let demoData = {
	tasks: [
		{ id: 1, text: "Q3 delivery plan", type: "project", open: true },
		{ id: 10, text: "Platform", type: "project", parent: 1, open: true },
		{ id: 11, text: "Migrate to new auth service", parent: 10, start_date: "2026-07-06", duration: 10, progress: 1 },
		{ id: 12, text: "API gateway rollout",         parent: 10, start_date: "2026-07-20", duration: 8,  progress: 0.6 },
		{ id: 13, text: "Observability upgrade",       parent: 10, start_date: "2026-07-30", duration: 7,  progress: 0.3 },
		{ id: 14, text: "Database sharding",           parent: 10, start_date: "2026-07-06", duration: 12, progress: 1 },
		{ id: 15, text: "Rate limiting rollout",       parent: 10, start_date: "2026-07-22", duration: 6,  progress: 0.4 },
		{ id: 16, text: "Secrets vault migration",     parent: 10, start_date: "2026-08-04", duration: 5,  progress: 0 },
		{ id: 17, text: "CI/CD pipeline hardening",    parent: 10, start_date: "2026-08-11", duration: 8,  progress: 0 },
		{ id: 20, text: "Product", type: "project", parent: 1, open: true },
		{ id: 21, text: "Onboarding redesign",         parent: 20, start_date: "2026-07-13", duration: 9,  progress: 0.7 },
		{ id: 22, text: "Billing self-service",        parent: 20, start_date: "2026-07-27", duration: 12, progress: 0.2 },
		{ id: 23, text: "Mobile parity",               parent: 20, start_date: "2026-08-12", duration: 10, progress: 0 },
		{ id: 25, text: "Search revamp",               parent: 20, start_date: "2026-07-09", duration: 8,  progress: 1 },
		{ id: 26, text: "Notifications center",        parent: 20, start_date: "2026-07-24", duration: 9,  progress: 0.5 },
		{ id: 27, text: "Accessibility pass",          parent: 20, start_date: "2026-08-06", duration: 6,  progress: 0.3 },
		{ id: 28, text: "In-app pricing page",         parent: 20, start_date: "2026-08-17", duration: 7,  progress: 0 },
		{ id: 24, text: "Public beta",                 parent: 20, type: "milestone", start_date: "2026-08-28", progress: 0 },
		{ id: 30, text: "Go-to-market", type: "project", parent: 1, open: true },
		{ id: 31, text: "Launch content",              parent: 30, start_date: "2026-08-17", duration: 8,  progress: 0 },
		{ id: 32, text: "Sales enablement",            parent: 30, start_date: "2026-08-24", duration: 6,  progress: 0 },
		{ id: 34, text: "Analyst briefings",           parent: 30, start_date: "2026-07-27", duration: 7,  progress: 0.6 },
		{ id: 35, text: "Partner co-marketing",        parent: 30, start_date: "2026-08-10", duration: 9,  progress: 0.2 },
		{ id: 36, text: "Press kit and embargo plan",   parent: 30, start_date: "2026-08-19", duration: 5,  progress: 0 },
		{ id: 37, text: "Launch event logistics",      parent: 30, start_date: "2026-08-26", duration: 6,  progress: 0 },
		{ id: 33, text: "Q3 launch",                   parent: 30, type: "milestone", start_date: "2026-09-04", progress: 0 }
	],
	links: [
		{ id: 1, source: 11, target: 12, type: "0" }, { id: 2, source: 12, target: 13, type: "0" },
		{ id: 3, source: 21, target: 22, type: "0" }, { id: 4, source: 22, target: 23, type: "0" },
		{ id: 5, source: 23, target: 24, type: "0" }, { id: 6, source: 13, target: 31, type: "0" },
		{ id: 7, source: 24, target: 31, type: "0" }, { id: 8, source: 31, target: 32, type: "0" },
		{ id: 9, source: 32, target: 33, type: "0" }, { id: 10, source: 14, target: 15, type: "0" },
		{ id: 11, source: 15, target: 16, type: "0" }, { id: 12, source: 16, target: 17, type: "0" },
		{ id: 13, source: 25, target: 26, type: "0" }, { id: 14, source: 26, target: 27, type: "0" },
		{ id: 15, source: 27, target: 28, type: "0" }, { id: 16, source: 34, target: 35, type: "0" },
		{ id: 17, source: 35, target: 36, type: "0" }, { id: 18, source: 36, target: 37, type: "0" }
	]
};

gantt.config.columns = [
	{ name: "text",       label: "Task", tree: true, width: 240, resize: true, template: function (t) { return "<b>" + gantt.getWBSCode(t) + "</b> " + t.text; } },
	{ name: "start_date", label: "Start", align: "center", width: 100, resize: true },
	{ name: "duration",   label: "Days", align: "center", width: 56, resize: true },
	{ name: "add", width: 40, resize: true }
];
gantt.config.grid_width = 430;

gantt.templates.tooltip_text = function (start, end, task) {
	return "<b>" + task.text + "</b><br>" + Math.round((task.progress || 0) * 100) + "% complete";
};

/* ---------------------------------------------------------------------------
 *  ZOOM
 * ------------------------------------------------------------------------ */
gantt.config.scale_height = 50;
gantt.config.scales = [
	{ unit: "month", step: 1, format: "%F %Y" },
	{ unit: "week", step: 1, format: function (d) {
		return gantt.date.date_to_str("%d")(d);
	}
}];
let zoomNames = ["week", "month"];
gantt.ext.zoom.init({
	levels: [
		{ name: "week",  scale_height: 50, scales: [{ unit: "month", step: 1, format: "%F %Y" }, { unit: "week", step: 1, format: function (d) { return "Wk " + gantt.date.date_to_str("%W")(d); } }] },
		{ name: "month", scale_height: 50, scales: [{ unit: "year",  step: 1, format: "%Y" }, { unit: "month", step: 1, format: "%M" }] }
	],
	element: function () { return gantt.$root.querySelector(".gantt_task"); }
});
DHX.zoom.init(gantt, zoomNames, "zoom_seg", null);
function setZoom(name) { DHX.zoom.set(name); }

/* ---------------------------------------------------------------------------
 *  EXPORT OPTIONS
 * ------------------------------------------------------------------------ */
let exportOpts = { format: "A4", landscape: true, fit: false, header: "Q3 delivery plan", footer: "Confidential" };

function setOpt(key, value, btn) {
	exportOpts[key] = value;
	let seg = btn.parentNode;
	seg.querySelectorAll("button").forEach(function (b) { b.classList.remove("active"); });
	btn.classList.add("active");
	updateSummary();
}
function toggleFit() {
	exportOpts.fit = !exportOpts.fit;
	DHX.toggle.setById("fit_switch", exportOpts.fit);
	updateSummary();
}
function updateSummary() {
	DHX.ui.setText("opt_summary", exportOpts.format + " · " + (exportOpts.landscape ? "Landscape" : "Portrait") + (exportOpts.fit ? " · fit to page" : ""));
}

function buildSettings() {
	let settings = {
		header: exportOpts.header ? "<h3 style='font-family:Inter,Arial'>" + esc(exportOpts.header) + "</h3>" : "",
		footer: exportOpts.footer ? "<div style='font-family:Inter,Arial;color:#888'>" + esc(exportOpts.footer) + "</div>" : "",
		skin: darkTheme ? "dark" : "material",
		additional_settings: { format: exportOpts.format, landscape: exportOpts.landscape }
	};
	if (exportOpts.fit) settings.additional_settings.fit = "page";
	return settings;
}
function esc(t) { return String(t).replace(/[&<>"]/g, function (c) { return { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;" }[c]; }); }

function doExport(type) {
	let settings = buildSettings();
	settings.name = "q3-delivery-plan." + type;
	toast("Building " + type.toUpperCase() + " (" + exportOpts.format + ") ...");
	if (type === "pdf") gantt.exportToPDF(settings);
	else                gantt.exportToPNG(settings);
}

/* ---------------------------------------------------------------------------
 *  PRINT
 *
 *  Browsers do not reliably fragment the nested Gantt layout. In landscape
 *  mode Chromium may move the complete chart to page two and leave page one
 *  blank. To avoid that, the live chart is expanded with autosize="xy", cloned,
 *  and placed into explicit print-page slices.
 * ------------------------------------------------------------------------ */
let printSession = null;
let printRestoreTimer = null;

let PAPER_SIZES_MM = {
	A4:     { width: 210, height: 297 },
	A3:     { width: 297, height: 420 },
	Letter: { width: 215.9, height: 279.4 }
};

let PRINT_MARGIN_MM = 10;

function mmToPixels(value) {
	return value * 96 / 25.4;
}

function getPrintPageSize() {
	let paper = PAPER_SIZES_MM[exportOpts.format] || PAPER_SIZES_MM.A4;
	let width = paper.width;
	let height = paper.height;

	if (exportOpts.landscape) {
		let temporary = width;
		width = height;
		height = temporary;
	}

	return {
		width: width,
		height: height,
		printableWidth: Math.max(1, width - PRINT_MARGIN_MM * 2),
		printableHeight: Math.max(1, height - PRINT_MARGIN_MM * 2)
	};
}

function updatePrintPageRule() {
	let style = document.getElementById("native_print_page_style");
	if (!style) {
		style = document.createElement("style");
		style.id = "native_print_page_style";
		document.head.appendChild(style);
	}

	style.textContent =
		"@page { size: " + exportOpts.format + " " +
		(exportOpts.landscape ? "landscape" : "portrait") +
		"; margin: " + PRINT_MARGIN_MM + "mm; }";
}

function removePrintPages() {
	let pages = document.getElementById("gantt_print_pages");
	if (pages && pages.parentNode) {
		pages.parentNode.removeChild(pages);
	}
	document.body.classList.remove("print_pages_ready");
}

function restorePrintLayout() {
	if (!printSession) return;

	clearTimeout(printRestoreTimer);

	let session = printSession;
	let ganttNode = document.getElementById("gantt_here");
	printSession = null;

	removePrintPages();

	gantt.config.autosize = session.autosize;
	gantt.config.static_background = session.staticBackground;

	ganttNode.style.cssText = session.containerStyle;
	document.body.classList.remove("print_preparing");

	let pageStyle = document.getElementById("native_print_page_style");
	if (pageStyle) pageStyle.textContent = "";

	gantt.render();

	requestAnimationFrame(function () {
		gantt.scrollTo(session.scroll.x, session.scroll.y);
		window.scrollTo(session.windowScroll.x, session.windowScroll.y);
	});
}

function calculatePrintScale(fullWidth, fullHeight) {
	let page = getPrintPageSize();
	let widthScale = mmToPixels(page.printableWidth) / fullWidth;

	if (!exportOpts.fit) {
		return Math.min(1, widthScale);
	}

	let heightScale = mmToPixels(page.printableHeight) / fullHeight;
	return Math.min(1, widthScale, heightScale);
}

function cloneExpandedGantt(ganttNode, fullWidth, fullHeight) {
	let clone = ganttNode.cloneNode(true);

	clone.removeAttribute("id");
	clone.classList.add("gantt_print_clone");
	clone.style.cssText = ganttNode.style.cssText;
	clone.style.width = fullWidth + "px";
	clone.style.height = fullHeight + "px";
	clone.style.maxWidth = "none";
	clone.style.maxHeight = "none";
	clone.style.flex = "none";
	clone.style.zoom = "";

	return clone;
}

function buildPrintPages(ganttNode, fullWidth, fullHeight, scale) {
	removePrintPages();

	let page = getPrintPageSize();
	let printableWidthPx = mmToPixels(page.printableWidth);
	let printableHeightPx = mmToPixels(page.printableHeight);
	let scaledHeight = fullHeight * scale;
	let pageCount = exportOpts.fit
		? 1
		: Math.max(1, Math.ceil(scaledHeight / printableHeightPx));

	let pages = document.createElement("div");
	pages.id = "gantt_print_pages";
	pages.className = "gantt_print_pages";

	for (let pageIndex = 0; pageIndex < pageCount; pageIndex++) {
		let pageNode = document.createElement("section");
		pageNode.className = "gantt_print_page";
		pageNode.style.width = page.printableWidth + "mm";
		pageNode.style.height = page.printableHeight + "mm";

		let scaled = document.createElement("div");
		scaled.className = "gantt_print_scaled";
		scaled.style.top = -(pageIndex * printableHeightPx) + "px";
		scaled.style.width = fullWidth + "px";
		scaled.style.height = fullHeight + "px";
		scaled.style.transform = "scale(" + scale + ")";

		scaled.appendChild(cloneExpandedGantt(ganttNode, fullWidth, fullHeight));
		pageNode.appendChild(scaled);
		pages.appendChild(pageNode);
	}

	document.body.appendChild(pages);
	document.body.classList.add("print_pages_ready");

	return {
		pageCount: pageCount,
		scale: scale,
		printableWidthPx: printableWidthPx,
		printableHeightPx: printableHeightPx
	};
}

function preparePrintLayout() {
	let ganttNode = document.getElementById("gantt_here");

	printSession = {
		autosize: gantt.config.autosize,
		staticBackground: gantt.config.static_background,
		containerStyle: ganttNode.style.cssText,
		scroll: gantt.getScrollState(),
		windowScroll: { x: window.scrollX, y: window.scrollY }
	};

	document.body.classList.add("print_preparing");
	updatePrintPageRule();

	gantt.config.autosize = "xy";
	gantt.config.static_background = false;

	ganttNode.style.flex = "none";
	ganttNode.style.minHeight = "0";
	ganttNode.style.maxHeight = "none";
	ganttNode.style.maxWidth = "none";
	ganttNode.style.zoom = "";

	gantt.render();

	return new Promise(function (resolve) {
		requestAnimationFrame(function () {
			requestAnimationFrame(function () {
				let fullWidth = Math.max(
					ganttNode.scrollWidth,
					ganttNode.offsetWidth,
					ganttNode.getBoundingClientRect().width
				);
				let fullHeight = Math.max(
					ganttNode.scrollHeight,
					ganttNode.offsetHeight,
					ganttNode.getBoundingClientRect().height
				);
				let scale = calculatePrintScale(fullWidth, fullHeight);
				let result = buildPrintPages(ganttNode, fullWidth, fullHeight, scale);

				if (scale < 0.55) {
					toast(
						"Print scale is " + Math.round(scale * 100) +
						"%. A3 or PDF export will be easier to read."
					);
				} else if (result.pageCount > 1) {
					toast("Preparing " + result.pageCount + " print pages...");
				}

				resolve();
			});
		});
	});
}

function doPrint() {
	if (printSession) return;

	preparePrintLayout().then(function () {
		window.addEventListener("afterprint", restorePrintLayout, { once: true });

		requestAnimationFrame(function () {
			document.body.classList.remove("print_preparing");
			window.print();

			/* Fallback for browsers where afterprint is delayed or omitted. */
			setTimeout(restorePrintLayout, 0);
		});
	});

	printRestoreTimer = setTimeout(restorePrintLayout, 120000);
}

/* ---------------------------------------------------------------------------
 *  THEME + TOAST
 * ------------------------------------------------------------------------ */
let darkTheme = false;
function toggleTheme() {
	darkTheme = !darkTheme;
	document.getElementById("theme_sun").classList.toggle("dhx_hidden", darkTheme);
	document.getElementById("theme_moon").classList.toggle("dhx_hidden", !darkTheme);
	gantt.setSkin(darkTheme ? "dark" : "");
	gantt.render();
}

let toastTimer = null;
function toast(msg) {
	let el = document.getElementById("toast");
	el.textContent = msg;
	el.classList.add("show");
	clearTimeout(toastTimer);
	toastTimer = setTimeout(function () { el.classList.remove("show"); }, 2600);
}

/* ---------------------------------------------------------------------------
 *  INIT
 * ------------------------------------------------------------------------ */
DHX.dd.initClickOutside();
gantt.init("gantt_here");
gantt.parse(demoData);

DHX.zoom.set("week");
updateSummary();
<!DOCTYPE html>
<html lang="en">
<head>
	<meta http-equiv="Content-type" content="text/html; charset=utf-8">
	<title>Export to PDF / PNG &amp; print: dhtmlxGantt</title>
	<script src="../../codebase/dhtmlxgantt.js?v=10.0.0"></script>
	<link rel="stylesheet" href="../../codebase/dhtmlxgantt.css?v=10.0.0">
	<link rel="stylesheet" href="../common/demo-controls/dhx_controls.css">
	<script src="../common/demo-controls/dhx_controls.js"></script>
	<link rel="preconnect" href="https://fonts.googleapis.com">
	<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
	<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap">
	<style>
		body { display: flex; flex-direction: column; }
		#gantt_here { width: 100%; flex: 1 1 auto; min-height: 0; }

		.opt_menu { min-width: 230px; padding: 12px; }
		.opt_row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 7px 0; font: 500 13px var(--dhx-font); color: var(--dhx-ink-2); }
		.opt_row + .opt_row { border-top: 1px solid var(--dhx-line-2); }
		.opt_seg { display: inline-flex; background: #eef1f4; border-radius: 8px; padding: 2px; }
		.opt_seg button { border: none; background: none; cursor: pointer; height: 26px; padding: 0 10px; border-radius: 6px; font: 600 12px var(--dhx-font); color: var(--dhx-ink-2); }
		.opt_seg button.active { background: #fff; color: var(--dhx-ink); box-shadow: 0 1px 2px rgba(16,24,40,.12); }
		:root[data-gantt-theme="dark"] .opt_seg { background: #242a33; }
		:root[data-gantt-theme="dark"] .opt_seg button.active { background: #323a45; color: #fff; }
		.opt_text { width: 130px; height: 30px; border: 1px solid var(--dhx-line); border-radius: 7px; padding: 0 9px; font: 500 13px var(--dhx-font); background: var(--dhx-surface); color: var(--dhx-ink); }
		.note { font: 500 12px var(--dhx-font); color: var(--dhx-muted); }

		.toast {
			position: fixed; bottom: 48px; left: 50%; transform: translateX(-50%) translateY(20px);
			background: #1f2630; color: #fff; padding: 10px 16px; border-radius: 10px;
			font: 500 13px var(--dhx-font); box-shadow: 0 8px 24px rgba(16,24,40,.3);
			opacity: 0; pointer-events: none; transition: opacity .2s, transform .2s; z-index: 80;
		}
		.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

		body.print_preparing {
			cursor: progress;
		}

		.gantt_print_pages {
			display: none;
		}

		@media print {
			.dhx_header, .dhx_toolbar, .dhx_footer, .toast,
			body.print_pages_ready > #gantt_here {
				display: none !important;
			}

			html, body {
				display: block !important;
				overflow: visible !important;
				width: auto !important;
				height: auto !important;
				margin: 0 !important;
				padding: 0 !important;
			}

			.gantt_print_pages {
				display: block !important;
				width: 100%;
				margin: 0;
				padding: 0;
			}

			.gantt_print_page {
				position: relative;
				overflow: hidden;
				margin: 0;
				padding: 0;
				break-after: page;
				page-break-after: always;
			}

			.gantt_print_page:last-child {
				break-after: auto;
				page-break-after: auto;
			}

			.gantt_print_scaled {
				position: absolute;
				left: 0;
				transform-origin: top left;
			}

			.gantt_print_clone {
				display: block !important;
				flex: none !important;
				overflow: visible !important;
				margin: 0 !important;
			}

			.gantt_print_clone .gantt_container,
			.gantt_print_clone .gantt_layout_root,
			.gantt_print_clone .gantt_layout_cell,
			.gantt_print_clone .gantt_task,
			.gantt_print_clone .gantt_grid {
				overflow: visible !important;
			}

			.gantt_task_line, .gantt_line_wrapper > div {
				print-color-adjust: exact;
			}
		}
	</style>
</head>
<body>

<!-- Header -->
<div class="dhx_header">
	<div class="dhx_brand dhx_brand--static">
		<button class="dhx_brand__btn">
			<div class="dhx_brand__logo" style="background:linear-gradient(140deg,#ef4444,#f97316)">PD</div>
			<div class="dhx_brand__titles">
				<div class="dhx_brand__title-row"><span class="dhx_brand__title">Q3 delivery plan</span></div>
				<div class="dhx_brand__meta"><span class="dhx_brand__subtitle">Export &amp; print</span></div>
			</div>
		</button>
	</div>

	<div class="dhx_header__center">
		<div class="dhx_seg" id="zoom_seg">
			<button class="dhx_btn" data-zoom="week"  onclick="setZoom('week')">Week</button>
			<button class="dhx_btn" data-zoom="month" onclick="setZoom('month')">Month</button>
		</div>
	</div>

	<div class="dhx_header__right">
		<button class="dhx_btn dhx_btn--icon" title="Toggle theme" onclick="toggleTheme()">
			<svg class="dhx_ic" id="theme_sun" viewBox="0 0 24 24"><circle cx="12" cy="12" r="4.2"/><line x1="12" y1="2.5" x2="12" y2="5"/><line x1="12" y1="19" x2="12" y2="21.5"/><line x1="2.5" y1="12" x2="5" y2="12"/><line x1="19" y1="12" x2="21.5" y2="12"/><line x1="5.3" y1="5.3" x2="7" y2="7"/><line x1="17" y1="17" x2="18.7" y2="18.7"/><line x1="5.3" y1="18.7" x2="7" y2="17"/><line x1="17" y1="7" x2="18.7" y2="5.3"/></svg>
			<svg class="dhx_ic dhx_hidden" id="theme_moon" viewBox="0 0 24 24"><path d="M20 14.5A8 8 0 0 1 9.5 4a7 7 0 1 0 10.5 10.5z"/></svg>
		</button>
	</div>
</div>

<!-- Toolbar -->
<div class="dhx_toolbar">
	<div class="dhx_dd" id="dd_page">
		<button class="dhx_btn dhx_btn--surface" onclick="DHX.dd.toggle('dd_page')">
			Page setup <span class="dhx_caret"><svg class="dhx_ic dhx_ic--sm" viewBox="0 0 24 24"><polyline points="6 9 12 15 18 9"/></svg></span>
		</button>
		<div class="dhx_menu opt_menu" id="page_menu">
			<div class="opt_row">Page size
				<span class="opt_seg" id="seg_format">
					<button class="active" data-format="A4"     onclick="setOpt('format','A4',this)">A4</button>
					<button data-format="A3"     onclick="setOpt('format','A3',this)">A3</button>
					<button data-format="Letter" onclick="setOpt('format','Letter',this)">Letter</button>
				</span>
			</div>
			<div class="opt_row">Orientation
				<span class="opt_seg" id="seg_orient">
					<button class="active" data-landscape="true"  onclick="setOpt('landscape',true,this)">Landscape</button>
					<button data-landscape="false" onclick="setOpt('landscape',false,this)">Portrait</button>
				</span>
			</div>
			<div class="opt_row">Fit to one page
				<label class="dhx_toggle" style="height:30px" onclick="toggleFit()">
					<span class="dhx_toggle__track" id="fit_switch"></span>
				</label>
			</div>
			<div class="opt_row">Header
				<input class="opt_text" id="hdr_text" value="Q3 delivery plan" oninput="exportOpts.header = this.value">
			</div>
			<div class="opt_row">Footer
				<input class="opt_text" id="ftr_text" value="Confidential" oninput="exportOpts.footer = this.value">
			</div>
		</div>
	</div>

	<button class="dhx_btn dhx_btn--primary" onclick="doExport('pdf')">
		<svg class="dhx_ic" viewBox="0 0 24 24"><path d="M12 3v12"/><polyline points="8 11 12 15 16 11"/><path d="M5 19h14"/></svg>
		Export PDF
	</button>
	<button class="dhx_btn dhx_btn--surface" onclick="doExport('png')">Export PNG</button>
	<button class="dhx_btn dhx_btn--surface" onclick="doPrint()">
		<svg class="dhx_ic" viewBox="0 0 24 24"><polyline points="6 9 6 3 18 3 18 9"/><path d="M6 18H4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-2"/><rect x="6" y="14" width="12" height="7"/></svg>
		Print
	</button>

	<div class="dhx_spacer"></div>
	<span class="note" id="opt_summary"></span>
</div>

<div id="gantt_here"></div>

<div class="toast" id="toast"></div>


</body>
</html>