/* 18.3 Worksheets also covers Chartsheets
778204
function parse_cs_xml(data, opts, rels, wb, themes, styles) {
	if(!data) return data;
	/* 18.3.1.12 chartsheet CT_ChartSheet */
	if(!rels) rels = {'!id':{}};
	var s = {'!type':"chart", '!chart':null, '!rel':""};
	var m;

	/* 18.3.1.36 drawing CT_Drawing */
	if((m = data.match(/drawing r:id="(.*?)"/))) s['!rel'] = m[1];

	if(rels['!id'][s['!rel']]) s['!chart'] = rels['!id'][s['!rel']];
	return s;
}
843766
function all(sheet, nodes) {
  var result = []
  var length = nodes.length
  var index = -1

  while (++index < length) {
    result.push(visit(sheet, nodes[index]))
  }

  return result.join('')
}
736063
function parse_cs_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*::, themes, styles*/)/*:Worksheet*/ {
	if(!data) return data;
	/* 18.3.1.12 chartsheet CT_ChartSheet */
	if(!rels) rels = {'!id':{}};
	var s = {'!type':"chart", '!chart':null, '!rel':""};
	var m;

	/* 18.3.1.83 sheetPr CT_ChartsheetPr */
	var sheetPr = data.match(sheetprregex);
	if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx);

	/* 18.3.1.36 drawing CT_Drawing */
	if((m = data.match(/drawing r:id="(.*?)"/))) s['!rel'] = m[1];

	if(rels['!id'][s['!rel']]) s['!chart'] = rels['!id'][s['!rel']];
	return s;
}
417483
function slide11() {
		var slide = pptx.addNewSlide();
		slide.addNotes('API Docs: https://gitbrent.github.io/PptxGenJS/docs/api-charts.html');
		slide.addTable( [ [{ text:'Chart Examples: Area Chart', options:gOptsTextL },gOptsTextR] ], gOptsTabOpts );

		var arrDataTimeline2ser = [
			{
				name  : 'Actual Sales',
				labels: MONS,
				values: [1500, 4600, 5156, 3167, 8510, 8009, 6006, 7855, 12102, 12789, 10123, 15121]
			},
			{
				name  : 'Proj Sales',
				labels: MONS,
				values: [1000, 2600, 3456, 4567, 5010, 6009, 7006, 8855, 9102, 10789, 11123, 12121]
			}
		];

		// TOP-LEFT
		var optsChartLine1 = {
			x:0.5, y:0.6, w:'45%', h:3,
			catAxisLabelRotate: 45,
			catAxisOrientation:'maxMin', valAxisOrientation:'maxMin'
		};
		slide.addChart( pptx.charts.AREA, arrDataTimeline2ser, optsChartLine1 );

		// TOP-RIGHT
		var optsChartLine2 = { x:7, y:0.6, w:'45%', h:3,
			chartColors: ['0088CC', '99FFCC'],
			chartColorsOpacity: 25,
			valAxisLabelRotate: 5,
			dataBorder: {pt:2, color:'FFFFFF'},
			fill: 'D1E1F1'
		};
		slide.addChart( pptx.charts.AREA, arrDataTimeline2ser, optsChartLine2 );

		// BOTTOM-LEFT
		var optsChartLine3 = { x:0.5, y:4.0, w:'45%', h:3,
			chartColors: ['0088CC', '99FFCC'],
			chartColorsOpacity: 50,
			valAxisLabelFormatCode: '#,K'
		};
		slide.addChart( pptx.charts.AREA, arrDataTimeline2ser, optsChartLine3 );

		// BOTTOM-RIGHT
		var optsChartLine4 = { x:7, y:4.0, w:'45%', h:3,
			chartColors: ['CC8833', 'CCFF69'],
			chartColorsOpacity: 75
		};
		slide.addChart( pptx.charts.AREA, arrDataTimeline2ser, optsChartLine4 );
	}
458986
function () {
		var chart = this.chart,
			options = this.options,
			offsetLeft = options.offsetLeft || 0,
			offsetRight = options.offsetRight || 0,
			horiz = this.horiz,
			width,
			height,
			top,
			left;

		// Expose basic values to use in Series object and navigator
		this.left = left = pick(options.left, chart.plotLeft + offsetLeft);
		this.top = top = pick(options.top, chart.plotTop);
		this.width = width = pick(options.width, chart.plotWidth - offsetLeft + offsetRight);
		this.height = height = pick(options.height, chart.plotHeight);
		this.bottom = chart.chartHeight - height - top;
		this.right = chart.chartWidth - width - left;

		// Direction agnostic properties
		this.len = mathMax(horiz ? width : height, 0); // mathMax fixes #905
		this.pos = horiz ? left : top; // distance from SVG origin
	}
1180887
function(chartInstance, box) {
			if (!chartInstance.boxes) {
				chartInstance.boxes = [];
			}
			chartInstance.boxes.push(box);
		}
211121
function () {
		var chart = this,
			spacing = chart.spacing,
			margin = chart.margin;

		chart.plotTop = pick(margin[0], spacing[0]);
		chart.marginRight = pick(margin[1], spacing[1]);
		chart.marginBottom = pick(margin[2], spacing[2]);
		chart.plotLeft = pick(margin[3], spacing[3]);
		chart.axisOffset = [0, 0, 0, 0]; // top, right, bottom, left
		chart.clipOffset = [0, 0, 0, 0];
	}
