[Libreoffice-commits] online.git: loleaflet/build loleaflet/css loleaflet/Makefile.am loleaflet/src

Marco Cecchetti (via logerrit) logerrit at kemper.freedesktop.org
Wed Oct 16 10:20:20 UTC 2019


 loleaflet/Makefile.am                            |    1 
 loleaflet/build/deps.js                          |    1 
 loleaflet/css/toolbar.css                        |  107 +++++++
 loleaflet/src/control/ColorPicker.js             |  330 +++++++++++++++++++++++
 loleaflet/src/control/Control.JSDialogBuilder.js |  121 ++++++--
 loleaflet/src/core/Util.js                       |    5 
 6 files changed, 534 insertions(+), 31 deletions(-)

New commits:
commit d0e6692c1bb07966f74304df401b434149d1609d
Author:     Marco Cecchetti <marco.cecchetti at collabora.com>
AuthorDate: Mon Oct 14 16:51:15 2019 +0200
Commit:     Marco Cecchetti <marco.cecchetti at collabora.com>
CommitDate: Wed Oct 16 12:18:43 2019 +0200

    loleaflet: color picker control based on JSDialogBuilder
    
    This patch provides an implementation of a color picker control living
    in its own submenu.
    
    Change-Id: I65c24c73d322f1d4d0d8819dc5c9ad80ee846261

diff --git a/loleaflet/Makefile.am b/loleaflet/Makefile.am
index 160e36ee8..23f6676bb 100644
--- a/loleaflet/Makefile.am
+++ b/loleaflet/Makefile.am
@@ -330,6 +330,7 @@ pot:
 		src/control/Control.ContextMenu.js \
 		src/control/Control.DocumentRepair.js \
 		src/control/Control.DownloadProgress.js \
+		src/control/ColorPicker.js \
 		src/control/Control.JSDialogBuilder.js \
 		src/control/Control.Menubar.js \
 		src/control/Control.MobileWizard.js \
diff --git a/loleaflet/build/deps.js b/loleaflet/build/deps.js
index 28eb45cf9..f003f06fe 100644
--- a/loleaflet/build/deps.js
+++ b/loleaflet/build/deps.js
@@ -387,6 +387,7 @@ var deps = {
 			'control/Control.LokDialog.js',
 			'control/Control.AlertDialog.js',
 			'control/Control.Infobar.js',
+			'control/ColorPicker.js',
 			'control/Control.JSDialogBuilder.js',
 			'control/Control.MobileWizard.js'],
 		heading: 'Controls',
diff --git a/loleaflet/css/toolbar.css b/loleaflet/css/toolbar.css
index d95f85a5f..518e03791 100644
--- a/loleaflet/css/toolbar.css
+++ b/loleaflet/css/toolbar.css
@@ -1066,6 +1066,7 @@ tr.useritem > td > img {
 }
 
 .ui-header.mobile-wizard {
+	width: 96%;
 	height: 56px !important;
 	font-size: 11pt !important;
 	margin: 0px;
@@ -1230,3 +1231,109 @@ menu-entry-with-icon.padding-left + menu-entry-icon.width */
 	vertical-align: middle;
 	padding-left: 8px;
 }
