xref: /online/loleaflet/src/control/Control.Toolbar.js (revision f7f4464b3c835ccaacf5519ad7ef9ef0bc98d668)
1/* -*- js-indent-level: 8; fill-column: 100 -*- */
2/*
3 * LibreOffice Online toolbar
4 */
5
6/* global $ w2ui vex _ */
7/*eslint indent: [error, "tab", { "outerIIFEBody": 0 }]*/
8(function(global) {
9
10var map;
11
12function _cancelSearch() {
13	var toolbar = window.mode.isMobile() ? w2ui['searchbar'] : w2ui['actionbar'];
14	var searchInput = L.DomUtil.get('search-input');
15	map.resetSelection();
16	toolbar.hide('cancelsearch');
17	toolbar.disable('searchprev');
18	toolbar.disable('searchnext');
19	searchInput.value = '';
20	if (window.mode.isMobile()) {
21		searchInput.focus();
22		// odd, but on mobile we need to invoke it twice
23		toolbar.hide('cancelsearch');
24	}
25
26	map._onGotFocus();
27}
28
29function getUNOCommand(unoData) {
30	if (typeof unoData !== 'object')
31		return unoData;
32
33	if (!map._clip)
34		return unoData.textCommand;
35
36	var selectionType = map._clip._selectionType;
37
38	if (!selectionType || selectionType === 'text')
39		return unoData.textCommand;
40
41	return unoData.objectCommand;
42}
43
44function onClose() {
45	if (window.ThisIsAMobileApp) {
46		window.postMobileMessage('BYE');
47	} else {
48		map.fire('postMessage', {msgId: 'close', args: {EverModified: map._everModified, Deprecated: true}});
49		map.fire('postMessage', {msgId: 'UI_Close', args: {EverModified: map._everModified}});
50	}
51	if (!map._disableDefaultAction['UI_Close']) {
52		map.remove();
53	}
54}
55
56function onClick(e, id, item) {
57	if (w2ui['editbar'].get(id) !== null) {
58		var toolbar = w2ui['editbar'];
59		item = toolbar.get(id);
60	}
61	else if ('actionbar' in w2ui && w2ui['actionbar'].get(id) !== null) {
62		toolbar = w2ui['actionbar'];
63		item = toolbar.get(id);
64	}
65	else if (w2ui['searchbar'].get(id) !== null) {
66		toolbar = w2ui['searchbar'];
67		item = toolbar.get(id);
68	}
69	else {
70		throw new Error('unknown id: ' + id);
71	}
72
73	if (id === 'sidebar' || id === 'modifypage' || id === 'slidechangewindow' || id === 'customanimation' || id === 'masterslidespanel') {
74		window.initSidebarState = true;
75	}
76
77	// In the iOS app we don't want clicking on the toolbar to pop up the keyboard.
78	if (!window.ThisIsTheiOSApp && id !== 'zoomin' && id !== 'zoomout' && id !== 'mobile_wizard' && id !== 'insertion_mobile_wizard') {
79		map.focus(map.canAcceptKeyboardInput()); // Maintain same keyboard state.
80	}
81
82	if (item.disabled) {
83		return;
84	}
85
86	if (item.postmessage && item.type === 'button') {
87		map.fire('postMessage', {msgId: 'Clicked_Button', args: {Id: item.id} });
88	}
89	else if (item.uno) {
90		if (item.unosheet && map.getDocType() === 'spreadsheet') {
91			map.toggleCommandState(item.unosheet);
92		}
93		else {
94			map.toggleCommandState(getUNOCommand(item.uno));
95		}
96	}
97	else if (id === 'print') {
98		map.print();
99	}
100	else if (id === 'save') {
101		// Save only when not read-only.
102		if (!map.isPermissionReadOnly()) {
103			map.fire('postMessage', {msgId: 'UI_Save'});
104			if (!map._disableDefaultAction['UI_Save']) {
105				map.save(false /* An explicit save should terminate cell edit */, false /* An explicit save should save it again */);
106			}
107		}
108	}
109	else if (id === 'repair') {
110		map._socket.sendMessage('commandvalues command=.uno:DocumentRepair');
111	}
112	else if (id === 'showsearchbar') {
113		$('#toolbar-down').hide();
114		$('#tb_editbar_item_showsearchbar .w2ui-button').removeClass('over');
115		$('#toolbar-search').show();
116		L.DomUtil.get('search-input').focus();
117	}
118	else if ((id === 'presentation' || id === 'fullscreen-presentation') && map.getDocType() === 'presentation') {
119		map.fire('fullscreen');
120	}
121	else if (id === 'insertannotation') {
122		map.insertComment();
123	}
124	else if (id === 'insertgraphic' || item.id === 'localgraphic') {
125		L.DomUtil.get('insertgraphic').click();
126	}
127	else if (item.id === 'remotegraphic') {
128		map.fire('postMessage', {msgId: 'UI_InsertGraphic'});
129	}
130	else if (id === 'fontcolor' && typeof e.color === 'undefined') {
131		map.fire('mobilewizard', getColorPickerData('Font Color'));
132	}
133	else if (id === 'backcolor' && typeof e.color === 'undefined') {
134		map.fire('mobilewizard', getColorPickerData('Highlight Color'));
135	}
136	else if (id === 'fontcolor' && typeof e.color !== 'undefined') {
137		onColorPick(id, e.color);
138	}
139	else if (id === 'backcolor' && typeof e.color !== 'undefined') {
140		onColorPick(id, e.color);
141	}
142	else if (id === 'backgroundcolor' && typeof e.color !== 'undefined') {
143		onColorPick(id, e.color);
144	}
145	else if (id === 'fold' || id === 'hamburger-tablet') {
146		map.uiManager.toggleMenubar();
147	}
148	else if (id === 'close' || id === 'closemobile') {
149		map.uiManager.enterReadonlyOrClose();
150	}
151	else if (id === 'link') {
152		map.showHyperlinkDialog();
153	}
154	else if (id === 'languagecode') {
155		map.fire('languagedialog');
156	}
157}
158
159function _setBorders(left, right, bottom, top, horiz, vert, color) {
160	var params = {
161		OuterBorder: {
162			type : '[]any',
163			value : [
164				{ type : 'com.sun.star.table.BorderLine2', value : { Color : { type : 'com.sun.star.util.Color', value : color }, InnerLineWidth : { type : 'short', value : 0 }, OuterLineWidth : { type : 'short', value : left }, LineDistance : { type : 'short', value : 0 },  LineStyle : { type : 'short', value : 0 }, LineWidth : { type : 'unsigned long', value : 0 } } },
165				{ type : 'com.sun.star.table.BorderLine2', value : { Color : { type : 'com.sun.star.util.Color', value : color }, InnerLineWidth : { type : 'short', value : 0 }, OuterLineWidth : { type : 'short', value : right }, LineDistance : { type : 'short', value : 0 },  LineStyle : { type : 'short', value : 0 }, LineWidth : { type : 'unsigned long', value : 0 } } },
166				{ type : 'com.sun.star.table.BorderLine2', value : { Color : { type : 'com.sun.star.util.Color', value : color }, InnerLineWidth : { type : 'short', value : 0 }, OuterLineWidth : { type : 'short', value : bottom }, LineDistance : { type : 'short', value : 0 },  LineStyle : { type : 'short', value : 0 }, LineWidth : { type : 'unsigned long', value : 0 } } },
167				{ type : 'com.sun.star.table.BorderLine2', value : { Color : { type : 'com.sun.star.util.Color', value : color }, InnerLineWidth : { type : 'short', value : 0 }, OuterLineWidth : { type : 'short', value : top }, LineDistance : { type : 'short', value : 0 },  LineStyle : { type : 'short', value : 0 }, LineWidth : { type : 'unsigned long', value : 0 } } },
168				{ type : 'long', value : 0 },
169				{ type : 'long', value : 0 },
170				{ type : 'long', value : 0 },
171				{ type : 'long', value : 0 },
172				{ type : 'long', value : 0 }
173			]
174		},
175		InnerBorder: {
176			type : '[]any',
177			value : [
178				{ type : 'com.sun.star.table.BorderLine2', value : { Color : { type : 'com.sun.star.util.Color', value : color }, InnerLineWidth : { type : 'short', value : 0 }, OuterLineWidth : { type : 'short', value : horiz }, LineDistance : { type : 'short', value : 0 },  LineStyle : { type : 'short', value : 0 }, LineWidth : { type : 'unsigned long', value : 0 } } },
179				{ type : 'com.sun.star.table.BorderLine2', value : { Color : { type : 'com.sun.star.util.Color', value : color }, InnerLineWidth : { type : 'short', value : 0 }, OuterLineWidth : { type : 'short', value : vert }, LineDistance : { type : 'short', value : 0 },  LineStyle : { type : 'short', value : 0 }, LineWidth : { type : 'unsigned long', value : 0 } } },
180				{ type : 'short', value : 0 },
181				{ type : 'short', value : 127 },
182				{ type : 'long', value : 0 }
183			]
184		}};
185	map.sendUnoCommand('.uno:SetBorderStyle', params);
186}
187
188// close the popup
189function closePopup() {
190	if ($('#w2ui-overlay-editbar').length > 0) {
191		$('#w2ui-overlay-editbar').removeData('keepOpen')[0].hide();
192	}
193	map.focus();
194}
195
196function setBorderStyle(num, color) {
197	if (color === undefined)
198		color = 0; // black
199	else if (color.startsWith('#'))
200		color = parseInt('0x' + color.substring(1, color.length));
201
202	switch (num) {
203	case 0: map.sendUnoCommand('.uno:FormatCellBorders'); break;
204
205	case 1: _setBorders(0, 0, 0, 0, 0, 0, color); break;
206	case 2: _setBorders(1, 0, 0, 0, 0, 0, color); break;
207	case 3: _setBorders(0, 1, 0, 0, 0, 0, color); break;
208	case 4: _setBorders(1, 1, 0, 0, 0, 0, color); break;
209
210	case 5: _setBorders(0, 0, 0, 1, 0, 0, color); break;
211	case 6: _setBorders(0, 0, 1, 0, 0, 0, color); break;
212	case 7: _setBorders(0, 0, 1, 1, 0, 0, color); break;
213	case 8: _setBorders(1, 1, 1, 1, 0, 0, color); break;
214
215	case 9:  _setBorders(0, 0, 1, 1, 1, 0, color); break;
216	case 10: _setBorders(1, 1, 1, 1, 1, 0, color); break;
217	case 11: _setBorders(1, 1, 1, 1, 0, 1, color); break;
218	case 12: _setBorders(1, 1, 1, 1, 1, 1, color); break;
219
220	default: console.log('ignored border: ' + num);
221	}
222
223	// TODO we may consider keeping it open in the future if we add border color
224	// and style to this popup too
225	closePopup();
226}
227
228global.setBorderStyle = setBorderStyle;
229
230function setConditionalFormatIconSet(num) {
231	var params = {
232		IconSet: {
233			type : 'short',
234			value : num
235		}};
236	map.sendUnoCommand('.uno:IconSetFormatDialog', params);
237
238	closePopup();
239}
240
241global.setConditionalFormatIconSet = setConditionalFormatIconSet;
242
243function getConditionalFormatMenuHtml() {
244	return '<table id="conditionalformatmenu-grid"><tr>' +
245	'<td class="w2ui-tb-image w2ui-icon iconset00" onclick="setConditionalFormatIconSet(0)"/><td class="w2ui-tb-image w2ui-icon iconset01" onclick="setConditionalFormatIconSet(1)"/><td class="w2ui-tb-image w2ui-icon iconset02" onclick="setConditionalFormatIconSet(2)"/></tr><tr>' +
246	'<td class="w2ui-tb-image w2ui-icon iconset03" onclick="setConditionalFormatIconSet(3)"/><td class="w2ui-tb-image w2ui-icon iconset04" onclick="setConditionalFormatIconSet(4)"/><td class="w2ui-tb-image w2ui-icon iconset05" onclick="setConditionalFormatIconSet(5)"/></tr><tr>' +
247	'<td class="w2ui-tb-image w2ui-icon iconset06" onclick="setConditionalFormatIconSet(6)"/><td class="w2ui-tb-image w2ui-icon iconset08" onclick="setConditionalFormatIconSet(8)"/><td class="w2ui-tb-image w2ui-icon iconset09" onclick="setConditionalFormatIconSet(9)"/></tr><tr>' + // iconset07 deliberately left out, see the .css for the reason
248	'<td class="w2ui-tb-image w2ui-icon iconset10" onclick="setConditionalFormatIconSet(10)"/><td class="w2ui-tb-image w2ui-icon iconset11" onclick="setConditionalFormatIconSet(11)"/><td class="w2ui-tb-image w2ui-icon iconset12" onclick="setConditionalFormatIconSet(12)"/></tr><tr>' +
249	'<td class="w2ui-tb-image w2ui-icon iconset13" onclick="setConditionalFormatIconSet(13)"/><td class="w2ui-tb-image w2ui-icon iconset14" onclick="setConditionalFormatIconSet(14)"/><td class="w2ui-tb-image w2ui-icon iconset15" onclick="setConditionalFormatIconSet(15)"/></tr><tr>' +
250	'<td class="w2ui-tb-image w2ui-icon iconset16" onclick="setConditionalFormatIconSet(16)"/><td class="w2ui-tb-image w2ui-icon iconset17" onclick="setConditionalFormatIconSet(17)"/><td class="w2ui-tb-image w2ui-icon iconset18" onclick="setConditionalFormatIconSet(18)"/></tr><tr>' +
251	'<td class="w2ui-tb-image w2ui-icon iconset19" onclick="setConditionalFormatIconSet(19)"/><td class="w2ui-tb-image w2ui-icon iconset20" onclick="setConditionalFormatIconSet(20)"/><td class="w2ui-tb-image w2ui-icon iconset21" onclick="setConditionalFormatIconSet(21)"/></tr></table>';
252}
253
254global.getConditionalFormatMenuHtml = getConditionalFormatMenuHtml;
255
256function getInsertTablePopupHtml() {
257	return '<div id="inserttable-wrapper">\
258					<div id="inserttable-popup" class="inserttable-pop ui-widget ui-corner-all">\
259						<div class="inserttable-grid"></div>\
260						<div id="inserttable-status" class="loleaflet-font" style="padding: 5px;"><br/></div>\
261					</div>\
262				</div>';
263}
264
265function insertTable() {
266	var rows = 10;
267	var cols = 10;
268	var $grid = $('.inserttable-grid');
269	var $status = $('#inserttable-status');
270
271	// init
272	for (var r = 0; r < rows; r++) {
273		var $row = $('<div/>').addClass('row');
274		$grid.append($row);
275		for (var c = 0; c < cols; c++) {
276			var $col = $('<div/>').addClass('col');
277			$row.append($col);
278		}
279	}
280
281	// events
282	$grid.on({
283		mouseover: function () {
284			var col = $(this).index() + 1;
285			var row = $(this).parent().index() + 1;
286			$('.col').removeClass('bright');
287			$('.row:nth-child(-n+' + row + ') .col:nth-child(-n+' + col + ')')
288			.addClass('bright');
289			$status.html(col + 'x' + row);
290
291		},
292		click: function() {
293			var col = $(this).index() + 1;
294			var row = $(this).parent().index() + 1;
295			$('.col').removeClass('bright');
296			$status.html('<br/>');
297			var msg = 'uno .uno:InsertTable {' +
298				' "Columns": { "type": "long","value": '
299				+ col +
300				' }, "Rows": { "type": "long","value": '
301				+ row + ' }}';
302
303			map._socket.sendMessage(msg);
304
305			closePopup();
306		}
307	}, '.col');
308}
309
310var shapes = {
311	'Basic Shapes': [
312		{img: 'basicshapes_rectangle', uno: 'BasicShapes.rectangle'},
313		{img: 'basicshapes_round-rectangle', uno: 'BasicShapes.round-rectangle'},
314		{img: 'basicshapes_quadrat', uno: 'BasicShapes.quadrat'},
315		{img: 'basicshapes_round-quadrat', uno: 'BasicShapes.round-quadrat'},
316		{img: 'basicshapes_circle', uno: 'BasicShapes.circle'},
317		{img: 'basicshapes_ellipse', uno: 'BasicShapes.ellipse'},
318
319		{img: 'basicshapes_circle-pie', uno: 'BasicShapes.circle-pie'},
320		{img: 'basicshapes_isosceles-triangle', uno: 'BasicShapes.isosceles-triangle'},
321		{img: 'basicshapes_right-triangle', uno: 'BasicShapes.right-triangle'},
322		{img: 'basicshapes_trapezoid', uno: 'BasicShapes.trapezoid'},
323		{img: 'basicshapes_diamond', uno: 'BasicShapes.diamond'},
324		{img: 'basicshapes_parallelogram', uno: 'BasicShapes.parallelogram'},
325
326		{img: 'basicshapes_pentagon', uno: 'BasicShapes.pentagon'},
327		{img: 'basicshapes_hexagon', uno: 'BasicShapes.hexagon'},
328		{img: 'basicshapes_octagon', uno: 'BasicShapes.octagon'},
329		{img: 'basicshapes_cross', uno: 'BasicShapes.cross'},
330		{img: 'basicshapes_ring', uno: 'BasicShapes.ring'},
331		{img: 'basicshapes_block-arc', uno: 'BasicShapes.block-arc'},
332
333		{img: 'basicshapes_can', uno: 'BasicShapes.can'},
334		{img: 'basicshapes_cube', uno: 'BasicShapes.cube'},
335		{img: 'basicshapes_paper', uno: 'BasicShapes.paper'},
336		{img: 'basicshapes_frame', uno: 'BasicShapes.frame'}
337	],
338
339	'Symbol Shapes':  [
340		{img: 'symbolshapes', uno: 'SymbolShapes.smiley'},
341		{img: 'symbolshapes_sun', uno: 'SymbolShapes.sun'},
342		{img: 'symbolshapes_moon', uno: 'SymbolShapes.moon'},
343		{img: 'symbolshapes_lightning', uno: 'SymbolShapes.lightning'},
344		{img: 'symbolshapes_heart', uno: 'SymbolShapes.heart'},
345		{img: 'symbolshapes_flower', uno: 'SymbolShapes.flower'},
346
347		{img: 'symbolshapes_cloud', uno: 'SymbolShapes.cloud'},
348		{img: 'symbolshapes_forbidden', uno: 'SymbolShapes.forbidden'},
349		{img: 'symbolshapes_puzzle', uno: 'SymbolShapes.puzzle'},
350		{img: 'symbolshapes_bracket-pair', uno: 'SymbolShapes.bracket-pair'},
351		{img: 'symbolshapes_left-bracket', uno: 'SymbolShapes.left-bracket'},
352		{img: 'symbolshapes_right-bracket', uno: 'SymbolShapes.right-bracket'},
353
354		{img: 'symbolshapes_brace-pair', uno: 'SymbolShapes.brace-pair'},
355		{img: 'symbolshapes_left-brace', uno: 'SymbolShapes.left-brace'},
356		{img: 'symbolshapes_right-brace', uno: 'SymbolShapes.right-brace'},
357		{img: 'symbolshapes_quad-bevel', uno: 'SymbolShapes.quad-bevel'},
358		{img: 'symbolshapes_octagon-bevel', uno: 'SymbolShapes.octagon-bevel'},
359		{img: 'symbolshapes_diamond-bevel', uno: 'SymbolShapes.diamond-bevel'}
360	],
361
362	'Block Arrows': [
363		{img: 'arrowshapes_left-arrow', uno: 'ArrowShapes.left-arrow'},
364		{img: 'arrowshapes_right-arrow', uno: 'ArrowShapes.right-arrow'},
365		{img: 'arrowshapes_up-arrow', uno: 'ArrowShapes.up-arrow'},
366		{img: 'arrowshapes_down-arrow', uno: 'ArrowShapes.down-arrow'},
367		{img: 'arrowshapes_left-right-arrow', uno: 'ArrowShapes.left-right-arrow'},
368		{img: 'arrowshapes_up-down-arrow', uno: 'ArrowShapes.up-down-arrow'},
369
370		{img: 'arrowshapes_up-right-arrow', uno: 'ArrowShapes.up-right-arrow'},
371		{img: 'arrowshapes_up-right-down-arrow', uno: 'ArrowShapes.up-right-down-arrow'},
372		{img: 'arrowshapes_quad-arrow', uno: 'ArrowShapes.quad-arrow'},
373		{img: 'arrowshapes_corner-right-arrow', uno: 'ArrowShapes.corner-right-arrow'},
374		{img: 'arrowshapes_split-arrow', uno: 'ArrowShapes.split-arrow'},
375		{img: 'arrowshapes_striped-right-arrow', uno: 'ArrowShapes.striped-right-arrow'},
376
377		{img: 'arrowshapes_notched-right-arrow', uno: 'ArrowShapes.notched-right-arrow'},
378		{img: 'arrowshapes_pentagon-right', uno: 'ArrowShapes.pentagon-right'},
379		{img: 'arrowshapes_chevron', uno: 'ArrowShapes.chevron'},
380		{img: 'arrowshapes_right-arrow-callout', uno: 'ArrowShapes.right-arrow-callout'},
381		{img: 'arrowshapes_left-arrow-callout', uno: 'ArrowShapes.left-arrow-callout'},
382		{img: 'arrowshapes_up-arrow-callout', uno: 'ArrowShapes.up-arrow-callout'},
383
384		{img: 'arrowshapes_down-arrow-callout', uno: 'ArrowShapes.down-arrow-callout'},
385		{img: 'arrowshapes_left-right-arrow-callout', uno: 'ArrowShapes.left-right-arrow-callout'},
386		{img: 'arrowshapes_up-down-arrow-callout', uno: 'ArrowShapes.up-down-arrow-callout'},
387		{img: 'arrowshapes_up-right-arrow-callout', uno: 'ArrowShapes.up-right-arrow-callout'},
388		{img: 'arrowshapes_quad-arrow-callout', uno: 'ArrowShapes.quad-arrow-callout'},
389		{img: 'arrowshapes_circular-arrow', uno: 'ArrowShapes.circular-arrow'},
390
391		{img: 'arrowshapes_split-round-arrow', uno: 'ArrowShapes.split-round-arrow'},
392		{img: 'arrowshapes_s-sharped-arrow', uno: 'ArrowShapes.s-sharped-arrow'}
393	],
394
395	'Stars and Banners': [
396		{img: 'starshapes_bang', uno: 'StarShapes.bang'},
397		{img: 'starshapes_star4', uno: 'StarShapes.star4'},
398		{img: 'starshapes_star5', uno: 'StarShapes.star5'},
399		{img: 'starshapes_star6', uno: 'StarShapes.star6'},
400		{img: 'starshapes_star8', uno: 'StarShapes.star8'},
401		{img: 'starshapes_star12', uno: 'StarShapes.star12'},
402
403		{img: 'starshapes_star24', uno: 'StarShapes.star24'},
404		{img: 'starshapes_concave-star6', uno: 'StarShapes.concave-star6'},
405		{img: 'starshapes_vertical-scroll', uno: 'StarShapes.vertical-scroll'},
406		{img: 'starshapes_horizontal-scroll', uno: 'StarShapes.horizontal-scroll'},
407		{img: 'starshapes_signet', uno: 'StarShapes.signet'},
408		{img: 'starshapes_doorplate', uno: 'StarShapes.doorplate'}
409	],
410
411	'Callouts': [
412		{img: 'calloutshapes_rectangular-callout', uno: 'CalloutShapes.rectangular-callout'},
413		{img: 'calloutshapes_round-rectangular-callout', uno: 'CalloutShapes.round-rectangular-callout'},
414		{img: 'calloutshapes_round-callout', uno: 'CalloutShapes.round-callout'},
415		{img: 'calloutshapes_cloud-callout', uno: 'CalloutShapes.cloud-callout'},
416		{img: 'calloutshapes_line-callout-1', uno: 'CalloutShapes.line-callout-1'},
417		{img: 'calloutshapes_line-callout-2', uno: 'CalloutShapes.line-callout-2'},
418		{img: 'calloutshapes_line-callout-3', uno: 'CalloutShapes.line-callout-3'}
419	],
420
421	'Flowchart': [
422		{img: 'flowchartshapes_flowchart-process', uno: 'FlowchartShapes.flowchart-process'},
423		{img: 'flowchartshapes_flowchart-alternate-process', uno: 'FlowchartShapes.flowchart-alternate-process'},
424		{img: 'flowchartshapes_flowchart-decision', uno: 'FlowchartShapes.flowchart-decision'},
425		{img: 'flowchartshapes_flowchart-data', uno: 'FlowchartShapes.flowchart-data'},
426		{img: 'flowchartshapes_flowchart-predefined-process', uno: 'FlowchartShapes.flowchart-predefined-process'},
427		{img: 'flowchartshapes_flowchart-internal-storage', uno: 'FlowchartShapes.flowchart-internal-storage'},
428
429		{img: 'flowchartshapes_flowchart-document', uno: 'FlowchartShapes.flowchart-document'},
430		{img: 'flowchartshapes_flowchart-multidocument', uno: 'FlowchartShapes.flowchart-multidocument'},
431		{img: 'flowchartshapes_flowchart-terminator', uno: 'FlowchartShapes.flowchart-terminator'},
432		{img: 'flowchartshapes_flowchart-preparation', uno: 'FlowchartShapes.flowchart-preparation'},
433		{img: 'flowchartshapes_flowchart-manual-input', uno: 'FlowchartShapes.flowchart-manual-input'},
434		{img: 'flowchartshapes_flowchart-manual-operation', uno: 'FlowchartShapes.flowchart-manual-operation'},
435
436		{img: 'flowchartshapes_flowchart-connector', uno: 'FlowchartShapes.flowchart-connector'},
437		{img: 'flowchartshapes_flowchart-off-page-connector', uno: 'FlowchartShapes.flowchart-off-page-connector'},
438		{img: 'flowchartshapes_flowchart-card', uno: 'FlowchartShapes.flowchart-card'},
439		{img: 'flowchartshapes_flowchart-punched-tape', uno: 'FlowchartShapes.flowchart-punched-tape'},
440		{img: 'flowchartshapes_flowchart-summing-junction', uno: 'FlowchartShapes.flowchart-summing-junction'},
441		{img: 'flowchartshapes_flowchart-or', uno: 'FlowchartShapes.flowchart-or'},
442
443		{img: 'flowchartshapes_flowchart-collate', uno: 'FlowchartShapes.flowchart-collate'},
444		{img: 'flowchartshapes_flowchart-sort', uno: 'FlowchartShapes.flowchart-sort'},
445		{img: 'flowchartshapes_flowchart-extract', uno: 'FlowchartShapes.flowchart-extract'},
446		{img: 'flowchartshapes_flowchart-merge', uno: 'FlowchartShapes.flowchart-merge'},
447		{img: 'flowchartshapes_flowchart-stored-data', uno: 'FlowchartShapes.flowchart-stored-data'},
448		{img: 'flowchartshapes_flowchart-delay', uno: 'FlowchartShapes.flowchart-delay'},
449
450		{img: 'flowchartshapes_flowchart-sequential-access', uno: 'FlowchartShapes.flowchart-sequential-access'},
451		{img: 'flowchartshapes_flowchart-magnetic-disk', uno: 'FlowchartShapes.flowchart-magnetic-disk'},
452		{img: 'flowchartshapes_flowchart-direct-access-storage', uno: 'FlowchartShapes.flowchart-direct-access-storage'},
453		{img: 'flowchartshapes_flowchart-display', uno: 'FlowchartShapes.flowchart-display'}
454	]
455};
456
457function createShapesPanel() {
458	var $grid = $('<div/>').addClass('insertshape-grid');
459
460	for (var s in shapes) {
461		var $rowHeader = $('<div/>').addClass('row-header loleaflet-font').append(_(s));
462		$grid.append($rowHeader);
463		var $row = $('<div/>').addClass('row');
464		$grid.append($row);
465		for (var idx = 0; idx < shapes[s].length; ++idx) {
466			var shape = shapes[s][idx];
467			var $col = $('<div/>').addClass('col w2ui-icon').addClass(shape.img);
468			$col.data('uno', shape.uno);
469			$row.append($col);
470		}
471	}
472
473	$grid.on({
474		click: function(e) {
475			map.sendUnoCommand('.uno:' + $(e.target).data().uno);
476			map._docLayer._closeMobileWizard();
477		}
478	});
479
480	return $grid.get(0);
481}
482
483function insertShapes(mobile) {
484	var width = 10;
485	var $grid = $('.insertshape-grid');
486
487	if ($grid.children().length > 0)
488		return;
489
490	for (var s in shapes) {
491		var $rowHeader = $('<div/>').addClass('row-header loleaflet-font').append(_(s));
492		$grid.append($rowHeader);
493
494		var rows = Math.ceil(shapes[s].length / width);
495		var idx = 0;
496		for (var r = 0; r < rows; r++) {
497			var $row = $('<div/>').addClass('row');
498			$grid.append($row);
499			for (var c = 0; c < width; c++) {
500				if (idx >= shapes[s].length) {
501					break;
502				}
503				var shape = shapes[s][idx++];
504				var $col = $('<div/>').addClass('col w2ui-icon').addClass(shape.img);
505				$col.data('uno', shape.uno);
506				$row.append($col);
507			}
508
509			if (idx >= shapes[s].length)
510				break;
511		}
512	}
513
514	$grid.on({
515		click: function(e) {
516			map.sendUnoCommand('.uno:' + $(e.target).data().uno);
517			if (mobile)
518				vex.closeAll();
519			else
520				closePopup();
521		}
522	});
523}
524
525function getShapesPopupHtml() {
526	return '<div id="insertshape-wrapper">\
527				<div id="insertshape-popup" class="insertshape-pop ui-widget ui-corner-all">\
528					<div class="insertshape-grid"></div>\
529				</div>\
530			</div>';
531}
532
533function getColorPickerData(type) {
534	var uno;
535	if (type === 'Font Color') {
536		if (map.getDocType() === 'spreadsheet' ||
537		    map.getDocType() === 'presentation')
538			uno = '.uno:Color';
539		else
540			uno = '.uno:FontColor';
541	} else if (type === 'Highlight Color') {
542		if (map.getDocType() === 'spreadsheet')
543			uno = '.uno:BackgroundColor';
544		else if (map.getDocType() === 'presentation')
545			uno = '.uno:CharBackColor';
546		else
547			uno = '.uno:BackColor';
548	}
549	var data = {
550		id: 'colorpicker',
551		type: 'window',
552		text: type,
553		enabled: 'true',
554		children: [
555			{
556				type: 'toolitem',
557				text: '',
558				command: uno,
559				nosubmenu: true
560			}
561		],
562		vertical: 'true'
563	};
564	return data;
565}
566
567function onColorPick(id, color) {
568	if (!map.isPermissionEdit()) {
569		return;
570	}
571	// no fill or automatic color is -1
572	if (color === '') {
573		color = -1;
574	}
575	// transform from #FFFFFF to an Int
576	else {
577		color = parseInt(color.replace('#', ''), 16);
578	}
579	var command = {};
580	var fontcolor, backcolor;
581	if (id === 'fontcolor') {
582		fontcolor = {'text': 'FontColor',
583			     'spreadsheet': 'Color',
584			     'presentation': 'Color'}[map.getDocType()];
585		command[fontcolor] = {};
586		command[fontcolor].type = 'long';
587		command[fontcolor].value = color;
588		var uno = '.uno:' + fontcolor;
589	}
590	// "backcolor" can be used in Writer and Impress and translates to "Highlighting" while
591	// "backgroundcolor" can be used in Writer and Calc and translates to "Background color".
592	else if (id === 'backcolor') {
593		backcolor = {'text': 'BackColor',
594			     'presentation': 'CharBackColor'}[map.getDocType()];
595		command[backcolor] = {};
596		command[backcolor].type = 'long';
597		command[backcolor].value = color;
598		uno = '.uno:' + backcolor;
599	}
600	else if (id === 'backgroundcolor') {
601		backcolor = {'text': 'BackgroundColor',
602			     'spreadsheet': 'BackgroundColor'}[map.getDocType()];
603		command[backcolor] = {};
604		command[backcolor].type = 'long';
605		command[backcolor].value = color;
606		uno = '.uno:' + backcolor;
607	}
608	map.sendUnoCommand(uno, command);
609	map.focus();
610}
611
612function hideTooltip(toolbar, id) {
613	if (toolbar.touchStarted) {
614		setTimeout(function() {
615			toolbar.tooltipHide(id, {});
616		}, 5000);
617		toolbar.touchStarted = false;
618	}
619}
620
621function setupSearchInput() {
622	$('#search-input').off('input', onSearchInput).on('input', onSearchInput);
623	$('#search-input').off('keydown', onSearchKeyDown).on('keydown', onSearchKeyDown);
624	$('#search-input').off('focus', onSearchFocus).on('focus', onSearchFocus);
625	$('#search-input').off('blur', onSearchBlur).on('blur', onSearchBlur);
626}
627
628function unoCmdToToolbarId(commandname)
629{
630	var id = commandname.toLowerCase().substr(5);
631	var selectionType = 'text';
632
633	if (map._clip && map._clip._selectionType)
634		selectionType = map._clip._selectionType;
635
636	if (map.getDocType() === 'spreadsheet') {
637		switch (id) {
638		case 'alignleft':
639			id = 'leftpara';
640			break;
641		case 'alignhorizontalcenter':
642			id = 'centerpara';
643			break;
644		case 'alignright':
645			id = 'rightpara';
646			break;
647		}
648	}
649	else if (selectionType == 'complex') {
650
651		// ignore the text align state messages.
652		if (id === 'leftpara' || id === 'rightpara' ||
653			id === 'centerpara') {
654			id = '';
655		}
656
657		// convert the object align statemessages to align button ids.
658		switch (id) {
659		case 'objectalignleft':
660			id = 'leftpara';
661			break;
662		case 'aligncenter':
663			id = 'centerpara';
664			break;
665		case 'objectalignright':
666			id = 'rightpara';
667			break;
668		}
669	}
670	else if (id === 'objectalignleft' || id === 'aligncenter' ||
671		id === 'objectalignright') {
672		// selectionType is 'text', so ignore object align state messages.
673		id = '';
674	}
675	return id;
676}
677
678function updateSearchButtons() {
679	var toolbar = window.mode.isMobile() ? w2ui['searchbar'] : w2ui['actionbar'];
680	// conditionally disabling until, we find a solution for tdf#108577
681	if (L.DomUtil.get('search-input').value === '') {
682		toolbar.disable('searchprev');
683		toolbar.disable('searchnext');
684		toolbar.hide('cancelsearch');
685	}
686	else {
687		toolbar.enable('searchprev');
688		toolbar.enable('searchnext');
689		toolbar.show('cancelsearch');
690	}
691}
692
693function onSearchInput() {
694	updateSearchButtons();
695	if (map.getDocType() === 'text') {
696		// perform the immediate search in Writer
697		map.search(L.DomUtil.get('search-input').value, false, '', 0, true /* expand search */);
698	}
699}
700
701function onSearchKeyDown(e) {
702	var entry = L.DomUtil.get('search-input');
703	if ((e.keyCode === 71 && e.ctrlKey) || e.keyCode === 114 || e.keyCode === 13) {
704		if (e.shiftKey) {
705			map.search(entry.value, true);
706		} else {
707			map.search(entry.value);
708		}
709		e.preventDefault();
710	} else if (e.ctrlKey && e.keyCode === 70) {
711		entry.focus();
712		entry.select();
713		e.originalEvent.preventDefault();
714	} else if (e.keyCode === 27) {
715		_cancelSearch();
716	}
717}
718
719function onSearchFocus() {
720	// Start searching.
721	map.fire('searchstart');
722
723	updateSearchButtons();
724}
725
726function onSearchBlur() {
727	map._onGotFocus();
728}
729
730function onInsertFile() {
731	var insertGraphic = L.DomUtil.get('insertgraphic');
732	if ('files' in insertGraphic) {
733		for (var i = 0; i < insertGraphic.files.length; i++) {
734			var file = insertGraphic.files[i];
735			map.insertFile(file);
736		}
737	}
738
739	// Set the value to null everytime so that onchange event is triggered,
740	// even if the same file is selected
741	insertGraphic.value = null;
742	return false;
743}
744
745function onInsertBackground() {
746	var selectBackground = L.DomUtil.get('selectbackground');
747	if ('files' in selectBackground) {
748		for (var i = 0; i < selectBackground.files.length; i++) {
749			var file = selectBackground.files[i];
750			map.selectBackground(file);
751		}
752	}
753
754	// Set the value to null everytime so that onchange event is triggered,
755	// even if the same file is selected
756	selectBackground.value = null;
757	return false;
758}
759
760function onWopiProps(e) {
761	if (e.DisableCopy) {
762		$('input#formulaInput').bind('copy', function(evt) {
763			evt.preventDefault();
764		});
765		$('input#addressInput').bind('copy', function(evt) {
766			evt.preventDefault();
767		});
768	}
769}
770
771function onCommandStateChanged(e) {
772	var toolbar = w2ui['editbar'];
773	var commandName = e.commandName;
774	var state = e.state;
775	var color, div;
776
777	if (!commandName)
778		return;
779
780	if (commandName === '.uno:AssignLayout') {
781		$('.styles-select').val(state).trigger('change');
782	}
783	else if (commandName === '.uno:FontColor' || commandName === '.uno:Color') {
784		// confusingly, the .uno: command is named differently in Writer, Calc and Impress
785		color = parseInt(e.state);
786		if (color === -1) {
787			color = 'transparent';
788		}
789		else {
790			color = color.toString(16);
791			color = '#' + Array(7 - color.length).join('0') + color;
792		}
793		$('#tb_editbar_item_fontcolor .w2ui-tb-image').css('box-shadow', 'inset 0 -2px #ffffff, inset 0px -6px ' + color);
794		$('#tb_editbar_item_fontcolor .w2ui-tb-down').css('display', 'none');
795		$('#tb_editbar_item_fontcolor .w2ui-tb-caption').css('display', 'none');
796
797		div = L.DomUtil.get('fontcolorindicator');
798		if (div) {
799			L.DomUtil.setStyle(div, 'background', color);
800		}
801	}
802	else if (commandName === '.uno:BackColor' || commandName === '.uno:BackgroundColor' || commandName === '.uno:CharBackColor') {
803		// confusingly, the .uno: command is named differently in Writer, Calc and Impress
804		color = parseInt(e.state);
805		if (color === -1) {
806			color = 'transparent';
807		}
808		else {
809			color = color.toString(16);
810			color = '#' + Array(7 - color.length).join('0') + color;
811		}
812		//writer
813		$('#tb_editbar_item_backcolor .w2ui-tb-image').css('box-shadow', 'inset 0 -2px #ffffff, inset 0px -6px ' + color);
814		$('#tb_editbar_item_backcolor .w2ui-tb-down').css('display', 'none');
815		$('#tb_editbar_item_backcolor .w2ui-tb-caption').css('display', 'none');
816		//calc?
817		$('#tb_editbar_item_backgroundcolor .w2ui-tb-image').css('box-shadow', 'inset 0 -2px #ffffff, inset 0px -6px ' + color);
818		$('#tb_editbar_item_backgroundcolor .w2ui-tb-down').css('display', 'none');
819		$('#tb_editbar_item_backgroundcolor .w2ui-tb-caption').css('display', 'none');
820
821		div = L.DomUtil.get('backcolorindicator');
822		if (div) {
823			L.DomUtil.setStyle(div, 'background', color);
824		}
825	}
826	else if (commandName === '.uno:LanguageStatus') {
827		var code = state;
828		var split = code.split(';');
829		if (split.length > 1) {
830			code = split[1];
831		}
832		w2ui['editbar'].set('languagecode', {text: code});
833	}
834	else if (commandName === '.uno:ModifiedStatus') {
835		if (e.state === 'true') {
836			w2ui['editbar'].set('save', {img:'savemodified'});
837		}
838		else {
839			w2ui['editbar'].set('save', {img:'save'});
840		}
841	}
842	else if (commandName === '.uno:DocumentRepair') {
843		if (state === 'true') {
844			toolbar.enable('repair');
845		} else {
846			toolbar.disable('repair');
847		}
848	}
849	else if (commandName === '.uno:FormatPaintbrush') {
850		if (state === 'true')
851			$('.leaflet-pane.leaflet-map-pane').addClass('bucket-cursor');
852		else
853			$('.leaflet-pane.leaflet-map-pane').removeClass('bucket-cursor');
854	}
855
856	var id = unoCmdToToolbarId(commandName);
857	// id is set to '' by unoCmdToToolbarId() if the statechange message should be ignored.
858	if (id === '')
859		return;
860
861	if (state === 'true') {
862		if (map.isPermissionEdit()) {
863			toolbar.enable(id);
864		}
865		toolbar.check(id);
866	}
867	else if (state === 'false') {
868		if (map.isPermissionEdit()) {
869			toolbar.enable(id);
870		}
871		toolbar.uncheck(id);
872	}
873	// Change the toolbar button states if we are in editmode
874	// If in non-edit mode, will be taken care of when permission is changed to 'edit'
875	else if (map.isPermissionEdit() && (state === 'enabled' || state === 'disabled')) {
876		var toolbarUp = toolbar;
877		if (state === 'enabled') {
878			toolbarUp.enable(id);
879		} else {
880			toolbarUp.uncheck(id);
881			toolbarUp.disable(id);
882		}
883	}
884}
885
886function onUpdateParts(e) {
887	$('#document-container').addClass(e.docType + '-doctype');
888	if (e.docType === 'text') {
889		var current = e.currentPage;
890		var count = e.pages;
891	}
892	else {
893		current = e.selectedPart;
894		count = e.parts;
895	}
896
897	var toolbar = w2ui['actionbar'];
898	if (!toolbar) {
899		return;
900	}
901
902	if (!window.mode.isMobile()) {
903		if (e.docType === 'presentation') {
904			toolbar.set('prev', {hint: _('Previous slide')});
905			toolbar.set('next', {hint: _('Next slide')});
906		}
907		else {
908			toolbar.hide('presentation');
909			toolbar.hide('insertpage');
910			toolbar.hide('duplicatepage');
911			toolbar.hide('deletepage');
912		}
913	}
914
915	if (e.docType !== 'spreadsheet') {
916		if (current === 0) {
917			toolbar.disable('prev');
918		}
919		else {
920			toolbar.enable('prev');
921		}
922
923		if (current === count - 1) {
924			toolbar.disable('next');
925		}
926		else {
927			toolbar.enable('next');
928		}
929	}
930}
931
932function onCommandResult(e) {
933	var commandName = e.commandName;
934
935	if (commandName === '.uno:Save') {
936		if (e.success) {
937			// Saved a new version; the document is modified.
938			map._everModified = true;
939
940			// document is saved for rename
941			if (map._renameFilename) {
942				var renameFilename = map._renameFilename;
943				map._renameFilename = '';
944				map.renameFile(renameFilename);
945			}
946		}
947		var postMessageObj = {
948			success: e.success
949		};
950		if (!e.success) {
951			// add the result reason string if failed
952			postMessageObj['result'] = e.result && e.result.value;
953		}
954
955		map.fire('postMessage', {msgId: 'Action_Save_Resp', args: postMessageObj});
956	}
957	else if ((commandName === '.uno:Undo' || commandName === '.uno:Redo') &&
958		e.success === true && e.result.value && !isNaN(e.result.value)) { /*UNDO_CONFLICT*/
959		$('#tb_editbar_item_repair').w2overlay({ html: '<div style="padding: 10px; line-height: 150%">' +
960			_('Conflict Undo/Redo with multiple users. Please use document repair to resolve') + '</div>'});
961	}
962}
963
964function onUpdatePermission(e) {
965	var toolbar = w2ui['editbar'];
966	if (toolbar) {
967		// always enabled items
968		var enabledButtons = ['closemobile', 'undo', 'redo', 'hamburger-tablet'];
969
970		// copy the first array
971		var items = toolbar.items.slice();
972		for (var idx in items) {
973			var found = enabledButtons.filter(function(id) { return id === items[idx].id; });
974			var alwaysEnable = found.length !== 0;
975
976			if (e.perm === 'edit') {
977				var unoCmd = map.getDocType() === 'spreadsheet' ? items[idx].unosheet : getUNOCommand(items[idx].uno);
978				var keepDisabled = map['stateChangeHandler'].getItemValue(unoCmd) === 'disabled';
979				if (!keepDisabled || alwaysEnable) {
980					toolbar.enable(items[idx].id);
981				}
982				$('.main-nav').removeClass('readonly');
983			} else if (!alwaysEnable) {
984				$('.main-nav').addClass('readonly');
985				toolbar.disable(items[idx].id);
986			}
987		}
988		if (e.perm === 'edit') {
989			toolbar.set('closemobile', {img: 'editmode'});
990		} else {
991			toolbar.set('closemobile', {img: 'closemobile'});
992		}
993
994	}
995}
996
997function editorUpdate(e) { // eslint-disable-line no-unused-vars
998	var docLayer = map._docLayer;
999
1000	if (e.target.checked) {
1001		var editorId = docLayer._editorId;
1002
1003		docLayer._followUser = false;
1004		docLayer._followEditor = true;
1005		if (editorId !== -1 && editorId !== docLayer.viewId) {
1006			map._goToViewId(editorId);
1007			docLayer._followThis = editorId;
1008		}
1009
1010		var userlistItem = w2ui['actionbar'].get('userlist');
1011		if (userlistItem !== null) {
1012			$('.selected-user').removeClass('selected-user');
1013		}
1014	}
1015	else {
1016		docLayer._followEditor = false;
1017		docLayer._followThis = -1;
1018	}
1019	$('#tb_actionbar_item_userlist').w2overlay('');
1020}
1021
1022global.editorUpdate = editorUpdate;
1023
1024$(document).ready(function() {
1025	// Attach insert file action
1026	$('#insertgraphic').on('change', onInsertFile);
1027	$('#selectbackground').on('change', onInsertBackground);
1028});
1029
1030function setupToolbar(e) {
1031	map = e;
1032
1033	map.on('focussearch', function () {
1034		var entry = L.DomUtil.get('search-input');
1035		entry.focus();
1036		entry.select();
1037	});
1038
1039	map.on('search', function (e) {
1040		var searchInput = L.DomUtil.get('search-input');
1041		var toolbar = w2ui['actionbar'];
1042		if (e.count === 0) {
1043			toolbar.disable('searchprev');
1044			toolbar.disable('searchnext');
1045			toolbar.hide('cancelsearch');
1046			L.DomUtil.addClass(searchInput, 'search-not-found');
1047			$('#findthis').addClass('search-not-found');
1048			map.resetSelection();
1049			setTimeout(function () {
1050				$('#findthis').removeClass('search-not-found');
1051				L.DomUtil.removeClass(searchInput, 'search-not-found');
1052			}, 500);
1053		}
1054	});
1055
1056	map.on('hyperlinkclicked', function (e) {
1057		if (e.url) {
1058			if (e.coordinates) {
1059				var strTwips = e.coordinates.match(/\d+/g);
1060				var topLeftTwips = new L.Point(parseInt(strTwips[6]), parseInt(strTwips[1]));
1061				var offset = new L.Point(parseInt(strTwips[2]), parseInt(strTwips[3]));
1062				var bottomRightTwips = topLeftTwips.add(offset);
1063				var cellCursor = new L.LatLngBounds(
1064								map._docLayer._twipsToLatLng(topLeftTwips, map.getZoom()),
1065								map._docLayer._twipsToLatLng(bottomRightTwips, map.getZoom()));
1066				//click pos tweak
1067				cellCursor._northEast.lng = cellCursor._southWest.lng;
1068				map._docLayer._closeURLPopUp();
1069				map._docLayer._showURLPopUp(cellCursor._northEast, e.url);
1070			} else {
1071				map.fire('warn', {url: e.url, map: map, cmd: 'openlink'});
1072			}
1073		}
1074	});
1075
1076	map.on('updatepermission', onUpdatePermission);
1077	map.on('wopiprops', onWopiProps);
1078	map.on('commandresult', onCommandResult);
1079	map.on('updateparts pagenumberchanged', onUpdateParts);
1080
1081	if (map.options.wopi && L.Params.closeButtonEnabled && !window.mode.isMobile()) {
1082		$('#closebuttonwrapper').css('display', 'block');
1083	} else if (!L.Params.closeButtonEnabled) {
1084		$('#closebuttonwrapper').hide();
1085	} else if (L.Params.closeButtonEnabled && !window.mode.isMobile()) {
1086		$('#closebuttonwrapper').css('display', 'block');
1087	}
1088
1089	$('#closebutton').click(onClose);
1090}
1091
1092global.onClose = onClose;
1093global.setupToolbar = setupToolbar;
1094global.onClick = onClick;
1095global.hideTooltip = hideTooltip;
1096global.insertTable = insertTable;
1097global.getInsertTablePopupHtml = getInsertTablePopupHtml;
1098global.getShapesPopupHtml = getShapesPopupHtml;
1099global.insertShapes = insertShapes;
1100global.createShapesPanel = createShapesPanel;
1101global.onUpdatePermission = onUpdatePermission;
1102global.setupSearchInput = setupSearchInput;
1103global.getUNOCommand = getUNOCommand;
1104global.unoCmdToToolbarId = unoCmdToToolbarId;
1105global.onCommandStateChanged = onCommandStateChanged;
1106
1107}(window));
1108