226791
function () {
		var chart = this,
			axes = chart.axes,
			renderer = chart.renderer,
			options = chart.options;

		var labels = options.labels,
			credits = options.credits,
			creditsHref;

		// Title
		chart.setTitle();


		// Legend
		chart.legend = new Legend(chart, options.legend);

		chart.getStacks(); // render stacks

		// Get margins by pre-rendering axes
		// set axes scales
		each(axes, function (axis) {
			axis.setScale();
		});

		chart.getMargins();

		chart.maxTicks = null; // reset for second pass
		each(axes, function (axis) {
			axis.setTickPositions(true); // update to reflect the new margins
			axis.setMaxTicks();
		});
		chart.adjustTickAmounts();
		chart.getMargins(); // second pass to check for new labels


		// Draw the borders and backgrounds
		chart.drawChartBox();		


		// Axes
		if (chart.hasCartesianSeries) {
			each(axes, function (axis) {
				axis.render();
			});
		}

		// The series
		if (!chart.seriesGroup) {
			chart.seriesGroup = renderer.g('series-group')
				.attr({ zIndex: 3 })
				.add();
		}
		each(chart.series, function (serie) {
			serie.translate();
			serie.setTooltipPoints();
			serie.render();
		});

		// Labels
		if (labels.items) {
			each(labels.items, function (label) {
				var style = extend(labels.style, label.style),
					x = pInt(style.left) + chart.plotLeft,
					y = pInt(style.top) + chart.plotTop + 12;

				// delete to prevent rewriting in IE
				delete style.left;
				delete style.top;

				renderer.text(
					label.html,
					x,
					y
				)
				.attr({ zIndex: 2 })
				.css(style)
				.add();

			});
		}

		// Credits
		if (credits.enabled && !chart.credits) {
			creditsHref = credits.href;
			chart.credits = renderer.text(
				credits.text,
				0,
				0
			)
			.on('click', function () {
				if (creditsHref) {
					location.href = creditsHref;
				}
			})
			.attr({
				align: credits.position.align,
				zIndex: 8
			})
			.css(credits.style)
			.add()
			.align(credits.position);
		}

		// Set flag
		chart.hasRendered = true;

	}
238004
def get_worksheets_section(self):
        
        out = []
        bc = getToolByName(self.context, CATALOG_WORKSHEET_LISTING)
        query = {'portal_type': "Worksheet", }

        # Check if dashboard_cookie contains any values to query
        # elements by
        query = self._update_criteria_with_filters(query, 'worksheets')

        # Active Worksheets (all)
        total = self.search_count(query, bc.id)

        # Open worksheets
        name = _('Results pending')
        desc = _('Results pending')
        purl = 'worksheets?list_review_state=open'
        query['review_state'] = ['open', 'attachment_due']
        out.append(self._getStatistics(name, desc, purl, bc, query, total))

        # Worksheets to be verified
        name = _('To be verified')
        desc = _('To be verified')
        purl = 'worksheets?list_review_state=to_be_verified'
        query['review_state'] = ['to_be_verified', ]
        out.append(self._getStatistics(name, desc, purl, bc, query, total))

        # Worksheets verified
        name = _('Verified')
        desc = _('Verified')
        purl = 'worksheets?list_review_state=verified'
        query['review_state'] = ['verified', ]
        out.append(self._getStatistics(name, desc, purl, bc, query, total))

        # Chart with the evolution of WSs over a period, grouped by
        # periodicity
        outevo = self.fill_dates_evo(bc, query)
        out.append({'type':         'bar-chart-panel',
                    'name':         _('Evolution of Worksheets'),
                    'class':        'informative',
                    'description':  _('Evolution of Worksheets'),
                    'data':         json.dumps(outevo),
                    'datacolors':   json.dumps(self.get_colors_palette())})

        return {'id': 'worksheets',
                'title': _('Worksheets'),
                'panels': out}