+
+.color-sample-selected {
+	height: 32px !important;
+	width: 32px !important;
+	border: 1px solid #8A8A8A;
+	border-radius: 100px;
+}
+
+.no-color-selected {
+	text-align: center;
+	font-size: 30pt;
+	line-height: 32px;
+	font-weight: 300;
+	color: #ff0000 !important;
+	background-color: #fff !important;
+}
+
+.color-sample-small {
+	border-left: 3px solid #fff;
+	border-right: 3px solid #fff;
+	border-bottom: 3px solid #fff;
+	width: 28px;
+	height: 28px;
+	color: #f0f8ff;
+	text-align: center;
+	vertical-align: bottom;
+	display: table-cell;
+}
+
+.color-sample-big {
+	border: 5px solid #f2f8f0;
+	padding: 5px;
+	width: 118px;
+	height: 42px;
+	color: #f0f8ff;
+	text-align: right;
+	vertical-align: bottom;
+	display: table-cell;
+}
+
+.colors-container {
+	display: table;
+}
+
+.colors-container-no-color-row {
+	display: flex;
+	justify-content: space-between;
+	height: 50px;
+}
+
+.colors-container-basic-colors-row {
+	padding-bottom: 20px;
+}
+
+.colors-container-tints {
+	padding-bottom: 0px;
+}
+
+.no-color-control-label {
+	display:table-cell;
+	padding-left: 30px;
+	vertical-align: middle;
+}
+
+.no-color-control-mark {
+	color: #0b87e7 !important;
+	font-size: larger;
+	line-height: 0;
+}
+
+.no-color-control-icon {
+	display: table-cell;
+	height: 28px !important;
+	width: 28px !important;
+	border: 1px solid #8A8A8A;
+	border-radius: 100px;
+	text-align: center;
+	font-size: 26pt;
+	line-height: 28px;
+	font-weight: 300;
+	color: #ff0000 !important;
+	background-color: #fff;
+}
+
+.colors-container-basic-color-mark {
+	width: 10px;
+	height: 10px;
+	font-size: x-large;
+	color: darkslategray !important;
+	background-color: transparent !important;
+	margin-bottom: 2px;
+	margin-left: 7px;
+	vertical-align: bottom;
+}
+
+.colors-container-tint-mark {
+	width: 20px;
+	height: 20px;
+	font-size: medium;
+	color: #000 !important;
+	background-color: whitesmoke !important;
+	text-align: center;
+	line-height: 21px;
+	margin-left: auto;
+	border-radius: 100px;
+}
\ No newline at end of file
diff --git a/loleaflet/src/control/ColorPicker.js b/loleaflet/src/control/ColorPicker.js
new file mode 100644
index 000000000..71a0e4224
--- /dev/null
+++ b/loleaflet/src/control/ColorPicker.js
@@ -0,0 +1,330 @@
+/* -*- js-indent-level: 8 -*- */
+/*
+ * L.ColorPicker is used for building a native HTML color picker
+ * panel to be used by the properties mobile wizard.
+ */
+
+/* global _ */
+
+L.ColorPicker = L.Class.extend({
+	options: {
+		selectedColor: '#CC0814',
+		noColorControl: true
+	},
+
+	statics: {
+		ID: 0,
+		ID_TAG: 'color-picker-',
+
+		// color types
+		BASIC_COLOR: 0,
+		TINT: 1,
+
+		BASIC_COLORS: ['#000000', '#FF011B', '#FF9838', '#FFFD59', '#01FD55',
+			'#00FFFE', '#006CE7', '#9B24F4', '#FF21F5'],
+		TINTS: {
+			'#000000': ['#000000', '#434343', '#666666', '#888888',
+				'#BBBBBB', '#DDDDDD', '#EEEEEE', '#FFFFFF'],
+			'#FF011B': ['#99050C', '#CC0814', '#E06666', '#FF011B',
+				'#EA9899', '#F4CCCC', '#FFEAEA', '#FFFFFF'],
+			'#FF9838': ['#783f04', '#b45f06', '#e69138', '#ff9900',
+				'#f6b26b', '#f9cb9c', '#fce5cd', '#FFFFFF'],
+			'#FFFD59': ['#7f6000', '#bf9000', '#f1c232', '#ffff00',
+				'#ffd966', '#ffe599', '#fff2cc', '#FFFFFF']
+		}
+	},
+
+	_selectedBasicColorIndex: 0,
+	_selectedTintIndex: 0,
+
+	initialize: function (selectedColorSample, options) {
+		L.setOptions(this, options);
+		this._id = L.ColorPicker.ID++;
+		this._basicColorSampleIdTag = L.ColorPicker.ID_TAG + this._id + '-basic-color-';
+		this._tintSampleIdTag = L.ColorPicker.ID_TAG + this._id + '-tint-';
+		this._noColorControlId = L.ColorPicker.ID_TAG + this._id + '-no-color';
+		this._createBasicColorSelectionMark();
+		this._createTintSelectionMark();
+		this._selectedColorElement = selectedColorSample;
+		this._selectedColor = this.options.selectedColor;
+		this._initIndexes();
+		this._container = this._createControl();
+	},
+
+	getId: function () {
+		return this._id;
+	},
+
+	getSelectedColor: function () {
+		return this._selectedColor;
+	},
+
+	getContainer: function () {
+		return this._container;
+	},
+
+	_initIndexes: function () {
+		for (var i = 0; i < this._getBasicColorCount(); ++i) {
+			var tintSet = this._getTintSet(i);
+			for (var j = 0; j < tintSet.length; ++j) {
+				var tint = tintSet[j];
+				if (tint === this._selectedColor) {
+					this._selectedBasicColorIndex = i;
+					this._selectedTintIndex = j;
+					return;
+				}
+			}
+		}
+	},
+
+	_createControl: function () {
+		var children = [];
+		if (this.options.noColorControl)
+			children.push(this._createNoColorControl());
+		children.push(this._createBasicColorSamples());
+		children.push(this._createTintSamples());
+		return {type: 'divcontainer', style: 'colors-container', children: children};
+	},
+
+	_createNoColorControl: function () {
+		var icon = {
+			type: 'fixedtext',
+			text: '\\',
+			style: 'no-color-control-icon'
+		};
+		var label = {type: 'fixedtext', style: 'no-color-control-label', text: _('No color')};
+		var description = {type: 'divcontainer', children: [icon, label]};
+		var checked = {type:'fixedtext', id: this._noColorControlId, style: 'no-color-control-mark', text: ''};
+		var container = {
+			type: 'divcontainer',
+			style: 'colors-container-no-color-row',
+			handlers: [{event: 'click', handler: L.bind(this.onClickNoColor, this)}],
+			children: [description, checked]
+		};
+		return container;
+	},
+
+	_createBasicColorSamples: function () {
+		var colorEntries = [];
+		for (var k = 0; k < this._getBasicColorCount(); ++k) {
+			var selected = k === this._selectedBasicColorIndex;
+			var entry = {
+				type: 'colorsample',
+				id: this._basicColorSampleIdTag + k,
+				selected: selected,
+				color: this._getBasicColor(k),
+				size: 'small',
+				handlers: [{event: 'click', handler: L.bind(this.onClickBasicColorSample, this)}]
+			};
+			if (selected) {
+				entry.mark = this._basicColorSelectionMark;
+			}
+			colorEntries.push(entry);
+		}
+		return {type: 'divcontainer', style: 'colors-container-basic-colors-row', children: colorEntries};
+	},
+
+	_createTintSamples: function () {
+		var tints = this._getTintSet(this._selectedBasicColorIndex);
+		var k, selected, entry, tintRowLength = tints.length / 2;
+
+		// first tints row
+		var tintsEntries1 = [];
+		for (k = 0; k < tintRowLength; ++k) {
+			selected = tints[k] === this._selectedColor;
+			entry = {
+				type: 'colorsample',
+				id: this._tintSampleIdTag + k,
+				selected: selected,
+				color: tints[k],
+				size: 'big',
+				handlers: [{event: 'click', handler: L.bind(this.onClickTintSample, this)}]
+			};
+			if (selected) {
+				entry.mark = this._tintSelectionMark;
+			}
+			tintsEntries1.push(entry);
+		}
+		var tintsRow1 = {type: 'divcontainer', style: 'colors-container-tints', children: tintsEntries1};
+
+		// second tints row
+		var tintsEntries2 = [];
+		for (k = tintRowLength; k < tints.length; ++k) {
+			selected = tints[k] === this._selectedColor;
+			entry = {
+				type: 'colorsample',
+				id: this._tintSampleIdTag + k,
+				color: tints[k],
+				size: 'big',
+				handlers: [{event: 'click', handler: L.bind(this.onClickTintSample, this)}]
+			};
+			if (selected) {
+				entry.mark = this._tintSelectionMark
+			}
+			tintsEntries2.push(entry);
+		}
+		var tintsRow2 = {type: 'divcontainer', style: 'colors-container-tints', children: tintsEntries2};
+
+		return {type: 'divcontainer', children: [tintsRow1, tintsRow2]};
+	},
+
+	_createBasicColorSelectionMark: function () {
+		this._basicColorSelectionMark = L.DomUtil.create('div', 'colors-container-basic-color-mark', null);
+		this._basicColorSelectionMark.innerHTML = '●';
+	},
+
+	_createTintSelectionMark: function () {
+		this._tintSelectionMark = L.DomUtil.create('div', 'colors-container-tint-mark', null);
+		this._tintSelectionMark.innerHTML = '✔';
+	},
+
+
+	_getSelectionMark: function (colorType) {
+		if (colorType === L.ColorPicker.BASIC_COLOR)
+			return this._basicColorSelectionMark;
+		else if (colorType === L.ColorPicker.TINT)
+			return this._tintSelectionMark;
+		else
+			return null;
+	},
+
+	_getBasicColorCount: function () {
+		return 	L.ColorPicker.BASIC_COLORS.length;
+	},
+
+	_getBasicColor: function (index) {
+		if (!(index >= 0 && index < L.ColorPicker.BASIC_COLORS.length))
+			return '';
+		return L.ColorPicker.BASIC_COLORS[index];
+	},
+
+	_getTintSet: function  (basicColorIndex) {
+		var basicColor = this._getBasicColor(basicColorIndex);
+		return 	L.ColorPicker.TINTS[basicColor];
+	},
+
+	_extractBasicColorIndex: function (sampleId) {
+		if (!sampleId.startsWith(this._basicColorSampleIdTag))
+			return -1;
+		var index = parseInt(sampleId.substring(this._basicColorSampleIdTag.length));
+		if (index < 0 || index >= this._getBasicColorCount())
+			return -1;
+		return index;
+	},
+
+	_extractTintIndex: function (sampleId) {
+		if (!sampleId.startsWith(this._tintSampleIdTag))
+			return -1;
+		var index = parseInt(sampleId.substring(this._tintSampleIdTag.length));
+		if (index < 0 || index >= this._getTintSet(this._selectedBasicColorIndex).length)
+			return -1;
+		return index;
+	},
+
+	_getColorCode: function (colorIndex, colorType) {
+		var sampleElem = this._getSampleElement(colorIndex, colorType);
+		return sampleElem.name;
+	},
+
+	onClickNoColor: function () {
+		this._selectedColor = '#';
+		this._unselectSample(this._selectedTintIndex, L.ColorPicker.TINT);
+		this._updateNoColorControl(true);
+	},
+
+	onClickBasicColorSample: function (e) {
+		var basicColorIndex = this._extractBasicColorIndex(e.id);
+		if (basicColorIndex < 0)
+			return;
+		this._selectedBasicColorIndex = this._updateSelectedSample(basicColorIndex, this._selectedBasicColorIndex, L.ColorPicker.BASIC_COLOR);
+		this._updateTintsView(basicColorIndex);
+	},
+
+	onClickTintSample: function (e) {
+		var tintIndex = this._extractTintIndex(e.id);
+		if (tintIndex < 0)
+			return;
+		this._selectedTintIndex = this._updateSelectedSample(tintIndex, this._selectedTintIndex, L.ColorPicker.TINT);
+		this._selectedColor = '#' + this._getColorCode(this._selectedTintIndex, L.ColorPicker.TINT);
+		this._updateNoColorControl(false);
+		this._updateSelectedColorElement();
+	},
+
+	_updateSelectedSample: function (colorIndex, selectedColorIndex, colorType) {
+		this._unselectSample(selectedColorIndex, colorType);
+		this._selectSample(colorIndex, colorType);
+		return colorIndex;
+	},
+
+	_unselectSample: function (colorIndex, colorType) {
+		var sampleElem = this._getSampleElement(colorIndex, colorType);
+		if (sampleElem && sampleElem.firstChild) {
+			sampleElem.removeChild(sampleElem.firstChild);
+		}
+	},
+
+	_selectSample: function (colorIndex, colorType) {
+		var sampleElem = this._getSampleElement(colorIndex, colorType);
+		if (sampleElem) {
+			sampleElem.appendChild(this._getSelectionMark(colorType));
+		}
+	},
+
+	_updateTintsView: function () {
+		var tintSet = this._getTintSet(this._selectedBasicColorIndex);
+		if (!tintSet)
+			return;
+		for (var i = 0; i < tintSet.length; ++i) {
+			var tint = tintSet[i];
+			var sampleElem = this._getSampleElement(i, L.ColorPicker.TINT);
+			if (sampleElem) {
+				sampleElem.style.backgroundColor = tint;
+				sampleElem.name = tint.substring(1);
+				if (tint === this._selectedColor) {
+					sampleElem.appendChild(this._getSelectionMark(L.ColorPicker.TINT));
+				} else if (sampleElem.firstChild) {
+					sampleElem.removeChild(sampleElem.firstChild);
+				}
+			}
+		}
+	},
+
+	_updateNoColorControl: function (checked) {
+		var noColorElem = L.DomUtil.get(this._noColorControlId);
+		if (noColorElem) {
+			if (noColorElem.checked !== checked) {
+				noColorElem.checked = checked;
+				if (this._selectedColorElement) {
+					if (checked) {
+						noColorElem.innerHTML = '✔';
+						// update value for the related menu entry
+						L.DomUtil.addClass(this._selectedColorElement, 'no-color-selected');
+						this._selectedColorElement.innerHTML = '\\';
+					} else {
+						noColorElem.innerHTML = '';
+						// update value for the related menu entry
+						L.DomUtil.removeClass(this._selectedColorElement, 'no-color-selected');
+						this._selectedColorElement.innerHTML = '';
+					}
+				}
+			}
+		}
+	},
+
+	_getSampleElement: function (index, type) {
+		var sampleId;
+		if (type === L.ColorPicker.BASIC_COLOR) {
+			sampleId = this._basicColorSampleIdTag + index;
+		} else if (type === L.ColorPicker.TINT) {
+			sampleId = this._tintSampleIdTag + index;
+		}
+		return L.DomUtil.get(sampleId);
+	},
+
+	_updateSelectedColorElement: function () {
+		if (this._selectedColorElement) {
+			this._selectedColorElement.style.backgroundColor = this._selectedColor;
+		}
+	}
+
+});
diff --git a/loleaflet/src/control/Control.JSDialogBuilder.js b/loleaflet/src/control/Control.JSDialogBuilder.js
index 311d0c64d..db4991df6 100644
--- a/loleaflet/src/control/Control.JSDialogBuilder.js
+++ b/loleaflet/src/control/Control.JSDialogBuilder.js
@@ -4,7 +4,8 @@
  * from the JSON description provided by the server.
  */
 