465235
function Chart(options) {

	this.__proto__ = new Control();

	this.init = function(options) {
		this.type = options.type = 'Chart';
		this.parent = options.parent;
		this.defaults = {
			x:48, y:48, w:288, h:144,
			text: '',
			script: undefined,
			onload: undefined,
			fill: this.parent.fill,
			fill_highlight: this.parent.lighter(this.parent.stroke), 	// ??
			stroke: this.parent.stroke,
			'stroke-width': this.parent.control_stroke,
			fontsize: this.parent.fontsize,
			repeat: 0,
			running: 0,
			corner: this.parent.button_corner,
			subtype: undefined,
			r: this.w/2,		//?? chart??
			autorun: undefined,
			interpolate: 'step-after',	// vs. 'basis'
			ticks: 5,
			target: undefined,
			refresh: 0,
			ymax: undefined,
			ymin: undefined
		};
		//console.log('Chart defaults:', this.defaults);
		this.setoptions(options);
		this.render();		// render D3 chart
		var self = this;
		if (this.refresh) setInterval(function() { self.redraw.call(self); }, this.refresh);
		return this;
	};

	this.attr = function(attrs) {
		this.__proto__.attr.call(this);
		this.svg.attr(attrs);
	};

	this.render = function() {

		var margin = {top: 0, right: 0, bottom: 0, left: 0};
		var width = this.w - margin.left - margin.right;
		var height = this.h - margin.top - margin.bottom;

		var x = d3.scale.linear().range([0, width]);
		var y = d3.scale.linear().range([height, 0]);
		var color = d3.scale.category10();
		var xAxis = d3.svg.axis().scale(x).ticks(this.ticks).orient('bottom');
		var yAxis = d3.svg.axis().scale(y).ticks(this.ticks).orient('left');

		var line = d3.svg.line().interpolate(this.interpolate)
				.x(function(d) { return x(d.time); })
				.y(function(d) { return y(d.value); });

		var self = this;
		this.outerrect = this.parent.paper.rect(this.x, this.y, this.w, this.h, this.parent.button_corner)
			.attr({fill: this.fill, stroke: this.stroke, 'stroke-width':this.parent.control_stroke});
		this.elts.push(this.outerrect);

		this.label = this.parent.paper.text(this.x + (this.w/2), this.y + this.h + this.fontsize*2, this.text)
			.attr({fill:this.stroke, stroke:this.stroke, 'font-size': this.fontsize});
		this.textelts.push(this.label);

		this.sethandlers();

		this.svg = d3.select(this.parent.paper.canvas).append('g')
				.attr('width', width + margin.left + margin.right)
				.attr('height', height + margin.top + margin.bottom)
			.append('g')
				//.attr('transform', 'translate(' + (this.x+margin.left) + ',' + (this.y+margin.top) + ')');
				.attr('transform', 'translate(' + (this.x) + ',' + (this.y) + ')');

		d3.json('/d3/' + this.target, function(data) {

			// console.log('d3:', typeof data, data);

			color.domain(d3.keys(data[0]).filter(function(key) { return key !== 'time'; }));
			var values = color.domain().map(function(name) {
				return {
					name: name,
					values: data.map(function(d) {
						return {time: d.time, value: +d[name]};
					})
				};
			});

			x.domain(d3.extent(data, function(d) { return d.time; }));
			if (self.ymax !== undefined) y.domain([self.ymin, self.ymax]);
			else y.domain([
				d3.min(values, function(c) { return d3.min(c.values, function(v) { return v.value; }); }),
				d3.max(values, function(c) { return d3.max(c.values, function(v) { return v.value; }); })
			]);

			self.svgx = self.svg.append('g')
					.attr('class', 'x axis')
					.attr('transform', 'translate(0,' + height + ')')
					.attr('stroke', self.stroke)
					.attr('fill', self.stroke)
					.call(xAxis);

			self.svgy = self.svg.append('g')
					.attr('class', 'y axis')
					.attr('stroke', self.stroke)
					.attr('fill', self.stroke)
					.call(yAxis);
/* y axis label
				.append('text')
					.attr('transform', 'rotate(-90)')
					.attr('y', 6)
					.attr('dy', '.71em')
					.style('text-anchor', 'end')
					.attr('stroke', self.stroke)
					.attr('fill', self.stroke)
					.text(' ');
*/
			self.svgvalue = self.svg.selectAll('.value')
					.data(values)
				.enter().append('g')
					.attr('class', 'value');

			self.svgvalue.append('path')
					.attr('class', 'line')
					.attr('d', function(d) { return line(d.values); })
					.style('stroke', function(d) { return color(d.name); })
					.style('fill', self.fill)
					.style('stroke-width', self['stroke-width']);

			self.svgvalue.append('text')
					.datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
					.attr('transform', function(d) { return 'translate(' + x(d.value.time) + ',' + y(d.value.value) + ')'; })
					.attr('x', 3)
					.attr('dy', '.35em')
					.attr('stroke', self.stroke)
					.attr('fill', self.stroke)
					.text(function(d) { return d.name; });
		});
	};

	this.redraw = function() {
		if (this.svg) {
			var doomed_svg = this.svg;
			delete this.svg;
			this.render();
			doomed_svg.remove();
		}
	};

	this.remove = function() {
		this.__proto__.remove.call(this);
		this.svg.remove();
	};

	this.move = function(x, y) {
		this.x = x;
		this.y = y;
		this.outerrect.attr({x:this.x, y:this.y, width:this.w, height:this.h});
		this.label.attr({x:this.x + this.w/2, y:this.y + this.h + this.fontsize*2});

		var translation = ['translate(', this.x, ',', this.y,')'].join('');
		//console.log('translation:', translation)
		this.svg.attr('transform', translation);
	};

	this.handleClick = function(e) {
		if (this.repeat) {
			if (this.running) {
				this.running = false;
				clearInterval(this.intervalid);
				delete this.intervalid;
			} else {
				this.running = true;
				this.exec();
			}
		}
		else this.redraw();

		if (e) {
			e.preventDefault();
			e.stopPropagation();
		}
		return false;
	};

	this.setValue = function(value) {
		this.value = value;
		//this.label.attr({text: this.text + ': ' + this.value});
		var update = {id: this.id, value: this.value};
		this.fire('update', update);
	};

	return this.init(options || {});
}
1368085
function (additionalOptions) {
		var chart = this,
			chartCopy,
			sandbox,
			svg,
			seriesOptions,
			sourceWidth,
			sourceHeight,
			cssWidth,
			cssHeight,
			options = merge(chart.options, additionalOptions); // copy the options and add extra options

		// IE compatibility hack for generating SVG content that it doesn't really understand
		if (!doc.createElementNS) {
			/*jslint unparam: true*//* allow unused parameter ns in function below */
			doc.createElementNS = function (ns, tagName) {
				return doc.createElement(tagName);
			};
			/*jslint unparam: false*/
		}

		// create a sandbox where a new chart will be generated
		sandbox = createElement(DIV, null, {
			position: ABSOLUTE,
			top: '-9999em',
			width: chart.chartWidth + PX,
			height: chart.chartHeight + PX
		}, doc.body);

		// get the source size
		cssWidth = chart.renderTo.style.width;
		cssHeight = chart.renderTo.style.height;
		sourceWidth = options.exporting.sourceWidth ||
			options.chart.width ||
			(/px$/.test(cssWidth) && parseInt(cssWidth, 10)) ||
			600;
		sourceHeight = options.exporting.sourceHeight ||
			options.chart.height ||
			(/px$/.test(cssHeight) && parseInt(cssHeight, 10)) ||
			400;

		// override some options
		extend(options.chart, {
			animation: false,
			renderTo: sandbox,
			forExport: true,
			width: sourceWidth,
			height: sourceHeight
		});
		options.exporting.enabled = false; // hide buttons in print
		delete options.data; // #3004

		// prepare for replicating the chart
		options.series = [];
		each(chart.series, function (serie) {
			seriesOptions = merge(serie.options, {
				animation: false, // turn off animation
				enableMouseTracking: false,
				showCheckbox: false,
				visible: serie.visible
			});

			if (!seriesOptions.isInternal) { // used for the navigator series that has its own option set
				options.series.push(seriesOptions);
			}
		});

		// Axis options must be merged in one by one, since it may be an array or an object (#2022, #3900)
		if (additionalOptions) {
			each(['xAxis', 'yAxis'], function (axisType) {
				each(splat(additionalOptions[axisType]), function (axisOptions, i) {
					options[axisType][i] = merge(options[axisType][i], axisOptions);
				});
			});
		}

		// generate the chart copy
		chartCopy = new Highcharts.Chart(options, chart.callback);

		// reflect axis extremes in the export
		each(['xAxis', 'yAxis'], function (axisType) {
			each(chart[axisType], function (axis, i) {
				var axisCopy = chartCopy[axisType][i],
					extremes = axis.getExtremes(),
					userMin = extremes.userMin,
					userMax = extremes.userMax;

				if (axisCopy && (userMin !== UNDEFINED || userMax !== UNDEFINED)) {
					axisCopy.setExtremes(userMin, userMax, true, false);
				}
			});
		});

		// get the SVG from the container's innerHTML
		svg = chartCopy.container.innerHTML;

		// free up memory
		options = null;
		chartCopy.destroy();
		discardElement(sandbox);

		// sanitize
		svg = this.sanitizeSVG(svg);

		// IE9 beta bugs with innerHTML. Test again with final IE9.
		svg = svg.replace(/(url\(#highcharts-[0-9]+)&quot;/g, '$1')
			.replace(/&quot;/g, "'");

		return svg;
	}
618599
function slide17() {
		// powerpoint 2016 add secondary category axis labels
		// https://peltiertech.com/chart-with-a-dual-category-axis/

		var slide = pptx.addNewSlide();
		slide.addNotes('API Docs: https://gitbrent.github.io/PptxGenJS/docs/api-charts.html');
		slide.addTable( [ [{ text:'Chart Examples: Multi-Type Charts', options:gOptsTextL },gOptsTextR] ], gOptsTabOpts );

		function doStackedLine() {
			// TOP-RIGHT:
			var opts = {
				x: 7.0, y: 0.6, w: 6.0, h: 3.0,
				barDir: 'col',
				barGrouping: 'stacked',
				catAxisLabelColor: '0000CC',
				catAxisLabelFontFace: 'Arial',
				catAxisLabelFontSize: 12,
				catAxisOrientation: 'minMax',
				showLegend: false,
				showTitle: false,
				valAxisMaxVal: 100,
				valAxisMajorUnit: 10
			};

			var labels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'];
			var chartTypes = [
				{
					type: pptx.charts.BAR,
					data: [
						{
							name: 'Bottom',
							labels: labels,
							values: [17, 26, 53, 10, 4]
						},
						{
							name: 'Middle',
							labels: labels,
							values: [55, 40, 20, 30, 15]
						},
						{
							name: 'Top',
							labels: labels,
							values: [10, 22, 25, 35, 70]
						}
					],
					options: {
						barGrouping: 'stacked'
					}
				},
				{
					type: pptx.charts.LINE,
					data: [{
						name: 'Current',
						labels: labels,
						values: [25, 35, 55, 10, 5]
					}],
					options: {
						barGrouping: 'standard'
					}
				}
			];
			slide.addChart(chartTypes, opts);
		}

		function doColumnAreaLine() {
			var opts = {
				x: 0.6, y: 0.6, w: 6.0, h: 3.0,
				barDir: 'col',
				catAxisLabelColor: '666666',
				catAxisLabelFontFace: 'Arial',
				catAxisLabelFontSize: 12,
				catAxisOrientation: 'minMax',
				showLegend: false,
				showTitle: false,
				valAxisMaxVal: 100,
				valAxisMajorUnit: 10,

				valAxes:[
					{
						showValAxisTitle: true,
						valAxisTitle: 'Primary Value Axis'
					}, {
						showValAxisTitle: true,
						valAxisTitle: 'Secondary Value Axis',
						valGridLine: 'none'
					}
				],

				catAxes: [
					{
						catAxisTitle: 'Primary Category Axis'
					}, {
						catAxisHidden: true
					}
				]
			};

			var labels = ['April', 'May', 'June', 'July', 'August'];
			var chartTypes = [
				{
					type: pptx.charts.AREA,
					data: [{
						name: 'Current',
						labels: labels,
						values: [1, 4, 7, 2, 3]
					}],
					options: {
						chartColors: ['00FFFF'],
						barGrouping: 'standard',
						secondaryValAxis: !!opts.valAxes,
						secondaryCatAxis: !!opts.catAxes
					}
				}, {
					type: pptx.charts.BAR,
					data: [{
						name: 'Bottom',
						labels: labels,
						values: [17, 26, 53, 10, 4]
					}],
					options: {
						chartColors: ['0000FF'],
						barGrouping: 'stacked'
					}
				}, {
					type: pptx.charts.LINE,
					data: [{
						name: 'Current',
						labels: labels,
						values: [5, 3, 2, 4, 7]
					}],
					options: {
						barGrouping: 'standard',
						secondaryValAxis: !!opts.valAxes,
						secondaryCatAxis: !!opts.catAxes
					}
				}
			];
			slide.addChart(chartTypes, opts);
		}

		function doStackedDot() {
			// BOT-LEFT:
			var opts = {
				x: 0.6, y: 4.0, w: 6.0, h: 3.0,
				barDir: 'col',
				barGrouping: 'stacked',
				catAxisLabelColor: '999999',
				catAxisLabelFontFace: 'Arial',
				catAxisLabelFontSize: 14,
				catAxisOrientation: 'minMax',
				showLegend: false,
				showTitle: false,
				valAxisMaxVal: 100,
				valAxisMinVal: 0,
				valAxisMajorUnit: 20,

				lineSize: 0,
				lineDataSymbolSize: 20,
				lineDataSymbolLineSize: 2,
				lineDataSymbolLineColor: 'FF0000',

				//dataNoEffects: true,

				valAxes:[
					{
						showValAxisTitle: true,
						valAxisTitle: 'Primary Value Axis'
					}, {
						showValAxisTitle: true,
						valAxisTitle: 'Secondary Value Axis',
						catAxisOrientation  : 'maxMin',
						valAxisMajorUnit: 1,
						valAxisMaxVal: 10,
						valAxisMinVal: 1,
						valGridLine: 'none'
					}
				],
				catAxes: [
					{
						catAxisTitle: 'Primary Category Axis'
					}, {
						catAxisHidden: true
					}

				]
			};

			var labels = ['Q1', 'Q2', 'Q3', 'Q4', 'OT'];
			var chartTypes = [
				{
					type: pptx.charts.BAR,
					data: [{
						name: 'Bottom',
						labels: labels,
						values: [17, 26, 53, 10, 4]
					},
						{
							name: 'Middle',
							labels: labels,
							values: [55, 40, 20, 30, 15]
						},
						{
							name: 'Top',
							labels: labels,
							values: [10, 22, 25, 35, 70]
						}],
					options: {
						barGrouping: 'stacked'
					}
				}, {
					type: pptx.charts.LINE,
					data: [{
						name: 'Current',
						labels: labels,
						values: [5, 3, 2, 4, 7]
					}],
					options: {
						barGrouping: 'standard',
						secondaryValAxis: !!opts.valAxes,
						secondaryCatAxis: !!opts.catAxes,
						chartColors: ['FFFF00']
					}
				}
			];
			slide.addChart(chartTypes, opts);
		}

		function doBarCol() {
			// BOT-RGT:
			var opts = {
				x: 7, y: 4.0, w: 6.0, h: 3.0,
				barDir: 'col',
				barGrouping: 'stacked',
				catAxisLabelColor: '999999',
				catAxisLabelFontFace: 'Arial',
				catAxisLabelFontSize: 14,
				catAxisOrientation: 'minMax',
				showLegend: false,
				showTitle: false,
				valAxisMaxVal: 100,
				valAxisMinVal: 0,
				valAxisMajorUnit: 20,
				valAxes:[
					{
						showValAxisTitle: true,
						valAxisTitle: 'Primary Value Axis'
					}, {
						showValAxisTitle: true,
						valAxisTitle: 'Secondary Value Axis',
						catAxisOrientation  : 'maxMin',
						valAxisMajorUnit: 1,
						valAxisMaxVal: 10,
						valAxisMinVal: 1,
						valGridLine: 'none'
					}
				],
				catAxes: [
					{
						catAxisTitle: 'Primary Category Axis'
					}, {
						catAxisHidden: true
					}

				]
			};

			var labels = ['Q1', 'Q2', 'Q3', 'Q4', 'OT'];
			var chartTypes = [
				{
					type: pptx.charts.BAR,
					data: [{
						name: 'Bottom',
						labels: labels,
						values: [17, 26, 53, 10, 4]
					},
						{
							name: 'Middle',
							labels: labels,
							values: [55, 40, 20, 30, 15]
						},
						{
							name: 'Top',
							labels: labels,
							values: [10, 22, 25, 35, 70]
						}],
					options: {
						barGrouping: 'stacked'
					}
				}, {
					type: pptx.charts.BAR,
					data: [{
						name: 'Current',
						labels: labels,
						values: [5, 3, 2, 4, 7]
					}],
					options: {
						barDir: 'bar',
						barGrouping: 'standard',
						secondaryValAxis: !!opts.valAxes,
						secondaryCatAxis: !!opts.catAxes
					}
				}
			];
			slide.addChart(chartTypes, opts);
		}

		function readmeExample() {
			// for testing - not rendered in demo
			var labels = ['Q1', 'Q2', 'Q3', 'Q4', 'OT'];
			var chartTypes = [
				{
					type: pptx.charts.BAR,
					data: [{
						name: 'Projected',
						labels: labels,
						values: [17, 26, 53, 10, 4]
					}],
					options: {
						barDir: 'col'
					}
				}, {
					type: pptx.charts.LINE,
					data: [{
						name: 'Current',
						labels: labels,
						values: [5, 3, 2, 4, 7]
					}],
					options: {
						secondaryValAxis: true,
						secondaryCatAxis: true
					}
				}
			];
			var multiOpts = {
				x:1.0, y:1.0, w:6, h:6,
				valAxisMaxVal: 100,
				valAxisMinVal: 0,
				valAxisMajorUnit: 20,
				valAxes:[
					{
						showValAxisTitle: true,
						valAxisTitle: 'Primary Value Axis'
					}, {
						showValAxisTitle: true,
						valAxisTitle: 'Secondary Value Axis',
						valAxisMajorUnit: 1,
						valAxisMaxVal: 10,
						valAxisMinVal: 1,
						valGridLine: 'none'
					}
				],
				catAxes: [
					{
						catAxisTitle: 'Primary Category Axis'
					}, {
						catAxisHidden: true
					}

				]
			};

			slide.addChart(chartTypes, multiOpts);
		}

		doBarCol();
		doStackedDot();
		doColumnAreaLine();
		doStackedLine();
		//readmeExample();
	}
1236136
private function _buildWorksheetEschers()
	{
		// 1-based index to BstoreContainer
		$blipIndex = 0;
		$lastReducedSpId = 0;
		$lastSpId = 0;

		foreach ($this->_phpExcel->getAllsheets() as $sheet) {
			// sheet index
			$sheetIndex = $sheet->getParent()->getIndex($sheet);

			$escher = null;

			// check if there are any shapes for this sheet
			$filterRange = $sheet->getAutoFilter()->getRange();
			if (count($sheet->getDrawingCollection()) == 0 && empty($filterRange)) {
				continue;
			}

			// create intermediate Escher object
			$escher = new PHPExcel_Shared_Escher();

			// dgContainer
			$dgContainer = new PHPExcel_Shared_Escher_DgContainer();

			// set the drawing index (we use sheet index + 1)
			$dgId = $sheet->getParent()->getIndex($sheet) + 1;
			$dgContainer->setDgId($dgId);
			$escher->setDgContainer($dgContainer);

			// spgrContainer
			$spgrContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer();
			$dgContainer->setSpgrContainer($spgrContainer);

			// add one shape which is the group shape
			$spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer();
			$spContainer->setSpgr(true);
			$spContainer->setSpType(0);
			$spContainer->setSpId(($sheet->getParent()->getIndex($sheet) + 1) << 10);
			$spgrContainer->addChild($spContainer);

			// add the shapes

			$countShapes[$sheetIndex] = 0; // count number of shapes (minus group shape), in sheet

			foreach ($sheet->getDrawingCollection() as $drawing) {
				++$blipIndex;

				++$countShapes[$sheetIndex];

				// add the shape
				$spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer();

				// set the shape type
				$spContainer->setSpType(0x004B);
				// set the shape flag
				$spContainer->setSpFlag(0x02);

				// set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
				$reducedSpId = $countShapes[$sheetIndex];
				$spId = $reducedSpId
					| ($sheet->getParent()->getIndex($sheet) + 1) << 10;
				$spContainer->setSpId($spId);

				// keep track of last reducedSpId
				$lastReducedSpId = $reducedSpId;

				// keep track of last spId
				$lastSpId = $spId;

				// set the BLIP index
				$spContainer->setOPT(0x4104, $blipIndex);

				// set coordinates and offsets, client anchor
				$coordinates = $drawing->getCoordinates();
				$offsetX = $drawing->getOffsetX();
				$offsetY = $drawing->getOffsetY();
				$width = $drawing->getWidth();
				$height = $drawing->getHeight();

				$twoAnchor = PHPExcel_Shared_Excel5::oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height);

				$spContainer->setStartCoordinates($twoAnchor['startCoordinates']);
				$spContainer->setStartOffsetX($twoAnchor['startOffsetX']);
				$spContainer->setStartOffsetY($twoAnchor['startOffsetY']);
				$spContainer->setEndCoordinates($twoAnchor['endCoordinates']);
				$spContainer->setEndOffsetX($twoAnchor['endOffsetX']);
				$spContainer->setEndOffsetY($twoAnchor['endOffsetY']);

				$spgrContainer->addChild($spContainer);
			}

			// AutoFilters
			if(!empty($filterRange)){
				$rangeBounds = PHPExcel_Cell::rangeBoundaries($filterRange);
				$iNumColStart = $rangeBounds[0][0];
				$iNumColEnd = $rangeBounds[1][0];

				$iInc = $iNumColStart;
				while($iInc <= $iNumColEnd){
					++$countShapes[$sheetIndex];

					// create an Drawing Object for the dropdown
					$oDrawing  = new PHPExcel_Worksheet_BaseDrawing();
					// get the coordinates of drawing
					$cDrawing   = PHPExcel_Cell::stringFromColumnIndex($iInc - 1) . $rangeBounds[0][1];
					$oDrawing->setCoordinates($cDrawing);
					$oDrawing->setWorksheet($sheet);

					// add the shape
					$spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer();
					// set the shape type
					$spContainer->setSpType(0x00C9);
					// set the shape flag
					$spContainer->setSpFlag(0x01);

					// set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index)
					$reducedSpId = $countShapes[$sheetIndex];
					$spId = $reducedSpId
						| ($sheet->getParent()->getIndex($sheet) + 1) << 10;
					$spContainer->setSpId($spId);

					// keep track of last reducedSpId
					$lastReducedSpId = $reducedSpId;

					// keep track of last spId
					$lastSpId = $spId;

					$spContainer->setOPT(0x007F, 0x01040104); // Protection -> fLockAgainstGrouping
					$spContainer->setOPT(0x00BF, 0x00080008); // Text -> fFitTextToShape
					$spContainer->setOPT(0x01BF, 0x00010000); // Fill Style -> fNoFillHitTest
					$spContainer->setOPT(0x01FF, 0x00080000); // Line Style -> fNoLineDrawDash
					$spContainer->setOPT(0x03BF, 0x000A0000); // Group Shape -> fPrint

					// set coordinates and offsets, client anchor
					$endCoordinates = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::stringFromColumnIndex($iInc - 1));
					$endCoordinates .= $rangeBounds[0][1] + 1;

					$spContainer->setStartCoordinates($cDrawing);
					$spContainer->setStartOffsetX(0);
					$spContainer->setStartOffsetY(0);
					$spContainer->setEndCoordinates($endCoordinates);
					$spContainer->setEndOffsetX(0);
					$spContainer->setEndOffsetY(0);

					$spgrContainer->addChild($spContainer);
					$iInc++;
				}
			}

			// identifier clusters, used for workbook Escher object
			$this->_IDCLs[$dgId] = $lastReducedSpId;

			// set last shape index
			$dgContainer->setLastSpId($lastSpId);

			// set the Escher object
			$this->_writerWorksheets[$sheetIndex]->setEscher($escher);
		}
	}
693218
function() {
      var n = JSLitmus._tests.length, markers = [], data = [];
      var d, min = 0, max = -1e10;
      var normalize = jsl.$('test_normalize').checked;

      // Gather test data
      for (var i=0; i < JSLitmus._tests.length; i++) {
        var test = JSLitmus._tests[i];
        if (test.count) {
          var hz = test.getHz(normalize);
          var v = hz != Infinity ? hz : 0;
          data.push(v);
          markers.push('t' + jsl.escape(test.name + '(' + jsl.toLabel(hz)+ ')') + ',000000,0,' +
            markers.length + ',10');
          max = Math.max(v, max);
        }
      }
      if (markers.length <= 0) return null;

      // Build chart title
      var title = document.getElementsByTagName('title');
      title = (title && title.length) ? title[0].innerHTML : null;
      var chart_title = [];
      if (title) chart_title.push(title);
      chart_title.push('Ops/sec (' + platform + ')');

      // Build labels
      var labels = [jsl.toLabel(min), jsl.toLabel(max)];

      var w = 250, bw = 15;
      var bs = 5;
      var h = markers.length*(bw + bs) + 30 + chart_title.length*20;

      var params = {
        chtt: escape(chart_title.join('|')),
        chts: '000000,10',
        cht: 'bhg',                     // chart type
        chd: 't:' + data.join(','),     // data set
        chds: min + ',' + max,          // max/min of data
        chxt: 'x',                      // label axes
        chxl: '0:|' + labels.join('|'), // labels
        chsp: '0,1',
        chm: markers.join('|'),         // test names
        chbh: [bw, 0, bs].join(','),    // bar widths
        // chf: 'bg,lg,0,eeeeee,0,eeeeee,.5,ffffff,1', // gradient
        chs: w + 'x' + h
      };
      return 'http://chart.apis.google.com/chart?' + jsl.join(params, '=', '&');
    }
815691
function slide14() {
		var slide = pptx.addNewSlide();
		slide.addNotes('API Docs: https://gitbrent.github.io/PptxGenJS/docs/api-charts.html');
		slide.addTable( [ [{ text:'Chart Examples: XY Scatter Chart', options:gOptsTextL },gOptsTextR] ], gOptsTabOpts );

		var arrDataScatter1 = [
			{ name:'X-Axis',    values:[0,1,2,3,4,5,6,7,8,9] },
			{ name:'Y-Value 1', values:[13, 20, 21, 25] },
			{ name:'Y-Value 2', values:[21, 22, 25, 49] }
		];
		var arrDataScatter2 = [
			{ name:'X-Axis',   values:[1, 2, 3, 4, 5, 6] },
			{ name:'Airplane', values:[33, 20, 51, 65, 71, 75] },
			{ name:'Train',    values:[99, 88, 77, 89, 99, 99] },
			{ name:'Bus',      values:[21, 22, 25, 49, 59, 69] }
		];
		var arrDataScatterLabels = [
		    { name:'X-Axis',    values:[1, 10, 20, 30, 40, 50] },
		    { name:'Y-Value 1', values:[11, 23, 31, 45], labels:['Red 1', 'Red 2', 'Red 3', 'Red 4'] },
		    { name:'Y-Value 2', values:[21, 38, 47, 59], labels:['Blue 1', 'Blue 2', 'Blue 3', 'Blue 4'] }
		];

		// TOP-LEFT
		var optsChartScat1 = { x:0.5, y:0.6, w:'45%', h:3,
			valAxisTitle        : "Renters",
			valAxisTitleColor   : "428442",
			valAxisTitleFontSize: 14,
			showValAxisTitle    : true,
			lineSize: 0,
			catAxisTitle        : "Last 10 Months",
			catAxisTitleColor   : "428442",
			catAxisTitleFontSize: 14,
			showCatAxisTitle    : true
		};
		slide.addChart( pptx.charts.SCATTER, arrDataScatter1, optsChartScat1 );

		// TOP-RIGHT
		var optsChartScat2 = { x:7.0, y:0.6, w:'45%', h:3,
			fill: 'f1f1f1',
			showLegend: true,
			legendPos : 'b',

			lineSize  : 8,
			lineSmooth: true,
			lineDataSymbolSize: 12,
			lineDataSymbolLineColor: 'FFFFFF',

			chartColors: [ COLOR_RED, COLOR_AMB, COLOR_GRN, COLOR_UNK ],
			chartColorsOpacity: 25
		};
		slide.addChart( pptx.charts.SCATTER, arrDataScatter2, optsChartScat2 );

		// BOTTOM-LEFT: (Labels)
		var optsChartScat3 = { x:0.5, y:4.0, w:'45%', h:3,
			fill: 'f2f9fc',
			//catAxisOrientation: 'maxMin',
			//valAxisOrientation: 'maxMin',
			showCatAxisTitle: false,
			showValAxisTitle: false,
			lineSize: 0,

			catAxisTitle        : "Data Point Labels",
			catAxisTitleColor   : "0088CC",
			catAxisTitleFontSize: 14,
			showCatAxisTitle    : true,

			// Data Labels
			showLabel             : true, // Must be set to true or labels will not be shown
			dataLabelFormatScatter: 'custom', // Can be set to `custom` (default), `customXY`, or `XY`.
		};
		slide.addChart( pptx.charts.SCATTER, arrDataScatterLabels, optsChartScat3 );

		// BOTTOM-RIGHT
		var optsChartScat4 = { x:7.0, y:4.0, w:'45%', h:3 };
		slide.addChart( pptx.charts.SCATTER, arrDataScatter2, optsChartScat4 );
	}
1104454
def detect_worksheets(archive):
    """"""
    # content types has a list of paths but no titles
    # workbook has a list of titles and relIds but no paths
    # workbook_rels has a list of relIds and paths but no titles
    # rels = {'id':{'title':'', 'path':''} }
    content_types = read_content_types(archive)
    valid_sheets = dict((path, ct) for ct, path in content_types if ct == WORKSHEET_TYPE)
    rels = dict(read_rels(archive))
    for sheet in read_sheets(archive):
        rel = rels[sheet['id']]
        rel['title'] = sheet['name']
        rel['sheet_id'] = sheet['sheetId']
        rel['state'] = sheet.get('state', 'visible')
        if ("/" + rel['path'] in valid_sheets
            or "worksheets" in rel['path']): # fallback in case content type is missing
            yield rel
1229877
function(inst) {
		var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
			controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
			monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
			selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
			cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
			printDate, dRow, tbody, daySettings, otherMonth, unselectable,
			tempDate = new Date(),
			today = this._daylightSavingAdjust(
				new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
			isRTL = this._get(inst, "isRTL"),
			showButtonPanel = this._get(inst, "showButtonPanel"),
			hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
			navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
			numMonths = this._getNumberOfMonths(inst),
			showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
			stepMonths = this._get(inst, "stepMonths"),
			isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
			currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
				new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
			minDate = this._getMinMaxDate(inst, "min"),
			maxDate = this._getMinMaxDate(inst, "max"),
			drawMonth = inst.drawMonth - showCurrentAtPos,
			drawYear = inst.drawYear;

		if (drawMonth < 0) {
			drawMonth += 12;
			drawYear--;
		}
		if (maxDate) {
			maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
				drawMonth--;
				if (drawMonth < 0) {
					drawMonth = 11;
					drawYear--;
				}
			}
		}
		inst.drawMonth = drawMonth;
		inst.drawYear = drawYear;

		prevText = this._get(inst, "prevText");
		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
			this._getFormatConfig(inst)));

		prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
			"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
			" title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
			(hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>"));

		nextText = this._get(inst, "nextText");
		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
			this._getFormatConfig(inst)));

		next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
			"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
			" title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
			(hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>"));

		currentText = this._get(inst, "currentText");
		gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
		currentText = (!navigationAsDateFormat ? currentText :
			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));

		controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
			this._get(inst, "closeText") + "</button>" : "");

		buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
			(this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
			">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";

		firstDay = parseInt(this._get(inst, "firstDay"),10);
		firstDay = (isNaN(firstDay) ? 0 : firstDay);

		showWeek = this._get(inst, "showWeek");
		dayNames = this._get(inst, "dayNames");
		dayNamesMin = this._get(inst, "dayNamesMin");
		monthNames = this._get(inst, "monthNames");
		monthNamesShort = this._get(inst, "monthNamesShort");
		beforeShowDay = this._get(inst, "beforeShowDay");
		showOtherMonths = this._get(inst, "showOtherMonths");
		selectOtherMonths = this._get(inst, "selectOtherMonths");
		defaultDate = this._getDefaultDate(inst);
		html = "";
		dow;
		for (row = 0; row < numMonths[0]; row++) {
			group = "";
			this.maxRows = 4;
			for (col = 0; col < numMonths[1]; col++) {
				selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
				cornerClass = " ui-corner-all";
				calender = "";
				if (isMultiMonth) {
					calender += "<div class='ui-datepicker-group";
					if (numMonths[1] > 1) {
						switch (col) {
							case 0: calender += " ui-datepicker-group-first";
								cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
							case numMonths[1]-1: calender += " ui-datepicker-group-last";
								cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
							default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
						}
					}
					calender += "'>";
				}
				calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
					(/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
					(/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
					"</div><table class='ui-datepicker-calendar'><thead>" +
					"<tr>";
				thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
				for (dow = 0; dow < 7; dow++) { // days of the week
					day = (dow + firstDay) % 7;
					thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
						"<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
				}
				calender += thead + "</tr></thead><tbody>";
				daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
				if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
				}
				leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
				curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
				numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
				this.maxRows = numRows;
				printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
				for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
					calender += "<tr>";
					tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
						this._get(inst, "calculateWeek")(printDate) + "</td>");
					for (dow = 0; dow < 7; dow++) { // create date picker days
						daySettings = (beforeShowDay ?
							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
						otherMonth = (printDate.getMonth() !== drawMonth);
						unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
						tbody += "<td class='" +
							((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
							(otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
							((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
							(defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
							// or defaultDate is current printedDate and defaultDate is selectedDate
							" " + this._dayOverClass : "") + // highlight selected day
							(unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") +  // highlight unselectable days
							(otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
							(printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
							(printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
							((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
							(unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
							(otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
							(unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
							(printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
							(printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
							(otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
							"' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
						printDate.setDate(printDate.getDate() + 1);
						printDate = this._daylightSavingAdjust(printDate);
					}
					calender += tbody + "</tr>";
				}
				drawMonth++;
				if (drawMonth > 11) {
					drawMonth = 0;
					drawYear++;
				}
				calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
							((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
				group += calender;
			}
			html += group;
		}
		html += buttonPanel;
		inst._keyEvent = false;
		return html;
	}