-/* global $ w2ui _ */
+/* global $ _ */
+
 L.Control.JSDialogBuilder = L.Control.extend({
 
 	/* Handler is a function which takes three parameters:
@@ -46,6 +47,8 @@ L.Control.JSDialogBuilder = L.Control.extend({
 		this._controlHandlers['scrollbar'] = this._ignoreHandler;
 		this._controlHandlers['toolbox'] = this._containerHandler;
 		this._controlHandlers['toolitem'] = this._toolitemHandler;
+		this._controlHandlers['colorsample'] = this._colorSampleControl;
+		this._controlHandlers['divcontainer'] = this._divContainerHandler;
 
 		this._controlHandlers['chartTypeSelector'] = this._chartTypeControl;
 
@@ -67,11 +70,8 @@ L.Control.JSDialogBuilder = L.Control.extend({
 	},
 
 	_clearColorPickers: function() {
-		while (this._colorPickers.length) {
-			var id = this._colorPickers.pop();
-			w2ui[id].remove();
-			delete w2ui[id];
-		}
+		this._colorPickers = [];
+		L.ColorPicker.ID = 0;
 	},
 
 	_toolitemHandler: function(parentContainer, data, builder) {
@@ -100,6 +100,28 @@ L.Control.JSDialogBuilder = L.Control.extend({
 		}
 	},
 
+	_setupHandlers: function (controlElement, handlers) {
+		if (handlers) {
+			for (var i = 0; i < handlers.length; ++i) {
+				var event = handlers[i].event;
+				var handler = handlers[i].handler;
+				if (!L.isEmpty(event) && handler) {
+					if (event === 'click') {
+						var eventData = {
+							id: controlElement.id
+						};
+						$(controlElement).click(
+							// avoid to access mutable variable (that is `i` dependent) in closure
+							(function (lhandler, leventData) {
+								return function() { lhandler(leventData) };
+							})(handler, eventData)
+						);
+					}
+				}
+			}
+		}
+	},
+
 	_cleanText: function(text) {
 		if (!text)
 			return '';
@@ -458,7 +480,7 @@ L.Control.JSDialogBuilder = L.Control.extend({
 
 		var entries = [];
 		for (var index in data.entries) {
-			var entry = { type: 'fixedtext', text: data.entries[index], isComboboxItem: true };
+			var entry = { type: 'fixedtext', text: data.entries[index], style: 'ui-combobox-text' };
 			entries.push(entry);
 		}
 
@@ -470,13 +492,13 @@ L.Control.JSDialogBuilder = L.Control.extend({
 	},
 
 	_fixedtextControl: function(parentContainer, data, builder) {
-		var fixedtext = L.DomUtil.create('p', 'mobile-wizard ui-text', parentContainer);
+		var fixedtext = L.DomUtil.create('p', 'mobile-wizard', parentContainer);
 		fixedtext.innerHTML = builder._cleanText(data.text);
 		fixedtext.id = data.id;
-
-		if (data.isComboboxItem) {
-			$(fixedtext).removeClass('ui-text');
-			$(fixedtext).addClass('ui-combobox-text');
+		if (data.style && data.style.length) {
+			L.DomUtil.addClass(fixedtext, data.style);
+		} else {
+			L.DomUtil.addClass(fixedtext, 'ui-text');
 		}
 
 		if (data.hidden)
@@ -530,30 +552,67 @@ L.Control.JSDialogBuilder = L.Control.extend({
 		return false;
 	},
 
+	_divContainerHandler: function (parentContainer, data, builder) {
+		if (!(data.children && data.children.length))
+			return false;
+
+		var divElem = L.DomUtil.create('div', 'mobile-wizard', parentContainer);
+		if (data.style && data.style.length)
+			L.DomUtil.addClass(divElem, data.style);
+		for (var i = 0; i < data.children.length; ++i) {
+			var entry = data.children[i];
+			var handle = builder._controlHandlers[entry.type];
+			if (handle) {
+				handle(divElem, entry, builder);
+			}
+		}
+		builder._setupHandlers(divElem, data.handlers);
+		return false;
+	},
+
+	_colorSampleControl: function (parentContainer, data, builder) {
+		var sampleSizeClass = 'color-sample-small';
+		if (data.size === 'big')
+			sampleSizeClass = 'color-sample-big';
+		var colorSample = L.DomUtil.create('div', 'mobile-wizard ' + sampleSizeClass, parentContainer);
+		colorSample.id = data.id;
+		colorSample.style.backgroundColor = data.color;
+		colorSample.name = data.color.substring(1);
+
+		if (data.selected && data.mark) {
+			colorSample.appendChild(data.mark);
+		}
+
+		 builder._setupHandlers(colorSample, data.handlers);
+
+		 return false;
+	},
+
 	_colorControl: function(parentContainer, data, builder) {
-		var colorContainer = L.DomUtil.create('div', 'colorcontainer', parentContainer);
-		colorContainer.id = data.command.substr('.uno:'.length);
+		var title = data.text;
+		title = builder._cleanText(title);
 
-		if (data.enabled == 'false')
-			$(colorContainer).attr('disabled', 'disabled');
+		var selectedColor = L.ColorPicker.BASIC_COLORS[1];
+		var valueNode =  L.DomUtil.create('div', 'color-sample-selected', null);
+		valueNode.style.backgroundColor = selectedColor;
 
-		var imageContainer = L.DomUtil.create('div', 'colorimagecontainer', colorContainer);
-		var image = L.DomUtil.create('img', 'colorimage', imageContainer);
-		var icon = builder._createIconPath(data.command);
-		image.src = icon;
+		var iconPath = builder._createIconPath(data.command);
+		var noColorControl = data.command !== '.uno:FontColor';
 
-		var toolbarContainer = L.DomUtil.create('div', 'colorspan', colorContainer);
-		var toolbar = $(toolbarContainer);
-		var id = 'colorselector-' + builder._colorPickers.length;
-		var items = [{type: 'color',  id: 'color'}];
-		toolbar.w2toolbar({
-			name: id,
-			tooltip: 'bottom',
-			items: items
-		});
-		w2ui[id].set('color', {color: '#ff0033'});
-		builder._colorPickers.push(id);
+		var colorPickerControl = new L.ColorPicker(
+			valueNode,
+			{
+				selectedColor: selectedColor,
+				noColorControl: noColorControl
+			});
+		builder._colorPickers.push(colorPickerControl);
 
+		// color control panel
+		var colorsContainer = colorPickerControl.getContainer();
+
+		var contentNode = {type: 'container', children: [colorsContainer]};
+
+		builder._explorableEntry(parentContainer, title, contentNode, builder, valueNode, iconPath);
 		return false;
 	},
 
diff --git a/loleaflet/src/core/Util.js b/loleaflet/src/core/Util.js
index 5d25f5ec5..04b3638f9 100644
--- a/loleaflet/src/core/Util.js
+++ b/loleaflet/src/core/Util.js
@@ -191,6 +191,10 @@ L.Util = {
 		} else if (document.webkitExitFullscreen) {
 			document.webkitExitFullscreen();
 		}
+	},
+
+	isEmpty: function(o) {
+		return !(o && o.length);
 	}
 };
 
@@ -240,3 +244,4 @@ L.setOptions = L.Util.setOptions;
 L.round = L.Util.round;
 L.getDpiScaleFactor = L.Util.getDpiScaleFactor;
 L.toggleFullScreen = L.Util.toggleFullScreen;
+L.isEmpty = L.Util.isEmpty;


More information about the Libreoffice-commits mailing list