diff --git a/browser/Makefile.am b/browser/Makefile.am index 4d08a8fef762a..1ff65b43396f2 100644 --- a/browser/Makefile.am +++ b/browser/Makefile.am @@ -235,19 +235,19 @@ COOL_JS_LST =\ src/app/DocEvents.ts \ src/app/GraphicSelectionMiddleware.ts \ src/app/SearchService.ts \ + src/app/Rectangle.ts \ + src/app/Util.ts \ + src/app/LOUtil.ts \ src/Leaflet.js \ src/errormessages.js \ src/unocommands.js \ src/UNO/Key.js \ src/core/Log.js \ src/core/Util.js \ - src/core/LOUtil.js \ src/core/geometry.ts \ - src/core/Rectangle.ts \ src/core/Class.js \ src/core/Events.js \ src/core/Socket.js \ - src/core/Matrix.js \ src/core/Debug.js \ src/geometry/Point.ts \ src/geometry/Bounds.ts \ diff --git a/browser/mocha_tests/LOUtil.test.ts b/browser/mocha_tests/LOUtil.test.ts new file mode 100644 index 0000000000000..6d5d9508b6506 --- /dev/null +++ b/browser/mocha_tests/LOUtil.test.ts @@ -0,0 +1,144 @@ +/// +/// +/// +/// +/// +/// +/// +/// + +var assert = require('assert').strict; + +describe('LOUtil static class members', function () { + + describe('stringToBounds()', function () { + it('parse from string with separaters and whitespaces', function () { + const bounds = LOUtil.stringToBounds('1, 2, \n3, \t4 '); + const expected = cool.Bounds.toBounds([[1, 2], [4, 6]]) + assert.deepEqual(expected, bounds); + }); + + it('parse from string with more than 4 numbers', function () { + const bounds = LOUtil.stringToBounds('1, 2, 3, 4, 5 '); + const expected = cool.Bounds.toBounds([[1, 2], [4, 6]]) + assert.deepEqual(expected, bounds); + }); + }); + + describe('stringToRectangles()', function () { + + it('parse one rectangle from string with separaters and whitespaces', function () { + const rectangles = LOUtil.stringToRectangles('1, 2, \n3, \t4 '); + const bottomLeft = cool.Point.toPoint(1, 6); + const bottomRight = cool.Point.toPoint(4, 6); + const topLeft = cool.Point.toPoint(1, 2); + const topRight = cool.Point.toPoint(4, 2); + const expected = [[bottomLeft, bottomRight, topLeft, topRight],] + assert.deepEqual(expected, rectangles); + }); + + it('parse two rectangles from string with separaters and whitespaces', function () { + const rectangles = LOUtil.stringToRectangles('1, 2, \n3, \t4 ; 101, 202, \t3, \n4; '); + const bottomLeft = cool.Point.toPoint(1, 6); + const bottomRight = cool.Point.toPoint(4, 6); + const topLeft = cool.Point.toPoint(1, 2); + const topRight = cool.Point.toPoint(4, 2); + const offset = cool.Point.toPoint(100, 200); + const first = [bottomLeft, bottomRight, topLeft, topRight]; + const second: cool.Point[] = []; + for (let idx = 0; idx < 4; ++idx) { + second.push(first[idx].add(offset)); + } + const expected = [first, second]; + assert.deepEqual(expected, rectangles); + }); + }); + + describe('findItemWithAttributeRecursive()', function () { + it('match at depth 0', function () { + const expected = LOUtilTestData.tree; + assert.deepEqual(expected, LOUtil.findItemWithAttributeRecursive(LOUtilTestData.tree, 'id', 'level0')); + }); + + it('match at depth 1', function () { + const expected = LOUtilTestData.tree.children[1]; + assert.deepEqual(expected, LOUtil.findItemWithAttributeRecursive(LOUtilTestData.tree, 'id', 'level1_2')); + }); + + it('match at depth 2', function () { + const expected = LOUtilTestData.tree.children[0].children[0]; + assert.deepEqual(expected, LOUtil.findItemWithAttributeRecursive(LOUtilTestData.tree, 'id', 'level2')); + }); + it('match at depth 3', function () { + const expected = LOUtilTestData.tree.children[0].children[0].children[1]; + assert.deepEqual(expected, LOUtil.findItemWithAttributeRecursive(LOUtilTestData.tree, 'id', 'level3')); + }); + + it('no match in empty tree', function () { + assert.deepEqual(null, LOUtil.findItemWithAttributeRecursive({}, 'id', 'level0')); + }); + + it('no match for value', function () { + assert.deepEqual(null, LOUtil.findItemWithAttributeRecursive(LOUtilTestData.tree, 'id', 'level100')); + }); + + it('no match for key', function () { + assert.deepEqual(null, LOUtil.findItemWithAttributeRecursive(LOUtilTestData.tree, 'somekey', 'level3')); + }); + }); + + + describe('findIndexInParentByAttribute()', function () { + it('empty tree no match', function () { + assert.equal(-1, LOUtil.findIndexInParentByAttribute({}, 'class', 'xyz')); + }); + + it('non empty tree no match', function () { + assert.equal(-1, LOUtil.findIndexInParentByAttribute(LOUtilTestData.shortTree, 'class', 'xyz')); + }); + + it('multiple matches; get first', function () { + assert.equal(2, LOUtil.findIndexInParentByAttribute(LOUtilTestData.shortTree, 'class', 'bac')); + }); + + it('unique match', function () { + assert.equal(2, LOUtil.findIndexInParentByAttribute(LOUtilTestData.shortTree, 'name', 'BAC')); + }); + }); + + describe('_doRectanglesIntersect()', function () { + + it('rectangle intersects with itself', function () { + assert.ok(LOUtil._doRectanglesIntersect([10, 20, 100, 200], [10, 20, 100, 200])); + }); + + it('A contains B, there is intersection', function () { + assert.ok(LOUtil._doRectanglesIntersect([10, 20, 100, 200], [11, 21, 90, 190])); + }); + + it('B contains A, there is intersection', function () { + assert.ok(LOUtil._doRectanglesIntersect([11, 21, 90, 190], [10, 20, 100, 200])); + }); + + it('A meets B tangentially (vertical)', function () { + assert.ok(LOUtil._doRectanglesIntersect([10, 20, 100, 200], [110, 20, 10, 200])); + }); + + it('A meets B tangentially (horizontal)', function () { + assert.ok(LOUtil._doRectanglesIntersect([10, 20, 100, 200], [10, 220, 100, 20])); + }); + + it('A meets B tangentially (single point)', function () { + assert.ok(LOUtil._doRectanglesIntersect([10, 20, 100, 200], [110, 220, 10, 20])); + }); + + it('disjoint (bug in the function)', function () { + assert.ok(LOUtil._doRectanglesIntersect([10, 20, 100, 200], [111, 221, 100, 200])); + }); + + it('disjoint (rectangles very far away)', function () { + assert.ok(!LOUtil._doRectanglesIntersect([10, 20, 10, 20], [400, 500, 10, 20])); + }); + }); + +}); diff --git a/browser/mocha_tests/Rectangle.test.ts b/browser/mocha_tests/Rectangle.test.ts index 505bc4f1c6007..cd0b7f2bc9436 100644 --- a/browser/mocha_tests/Rectangle.test.ts +++ b/browser/mocha_tests/Rectangle.test.ts @@ -1,6 +1,6 @@ /// /// -/// +/// var assert = require('assert').strict; @@ -350,4 +350,4 @@ describe('coordinate API tests', function () { }); // coords.forEach -}); // root describe \ No newline at end of file +}); // root describe diff --git a/browser/mocha_tests/Util.test.ts b/browser/mocha_tests/Util.test.ts new file mode 100644 index 0000000000000..bf0958a02db4d --- /dev/null +++ b/browser/mocha_tests/Util.test.ts @@ -0,0 +1,215 @@ +/// +/// +/// + +var assert = require('assert'); + +describe('Util static members tests', function () { + + describe('stamp()', function () { + const obj1 = { _leaflet_id: -1 }; + const obj2 = { _leaflet_id: -1 }; + let obj1Id = Util.stamp(obj1); + let obj2Id = Util.stamp(obj2); + it('first: id must be > 0', function() { + assert.ok(obj1Id > 0); + }); + + it('second: id must be > 0', function() { + assert.ok(obj2Id > 0); + }); + + it('first objects id must be less than id of second object', function() { + assert.ok(obj1Id < obj2Id); + }); + + it('first: id must not change', function () { + assert.equal(obj1Id, Util.stamp(obj1)); + }); + + it('second: id must not change', function () { + assert.equal(obj2Id, Util.stamp(obj2)); + }); + + }); + + describe('formatNum()', function() { + it('integer with no decimal places', function () { + assertFloat(Util.formatNum(5, 0), 5, 1e-5, ''); + }); + + it('integer with 4 decimal places', function () { + assertFloat(Util.formatNum(5, 4), 5, 1e-5, ''); + }); + + it('decimal with 1 decimal places no-round', function () { + assertFloat(Util.formatNum(5.30333333, 1), 5.3, 1e-5, ''); + }); + + it('decimal with 4 decimal places no-round', function () { + assertFloat(Util.formatNum(5.30333333, 4), 5.3033, 1e-5, ''); + }); + + it('decimal with 1 decimal places round', function () { + assertFloat(Util.formatNum(5.35333333, 1), 5.4, 1e-5, ''); + }); + + it('decimal with 4 decimal places round', function () { + assertFloat(Util.formatNum(5.30335333, 4), 5.3034, 1e-5, ''); + }); + }); + + describe('trimStart()', function () { + it('whole string is prefix', function () { + assert.strictEqual(Util.trimStart('ABC', 'ABC'), ''); + }); + + it('whole string shorter than prefix', function () { + assert.strictEqual(Util.trimStart('ABC', 'ABCD'), 'ABC'); + }); + + it('No prefix', function () { + assert.strictEqual(Util.trimStart('XYZ', 'ABCD'), 'XYZ'); + }); + + it('Multi prefix', function () { + assert.strictEqual(Util.trimStart('ABCDABCDXYZ', 'ABCD'), 'ABCDXYZ'); + }); + }); + + describe('trimEnd()', function () { + it('whole string is suffix', function () { + assert.strictEqual(Util.trimEnd('ABC', 'ABC'), ''); + }); + + it('whole string shorter than suffix', function () { + assert.strictEqual(Util.trimEnd('ABC', 'ABCD'), 'ABC'); + }); + + it('No suffix', function () { + assert.strictEqual(Util.trimEnd('XYZ', 'ABCD'), 'XYZ'); + }); + + it('Multi suffix', function () { + assert.strictEqual(Util.trimEnd('XYZABCDABCD', 'ABCD'), 'XYZABCD'); + }); + }); + + describe('trim()', function () { + it('trim() with no prefix or suffix argument', function () { + assert.strictEqual(Util.trim('\t \tCONTENT \t\t \t'), 'CONTENT'); + }); + + it('whole string is prefix', function () { + assert.strictEqual(Util.trim('ABC', 'ABC'), ''); + }); + + it('whole string shorter than prefix', function () { + assert.strictEqual(Util.trim('ABC', 'ABCD'), 'ABC'); + }); + + it('whole string is suffix', function () { + assert.strictEqual(Util.trim('ABC', ' ', 'ABC'), ''); + }); + + it('whole string shorter than suffix', function () { + assert.strictEqual(Util.trim('ABC', '', 'ABCD'), 'ABC'); + }); + + it('No prefix', function () { + assert.strictEqual(Util.trim('XYZ', 'ABCD'), 'XYZ'); + }); + + it('No suffix', function () { + assert.strictEqual(Util.trim('XYZ', '', 'ABCD'), 'XYZ'); + }); + + it('Multi prefix and suffix', function () { + assert.strictEqual(Util.trim('ABCDABCDXYZABCDABCD', 'ABCD', 'ABCD'), 'ABCDXYZABCD'); + }); + + it('Overlapping prefix and suffix', function () { + assert.strictEqual(Util.trim('ABCDAB', 'ABCD', 'CDAB'), 'AB'); + }); + }); + + describe('splitWords()', function () { + it('split empty string', function () { + assert.deepEqual(Util.splitWords(''), ['']); + }); + + it('split string with white spaces', function () { + assert.deepEqual(Util.splitWords(' \t \t\t '), ['']); + }); + + it('split string with single word', function () { + assert.deepEqual(Util.splitWords('ABC'), ['ABC']); + }); + + it('split string with single word surrounded by multi white-spaces', function () { + assert.deepEqual(Util.splitWords(' \t \t \t\t ABC\t \t\t \t'), ['ABC']); + }); + + it('split string with two words', function () { + assert.deepEqual(Util.splitWords(' \t \t \t\t ABC\t \t\t \tXYZ \t\t \t'), ['ABC', 'XYZ']); + }); + }); + + describe('round()', function() { + it('integer with no decimal places', function () { + assertFloat(Util.round(5), 5, 1e-5, ''); + }); + + it('integer with 4 decimal places', function () { + assertFloat(Util.round(5, 1e-4), 5, 1e-5, ''); + }); + + it('decimal with 1 decimal places no-round', function () { + assertFloat(Util.round(5.30333333, 0.1), 5.3, 1e-5, ''); + }); + + it('decimal with 4 decimal places no-round', function () { + assertFloat(Util.round(5.30333333, 0.0001), 5.3033, 1e-5, ''); + }); + + it('decimal with 1 decimal places round', function () { + assertFloat(Util.round(5.35333333, 0.1), 5.4, 1e-5, ''); + }); + + it('decimal with 4 decimal places round', function () { + assertFloat(Util.round(5.30335333, 0.0001), 5.3034, 1e-5, ''); + }); + }); + + describe('template()', function () { + it('empty string', function () { + assert.strictEqual(Util.template('', {}), ''); + }); + + it('no substitutions', function () { + assert.strictEqual(Util.template('cool apps', {'cool': 32}), 'cool apps'); + }); + + it('one key one substitution', function () { + assert.strictEqual(Util.template('cool { app } abcd', {'cool': 32, 'app': 'calc'}), 'cool calc abcd'); + }); + + it('one key two substitutions', function () { + assert.strictEqual(Util.template('A {app } cool { app} abcd', {'cool': 32, 'app': 'calc'}), 'A calc cool calc abcd'); + }); + + it('two keys multiple substitutions', function () { + assert.strictEqual(Util.template('A) { app1}, B) {app2 }, C) { app2}, D) { app1 } ', {'cool': 32, 'app': 'calc', 'app1': 'draw', 'app2': 'impress'}), 'A) draw, B) impress, C) impress, D) draw '); + }); + + it('key function', function () { + assert.strictEqual(Util.template('{fkey }, { key }', { + 'key': '1234', + 'fkey': function(data: any) { + return data['key'] + '_999'; + }, + }), '1234_999, 1234'); + }); + }); + +}); diff --git a/browser/mocha_tests/data/LOUtilTestData.ts b/browser/mocha_tests/data/LOUtilTestData.ts new file mode 100644 index 0000000000000..59d74d92cae6d --- /dev/null +++ b/browser/mocha_tests/data/LOUtilTestData.ts @@ -0,0 +1,44 @@ +class LOUtilTestData { + public static tree = { + 'id': 'level0', + 'children': [ + { + 'id': 'level1_1', + 'children': [ + { + 'id': 'level2', + 'children': [ + { + 'id': 'level3_0', + 'data': 4321, + }, + { + 'id': 'level3', + 'children': [ + { + 'id': 'level4', + 'data': 1234, + }, + ], + }, + ], + }, + ], + }, + { + 'id': 'level1_2', + }, + ], + }; + + public static shortTree = { + id: 'level0', + children: [ + { 'class': 'abc', 'name': 'ABC', }, + { 'class': 'abc', 'name': 'ABC1', }, + { 'class': 'bac', 'name': 'BAC', }, + { 'class': 'bac', 'name': 'BAC1', }, + { 'class': 'cab', 'name': 'CAB', }, + ], + }; +} diff --git a/browser/src/app/LOUtil.ts b/browser/src/app/LOUtil.ts new file mode 100644 index 0000000000000..d0005fad06bd3 --- /dev/null +++ b/browser/src/app/LOUtil.ts @@ -0,0 +1,460 @@ +/* -*- js-indent-level: 8 -*- */ +/* global app */ +/* + * Copyright the Collabora Online contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +interface DOMObjectLike { + [index: string]: any; + children?: DOMObjectLike[]; +} + +interface RectangleLike { + top: number; + left: number; + bottom: number; + right: number; +} + +// LOUtil contains various LO related utility functions used +// throughout the code. + +class LOUtil { + // Based on core.git's colordata.hxx: COL_AUTHOR1_DARK...COL_AUTHOR9_DARK + // consisting of arrays of RGB values + // Maybe move the color logic to separate file when it becomes complex + public static darkColors = [ + [198, 146, 0], + [6, 70, 162], + [87, 157, 28], + [105, 43, 157], + [197, 0, 11], + [0, 128, 128], + [140, 132, 0], + [53, 85, 107], + [209, 118, 0], + ]; + + public static onRemoveHTMLElement( + element: Element, + onDetachCallback: () => void, + ) { + const observer = new MutationObserver(function () { + function isDetached(el: Element) { + return !el.closest('html'); + } + + if (isDetached(element)) { + onDetachCallback(); + observer.disconnect(); + } + }); + + observer.observe(document, { + childList: true, + subtree: true, + }); + } + + public static startSpinner( + spinnerCanvas: HTMLCanvasElement, + spinnerSpeed: number, + ): NodeJS.Timer { + spinnerCanvas.width = 50; + spinnerCanvas.height = 50; + + const context = spinnerCanvas.getContext('2d'); + context.lineWidth = 8; + context.strokeStyle = 'grey'; + const x = spinnerCanvas.width / 2; + const y = spinnerCanvas.height / 2; + const radius = y - context.lineWidth / 2; + const spinnerInterval = setInterval(function () { + context.clearRect(0, 0, x * 2, y * 2); + // Move to center + context.translate(x, y); + context.rotate((spinnerSpeed * Math.PI) / 180); + context.translate(-x, -y); + context.beginPath(); + context.arc(x, y, radius, 0, Math.PI * 1.3); + context.stroke(); + }, 30); + + return spinnerInterval; + } + + public static getViewIdColor(viewId: number): number { + const color = LOUtil.darkColors[(viewId + 1) % LOUtil.darkColors.length]; + return color[2] | (color[1] << 8) | (color[0] << 16); + } + + public static rgbToHex(color: number) { + return '#' + ('000000' + color.toString(16)).slice(-6); + } + + public static stringToBounds(bounds: string): cool.Bounds { + const numbers = bounds.match(/\d+/g); + const topLeft = cool.Point.toPoint( + parseInt(numbers[0]), + parseInt(numbers[1]), + ); + const bottomRight = topLeft.add( + L.point(parseInt(numbers[2]), parseInt(numbers[3])), + ); + return cool.Bounds.toBounds(topLeft, bottomRight); + } + + public static stringToRectangles(strRect: string): cool.Point[][] { + const matches = strRect.match(/\d+/g); + const rectangles: cool.Point[][] = []; + if (matches !== null) { + for (let itMatch = 0; itMatch < matches.length; itMatch += 4) { + const topLeft = cool.Point.toPoint( + parseInt(matches[itMatch]), + parseInt(matches[itMatch + 1]), + ); + const size = cool.Point.toPoint( + parseInt(matches[itMatch + 2]), + parseInt(matches[itMatch + 3]), + ); + const topRight = topLeft.add(L.point(size.x, 0)); + const bottomLeft = topLeft.add(L.point(0, size.y)); + const bottomRight = topLeft.add(size); + rectangles.push([bottomLeft, bottomRight, topLeft, topRight]); + } + } + return rectangles; + } + + // Some items will only be present in dark mode so we will not check errors + // for those in other mode. + public static onlydarkModeItems: string[] = ['invertbackground']; + + // Common images used in all modes, so the default one will be used. + public static commonItems: string[] = ['serverauditok', 'serverauditerror']; + + // Helper function to strip '.svg' suffix and 'lc_' prefix. + public static stripName(name: string): string { + // Remove the '.svg' suffix. + var strippedName = name.replace(/\.svg$/, ''); + + // Remove the 'lc_' prefix if it exists. + if (strippedName.startsWith('lc_')) { + strippedName = strippedName.substring(3); + } + + return strippedName; + } + + public static isDarkModeItem(name: string): boolean { + const strippedName = LOUtil.stripName(name); + + // Check if the stripped name is in the onlydarkModeItems array. + return LOUtil.onlydarkModeItems.includes(strippedName); + } + + public static isCommonForAllMode(name: string): boolean { + const strippedName = LOUtil.stripName(name); + + // Check if the stripped name is in the commonItems array. + return LOUtil.commonItems.includes(strippedName); + } + + /// unwind things to get a good absolute URL. + public static getURL(path: string): string { + if (path === '') return ''; + const customWindow = window as any; + if (customWindow.host === '' && customWindow.serviceRoot === '') + return path; // mobile app + + let url = customWindow.makeHttpUrl('/browser/' + customWindow.versionPath); + if (path.substr(0, 1) !== '/') url += '/'; + + url += path; + return url; + } + + public static setImage(img: HTMLImageElement, name: string, map: any): void { + const setupIcon = function () { + img.src = LOUtil.getImageURL(name); + LOUtil.checkIfImageExists(img); + }; + setupIcon(); + + map.on('themechanged', setupIcon); + } + + public static setUserImage( + img: HTMLImageElement, + map: any, + viewId: number, + ): void { + // set avatar image if it exist in user extract info. + const defaultImage = LOUtil.getImageURL('user.svg'); + const viewInfo = map._viewInfo[viewId]; + if ( + viewInfo !== undefined && + viewInfo.userextrainfo !== undefined && + viewInfo.userextrainfo.avatar !== undefined + ) { + // set user avatar. + img.src = viewInfo.userextrainfo.avatar; + // Track if error event is already bound to this image. + img.addEventListener( + 'error', + function () { + img.src = defaultImage; + LOUtil.checkIfImageExists(img, true); + }, + { once: true }, + ); + return; + } + img.src = defaultImage; + LOUtil.checkIfImageExists(img, true); + } + + public static getImageURL(imgName: string) { + let defaultImageURL = LOUtil.getURL('images/' + imgName); + + // Check if the image name is in the commonItems list and return the normal image path + if (LOUtil.isCommonForAllMode(imgName)) { + return defaultImageURL; + } + + if ((window as any).prefs.getBoolean('darkTheme')) { + return LOUtil.getURL('images/dark/' + imgName); + } + + const dummyEmptyImg = + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='; + defaultImageURL = LOUtil.isDarkModeItem(imgName) + ? dummyEmptyImg + : defaultImageURL; + return defaultImageURL; + } + + public static checkIfImageExists( + imageElement: HTMLImageElement, + imageIsLayoutCritical?: boolean, + ): void { + imageElement.addEventListener('error', function (e: any) { + if (e.loUtilProcessed) { + return; + } + + if ( + imageElement.src && + imageElement.src.includes('/images/branding/dark/') + ) { + imageElement.src = imageElement.src.replace( + '/images/branding/dark/', + '/images/dark/', + ); + e.loUtilProcessed = true; + return; + } + if ( + imageElement.src && + (imageElement.src.includes('/images/dark/') || + imageElement.src.includes('/images/branding/')) + ) { + imageElement.src = imageElement.src.replace( + '/images/dark/', + '/images/', + ); + imageElement.src = imageElement.src.replace( + '/images/branding/', + '/images/', + ); + e.loUtilProcessed = true; + return; + } + + if (imageIsLayoutCritical) { + imageElement.src = + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='; + // We cannot set visibility: hidden because that would hide + // other attributes of the image, e.g. its border. + e.loUtilProcessed = true; + return; + } + + imageElement.style.display = 'none'; + e.loUtilProcessed = true; + }); + } + + /// oldFileName = Example.odt, suffix = new + /// returns: Example_new.odt + public static generateNewFileName( + oldFileName: string, + suffix: string, + ): string { + const idx = oldFileName.lastIndexOf('.'); + return oldFileName.substring(0, idx) + suffix + oldFileName.substring(idx); + } + + public static commandWithoutIcon: string[] = [ + 'InsertPageHeader', + 'InsertPageFooter', + 'FLD_COL_NUMBER', + 'MTR_FLD_COL_SPACING', + 'rows', + 'cols', + 'None', + ]; + + public static existsIconForCommand( + command: string, + docType: string, + ): boolean { + const commandName = command.startsWith('.uno:') + ? command.substring('.uno:'.length) + : command; + const res = !LOUtil.commandWithoutIcon.find(function (el: string) { + return el.startsWith(commandName); + }); + if (commandName.indexOf('?') !== -1) { + if ( + commandName.indexOf('SpellCheckIgnore') !== -1 || + commandName.indexOf('SpellCheckIgnoreAll') !== -1 + ) + return true; + + if ( + (docType === 'spreadsheet' || docType === 'presentation') && + commandName.indexOf('LanguageStatus') !== -1 + ) + return true; + + if ( + commandName === + 'LanguageStatus?Language:string=Current_LANGUAGE_NONE' || + commandName === + 'LanguageStatus?Language:string=Current_RESET_LANGUAGES' || + commandName === + 'LanguageStatus?Language:string=Paragraph_LANGUAGE_NONE' || + commandName === + 'LanguageStatus?Language:string=Paragraph_RESET_LANGUAGES' + ) + return true; + + return false; + } + return res; + } + + /// Searching in JSON trees for data with a given field. + public static findItemWithAttributeRecursive( + node: DOMObjectLike, + idName: string, + idValue: any, + ): DOMObjectLike | null { + let found: DOMObjectLike | null = null; + if (node[idName] === idValue) return node; + if (node.children) { + for (var i = 0; !found && i < node.children.length; i++) + found = LOUtil.findItemWithAttributeRecursive( + node.children[i], + idName, + idValue, + ); + } + return found; + } + + /// Searching in JSON trees for an identifier and return the index in parent. + public static findIndexInParentByAttribute( + node: DOMObjectLike, + idName: string, + idValue: any, + ): number { + if (node.children) { + for (var i = 0; i < node.children.length; i++) + if (node.children[i][idName] === idValue) return i; + } + return -1; + } + + public static _doRectanglesIntersect( + rectangle1: number[], + rectangle2: number[], + ): boolean { + // Format: (x, y, w, h). + // Don't use equality in comparison, that's not an intersection. + if ( + Math.abs( + rectangle1[0] + + rectangle1[2] * 0.5 - + (rectangle2[0] + rectangle2[2] * 0.5), + ) < + rectangle1[2] + rectangle2[2] + ) { + if ( + Math.abs( + rectangle1[1] + + rectangle1[3] * 0.5 - + (rectangle2[1] + rectangle2[3] * 0.5), + ) < + rectangle1[3] + rectangle2[3] + ) + return true; + else return false; + } else return false; + } + + // Returns the intersecting area of 2 rectangles. Rectangle format: (x, y, w, h). Return format is the same or null. + public static _getIntersectionRectangle( + rectangle1: number[], + rectangle2: number[], + ): number[] | null { + if (this._doRectanglesIntersect(rectangle1, rectangle2)) { + var x = rectangle1[0] > rectangle2[0] ? rectangle1[0] : rectangle2[0]; + var y = rectangle1[1] > rectangle2[1] ? rectangle1[1] : rectangle2[1]; + var w = + rectangle1[0] + rectangle1[2] < rectangle2[0] + rectangle2[2] + ? rectangle1[0] + rectangle1[2] - x + : rectangle2[0] + rectangle2[2] - x; + var h = + rectangle1[1] + rectangle1[3] < rectangle2[1] + rectangle2[3] + ? rectangle1[1] + rectangle1[3] - y + : rectangle2[1] + rectangle2[3] - y; + + return [x, y, w, h]; + } else return null; + } + + public static getFileExtension(map: any): string { + const filename: string = map['wopi'].BaseFileName; + return filename.substring(filename.lastIndexOf('.') + 1); + } + + public static isFileODF(map: any): boolean { + var ext = LOUtil.getFileExtension(map); + return ext === 'odt' || ext === 'ods' || ext === 'odp' || ext == 'odg'; + } + + public static containsDOMRect( + viewRect: RectangleLike, + rect: RectangleLike, + ): boolean { + return ( + rect.top >= viewRect.top && + rect.right <= viewRect.right && + rect.bottom <= viewRect.bottom && + rect.left >= viewRect.left + ); + } + + public static Rectangle = cool.Rectangle; + public static createRectangle = cool.createRectangle; +} + +app.LOUtil = LOUtil; diff --git a/browser/src/app/Rectangle.ts b/browser/src/app/Rectangle.ts new file mode 100644 index 0000000000000..0fec8a6c44954 --- /dev/null +++ b/browser/src/app/Rectangle.ts @@ -0,0 +1,261 @@ +/* -*- js-indent-level: 8 -*- */ +/* + * Copyright the Collabora Online contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +namespace cool { + /** + * Represents a rectangle object which works with core pixels. + * x1 and y1 should always <= x2 and y2. In other words width >= 0 && height >= 0 is a precondition. + * This class doesn't check for above conditions. There is a isValid function for use when needed. + */ + export class Rectangle { + private x1: number; + private y1: number; + private width: number; + private height: number; + + constructor(x: number, y: number, width: number, height: number) { + this.x1 = x; + this.y1 = y; + this.width = width; + this.height = height; + } + + // convenience private getters + + private get x2(): number { + return this.x1 + this.width; + } + + private get y2(): number { + return this.y1 + this.height; + } + + private get area(): number { + return this.width * this.height; + } + + // Rounded coordinates private getters + + private get rx1(): number { + return Math.round(this.x1); + } + + private get ry1(): number { + return Math.round(this.y1); + } + + private get rx2(): number { + return Math.round(this.x2); + } + + private get ry2(): number { + return Math.round(this.y2); + } + + private get rwidth(): number { + return this.rx2 - this.rx1; + } + + private get rheight(): number { + return this.ry2 - this.ry1; + } + + private get rarea(): number { + return this.rwidth * this.rheight; + } + + public isValid(): boolean { + if (this.x1 <= this.x2 && this.y1 <= this.y2) return true; + return false; + } + + public clone(): Rectangle { + return new Rectangle(this.x1, this.x2, this.width, this.height); + } + + public containsPoint(x: number, y: number): boolean { + if (x >= this.x1 && x <= this.x2 && y >= this.y1 && y <= this.y2) + return true; + + return false; + } + + public containsPixel(px: number, py: number): boolean { + if (px >= this.rx1 && px <= this.rx2 && py >= this.ry1 && py <= this.ry2) + return true; + + return false; + } + + public containsXOrdinate(ox: number): boolean { + if (ox >= this.x1 && ox <= this.x2) return true; + + return false; + } + + public containsYOrdinate(oy: number): boolean { + if (oy >= this.y1 && oy <= this.y2) return true; + + return false; + } + + public containsPixelOrdinateX(ox: number): boolean { + if (ox >= this.rx1 && ox <= this.rx2) return true; + + return false; + } + + public containsPixelOrdinateY(oy: number): boolean { + if (oy >= this.ry1 && oy <= this.ry2) return true; + + return false; + } + + /// Sets x1 of the rectangle without changing x2. + public setX1(x1: number): void { + this.width += this.x1 - x1; + this.x1 = x1; + } + + /// Sets x2 of the rectangle without changing x1. + public setX2(x2: number): void { + this.width = x2 - this.x1; + } + + /// Sets y1 of the rectangle without changing y2. + public setY1(y1: number): void { + this.height += this.y1 - y1; + this.y1 = y1; + } + + /// Sets y2 of the rectangle without changing y1. + public setY2(y2: number): void { + this.height = y2 - this.y1; + } + + /// Sets width keeping x1 constant. + public setWidth(width: number): void { + this.width = width; + } + + /// Sets height keeping y1 constant. + public setHeight(height: number): void { + this.height = height; + } + + /// Sets area by either keeping height or width as constant. + public setArea(area: number, preserveHeight: boolean): void { + if (!preserveHeight) { + //preserve width + const height = area / this.width; + this.setHeight(height); + } else { + // preserve height + const width = area / this.height; + this.setWidth(width); + } + } + + /// Moves the whole rectangle by (dx, dy) by preserving width and height. + public moveBy(dx: number, dy: number): void { + this.x1 += dx; + this.y1 += dy; + } + + /** + * Moves the rectangle to (x, y) as its new x1, y1 without changing + * its size. + */ + public moveTo(x: number, y: number): void { + this.x1 = x; + this.y1 = y; + } + + // TODO: Following methods could be replaced with js getters + // but we need to change their users to access getters. + + public getX1(): number { + return this.x1; + } + + public getX2(): number { + return this.x2; + } + + public getY1(): number { + return this.y1; + } + + public getY2(): number { + return this.y2; + } + + public getWidth(): number { + return this.width; + } + + public getHeight(): number { + return this.height; + } + + public getArea(): number { + return this.area; + } + + public getCenter(): number[] { + return [(this.x2 + this.x1) / 2, (this.y2 + this.y1) / 2]; + } + + public getPxX1(): number { + return this.rx1; + } + + public getPxX2(): number { + return this.rx2; + } + + public getPxY1(): number { + return this.ry1; + } + + public getPxY2(): number { + return this.ry2; + } + + public getPxWidth(): number { + return this.rwidth; + } + + public getPxHeight(): number { + return this.rheight; + } + + public getPxArea(): number { + return this.rarea; + } + + public getPxCenter(): number[] { + return [ + Math.round((this.rx2 + this.rx1) / 2), + Math.round((this.ry2 + this.ry1) / 2), + ]; + } + } + + export function createRectangle( + x: number, + y: number, + width: number, + height: number, + ): Rectangle { + return new Rectangle(x, y, width, height); + } +} diff --git a/browser/src/app/Util.ts b/browser/src/app/Util.ts new file mode 100644 index 0000000000000..9802c8f128f73 --- /dev/null +++ b/browser/src/app/Util.ts @@ -0,0 +1,298 @@ +/* -*- js-indent-level: 8 -*- */ +/* + * Copyright the Collabora Online contributors. + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +declare var brandProductFAQURL: string | undefined; + +interface IDAble { + _leaflet_id: number; + [name: string]: any; +} + +type CallbackFunctionVariadic = (...args: any[]) => void; + +class Util { + private static lastId = 0; + private static nextId(): number { + return ++Util.lastId; + } + + /// Returns the id of the object. Initializes it if necessary. + public static stamp(obj: IDAble): number { + if (obj._leaflet_id > 0) { + return obj._leaflet_id; + } + obj._leaflet_id = Util.nextId(); + return obj._leaflet_id; + } + + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + public static merge(one: any, two: any): any { + return { ...one, ...two }; + } + + // return a function that won't be called more often than the given interval + public static throttle( + fn: CallbackFunctionVariadic, + time: number, + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + context: any, + ): CallbackFunctionVariadic { + let lock: boolean = false; + // eslint-disable-next-line prefer-const + let wrapperFn: CallbackFunctionVariadic; + let args: any[] | boolean = false; + + const later = function () { + // reset lock and call if queued. + lock = false; + if (args) { + wrapperFn.apply(context, args); + args = false; + } + }; + + wrapperFn = function (...args_: any[]) { + if (lock) { + // called too soon, queue to call later + args = args_; + } else { + // call and lock until later + fn.apply(context, args_); + setTimeout(later, time); + lock = true; + } + }; + + return wrapperFn; + } + + // wrap the given number to lie within a certain range (used for wrapping longitude) + public static wrapNum( + x: number, + range: Array, + includeMax: boolean, + ): number { + const max = range[1]; + const min = range[0]; + const d = max - min; + return x === max && includeMax ? x : ((((x - min) % d) + d) % d) + min; + } + + // do nothing (used as a noop throughout the code) + public static falseFn(): boolean { + return false; + } + + // round a given number to a given precision + public static formatNum(num: number, digits: number): number { + var pow = Math.pow(10, digits || 5); + return Math.round(num * pow) / pow; + } + + // removes prefix from string if string starts with that prefix + public static trimStart(str: string, prefix: string): string { + if (str.indexOf(prefix) === 0) return str.substring(prefix.length); + return str; + } + + // removes suffix from string if string ends with that suffix + public static trimEnd(str: string, suffix: string): string { + var suffixIndex = str.lastIndexOf(suffix); + if (suffixIndex !== -1 && str.length - suffix.length === suffixIndex) + return str.substring(0, suffixIndex); + return str; + } + + // removes given prefix and suffix from the string if exists + // if suffix is not specifed prefix is trimmed from both end of string + // trim whitespace from both sides of a string if prefix and suffix are not given + public static trim(str: string, prefix?: string, suffix?: string): string { + if (!prefix) return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); + let result = Util.trimStart(str, prefix); + result = Util.trimEnd(result, suffix); + return result; + } + + // split a string into words + public static splitWords(str: string): string[] { + return Util.trim(str).split(/\s+/); + } + + public static round(x: number, e?: number): number { + if (!e) { + return Math.round(x); + } + var f = 1.0 / e; + return Math.round(x * f) * e; + } + + public static templateRe = /\{ *([\w_]+) *\}/g; + + // super-simple templating facility, used for TileLayer URLs + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + public static template(str: string, data: any): string { + return str.replace(Util.templateRe, function (str, key) { + let value: any = data[key]; + + if (value === undefined) { + throw new Error('No value provided for variable ' + str); + } else if (typeof value === 'function') { + value = value(data); + } + return value; + }); + } + + public static isArray = + Array.isArray || + function (obj) { + return Object.prototype.toString.call(obj) === '[object Array]'; + }; + + // minimal image URI, set to an image when disposing to flush memory + public static emptyImageUrl = + 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='; + + public static toggleFullScreen(): void { + const doc = document as any; + if ( + !doc.fullscreenElement && + !doc.mozFullscreenElement && + !doc.msFullscreenElement && + !doc.webkitFullscreenElement + ) { + if (doc.documentElement.requestFullscreen) { + doc.documentElement.requestFullscreen(); + } else if (doc.documentElement.msRequestFullscreen) { + doc.documentElement.msRequestFullscreen(); + } else if (doc.documentElement.mozRequestFullScreen) { + doc.documentElement.mozRequestFullScreen(); + } else if (doc.documentElement.webkitRequestFullscreen) { + doc.documentElement.webkitRequestFullscreen( + (Element as any).ALLOW_KEYBOARD_INPUT, + ); + } + } else if (doc.exitFullscreen) { + doc.exitFullscreen(); + } else if (doc.msExitFullscreen) { + doc.msExitFullscreen(); + } else if (doc.mozCancelFullScreen) { + doc.mozCancelFullScreen(); + } else if (doc.webkitExitFullscreen) { + doc.webkitExitFullscreen(); + } + } + + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + public static isEmpty(o: any): boolean { + return !(o && o.length); + } + + public static mm100thToInch(mm: number): number { + return mm / 2540; + } + + private static _canvas: HTMLCanvasElement | null = null; + + private static getTempCanvas(): HTMLCanvasElement { + if (Util._canvas) { + return Util._canvas; + } + Util._canvas = document.createElement('canvas'); + return Util._canvas; + } + + public static getTextWidth(text: string, font: string): number { + const canvas = Util.getTempCanvas(); + const context = canvas.getContext('2d'); + context.font = font; + const metrics = context.measureText(text); + return Math.floor(metrics.width); + } + + public static getProduct(): string { + let brandFAQURL = + typeof brandProductFAQURL !== 'undefined' + ? brandProductFAQURL + : 'https://collaboraonline.github.io/post/faq/'; + const customWindow = window as any; + if (customWindow.feedbackUrl && customWindow.buyProductUrl) { + const integratorUrl = encodeURIComponent(customWindow.buyProductUrl); + brandFAQURL = customWindow.feedbackUrl; + brandFAQURL = + brandFAQURL.substring(0, brandFAQURL.lastIndexOf('/')) + + '/product.html?integrator=' + + integratorUrl; + } + return brandFAQURL; + } + + public static replaceCtrlAltInMac(msg: string): string { + if (L.Browser.mac) { + var ctrl = /Ctrl/g; + var alt = /Alt/g; + const CustomString = String as any; + if ( + CustomString.locale.startsWith('de') || + CustomString.locale.startsWith('dsb') || + CustomString.locale.startsWith('hsb') + ) { + ctrl = /Strg/g; + } + if (CustomString.locale.startsWith('lt')) { + ctrl = /Vald/g; + } + if (CustomString.locale.startsWith('sl')) { + ctrl = /Krmilka/gi; + alt = /Izmenjalka/gi; + } + return msg.replace(ctrl, '⌘').replace(alt, '⌥'); + } + return msg; + } + + public static randomString(len: number): string { + let result = ''; + const ValidCharacters = + '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + for (let i = 0; i < len; i++) { + result += ValidCharacters.charAt( + Math.floor(Math.random() * ValidCharacters.length), + ); + } + return result; + } + + public static requestAnimFrame( + fn: () => void, + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + context: any, + immediate?: boolean, + ): number { + if (immediate) { + fn.call(context); + return 0; + } + + return window.requestAnimationFrame(fn.bind(context)); + } + + public static cancelAnimFrame(id: number): void { + if (id) { + window.cancelAnimationFrame(id); + } + } + + public static MAX_SAFE_INTEGER = Math.pow(2, 3) - 1; + public static MIN_SAFE_INTEGER = Util.MAX_SAFE_INTEGER; +} + +app.util = Util; diff --git a/browser/src/canvas/sections/CommentListSection.ts b/browser/src/canvas/sections/CommentListSection.ts index 7d792ccaa3edc..87556fc31d00c 100644 --- a/browser/src/canvas/sections/CommentListSection.ts +++ b/browser/src/canvas/sections/CommentListSection.ts @@ -569,7 +569,7 @@ export class CommentSection extends app.definitions.canvasSectionObject { var tdAuthor = L.DomUtil.create(tagTd, 'cool-annotation-author', tr); var imgAuthor = L.DomUtil.create('img', 'avatar-img', tdImg); var user = this.map.getViewId(commentData.author); - L.LOUtil.setUserImage(imgAuthor, this.map, user); + app.LOUtil.setUserImage(imgAuthor, this.map, user); imgAuthor.setAttribute('width', 32); imgAuthor.setAttribute('height', 32); var authorAvatarImg = imgAuthor; @@ -579,7 +579,7 @@ export class CommentSection extends app.definitions.canvasSectionObject { $(contentAuthor).text(commentData.author); $(authorAvatarImg).attr('src', commentData.avatar); if (user >= 0) { - var color = L.LOUtil.rgbToHex(this.map.getViewColor(user)); + var color = app.LOUtil.rgbToHex(this.map.getViewColor(user)); $(authorAvatarImg).css('border-color', color); } @@ -1361,7 +1361,7 @@ export class CommentSection extends app.definitions.canvasSectionObject { redline.anchorPix = this.numberArrayToCorePixFromTwips(redline.anchorPos, 0, 2); redline.trackchange = true; redline.text = redline.comment; - var rectangles = L.PolyUtil.rectanglesToPolygons(L.LOUtil.stringToRectangles(redline.textRange), app.map._docLayer); + var rectangles = L.PolyUtil.rectanglesToPolygons(app.LOUtil.stringToRectangles(redline.textRange), app.map._docLayer); if (rectangles.length > 0) { redline.textSelected = L.polygon(rectangles, { pointerEvents: 'all', @@ -1780,7 +1780,7 @@ export class CommentSection extends app.definitions.canvasSectionObject { comment.parthash = comment.parthash ? comment.parthash: null; var viewId = this.map.getViewId(comment.author); - var color = viewId >= 0 ? L.LOUtil.rgbToHex(this.map.getViewColor(viewId)) : '#43ACE8'; + var color = viewId >= 0 ? app.LOUtil.rgbToHex(this.map.getViewColor(viewId)) : '#43ACE8'; comment.color = color; } @@ -1811,7 +1811,7 @@ export class CommentSection extends app.definitions.canvasSectionObject { } var viewId = this.map.getViewId(comment.author); - var color = viewId >= 0 ? L.LOUtil.rgbToHex(this.map.getViewColor(viewId)) : '#43ACE8'; + var color = viewId >= 0 ? app.LOUtil.rgbToHex(this.map.getViewColor(viewId)) : '#43ACE8'; comment.color = color; } diff --git a/browser/src/canvas/sections/CommentSection.ts b/browser/src/canvas/sections/CommentSection.ts index f4763aac5fc0e..3837cdd0c4799 100644 --- a/browser/src/canvas/sections/CommentSection.ts +++ b/browser/src/canvas/sections/CommentSection.ts @@ -279,7 +279,7 @@ export class Comment extends CanvasSectionObject { var tdAuthor = L.DomUtil.create('td', 'cool-annotation-author', tr); var imgAuthor = L.DomUtil.create('img', 'avatar-img', tdImg); var viewId = this.map.getViewId(this.sectionProperties.data.author); - L.LOUtil.setUserImage(imgAuthor, this.map, viewId); + app.LOUtil.setUserImage(imgAuthor, this.map, viewId); imgAuthor.setAttribute('width', this.sectionProperties.imgSize[0]); imgAuthor.setAttribute('height', this.sectionProperties.imgSize[1]); @@ -471,7 +471,7 @@ export class Comment extends CanvasSectionObject { } var user = this.map.getViewId(this.sectionProperties.data.author); if (user >= 0) { - var color = L.LOUtil.rgbToHex(this.map.getViewColor(user)); + var color = app.LOUtil.rgbToHex(this.map.getViewColor(user)); this.sectionProperties.authorAvatartdImg.style.borderColor = color; } diff --git a/browser/src/canvas/sections/ContentControlSection.ts b/browser/src/canvas/sections/ContentControlSection.ts index 05e234ca17d82..984751ff85a43 100644 --- a/browser/src/canvas/sections/ContentControlSection.ts +++ b/browser/src/canvas/sections/ContentControlSection.ts @@ -181,7 +181,7 @@ export class ContentControlSection extends CanvasSectionObject { var fontStyle = getComputedStyle(document.body).getPropertyValue('--docs-font').split(',')[0].replace(/'/g, ''); var fontSize = getComputedStyle(document.body).getPropertyValue('--default-font-size'); var font = fontSize + ' ' + fontStyle; - var textWidth: number = L.Util.getTextWidth(text, font) + padding; + var textWidth: number = app.util.getTextWidth(text, font) + padding; // draw rectangle with backgroundcolor this.context.beginPath(); diff --git a/browser/src/canvas/sections/OtherViewCellCursorSection.ts b/browser/src/canvas/sections/OtherViewCellCursorSection.ts index 163704705bb12..b70767fae6144 100644 --- a/browser/src/canvas/sections/OtherViewCellCursorSection.ts +++ b/browser/src/canvas/sections/OtherViewCellCursorSection.ts @@ -27,7 +27,7 @@ class OtherViewCellCursorSection extends CanvasSectionObject { this.size = [rectangle.pWidth, rectangle.pHeight]; this.position = [rectangle.pX1, rectangle.pY1]; - this.sectionProperties.color = L.LOUtil.rgbToHex(L.LOUtil.getViewIdColor(viewId)); + this.sectionProperties.color = app.LOUtil.rgbToHex(app.LOUtil.getViewIdColor(viewId)); this.name = OtherViewCellCursorSection.sectionNamePrefix + viewId; this.sectionProperties.viewId = viewId; diff --git a/browser/src/canvas/sections/OtherViewCursorSection.ts b/browser/src/canvas/sections/OtherViewCursorSection.ts index 6d85dadcf16f6..3337478b47a24 100644 --- a/browser/src/canvas/sections/OtherViewCursorSection.ts +++ b/browser/src/canvas/sections/OtherViewCursorSection.ts @@ -58,7 +58,7 @@ class OtherViewCursorSection extends HTMLObjectSection { public static addOrUpdateOtherViewCursor(viewId: number, username: string, rectangleData: Array, part: number, mode: number) { let rectangle = new cool.SimpleRectangle(0, 0, 0, 0); - const color = L.LOUtil.rgbToHex(L.LOUtil.getViewIdColor(viewId)); + const color = app.LOUtil.rgbToHex(app.LOUtil.getViewIdColor(viewId)); if (rectangleData) { rectangle = new app.definitions.simpleRectangle(rectangleData[0], rectangleData[1], rectangleData[2], rectangleData[3]); diff --git a/browser/src/canvas/sections/OtherViewGraphicSelectionSection.ts b/browser/src/canvas/sections/OtherViewGraphicSelectionSection.ts index 061ba700da856..f3e65e7425578 100644 --- a/browser/src/canvas/sections/OtherViewGraphicSelectionSection.ts +++ b/browser/src/canvas/sections/OtherViewGraphicSelectionSection.ts @@ -27,7 +27,7 @@ class OtherViewGraphicSelectionSection extends CanvasSectionObject { this.size = [rectangle.pWidth, rectangle.pHeight]; this.position = [rectangle.pX1, rectangle.pY1]; - this.sectionProperties.color = L.LOUtil.rgbToHex(L.LOUtil.getViewIdColor(viewId)); + this.sectionProperties.color = app.LOUtil.rgbToHex(app.LOUtil.getViewIdColor(viewId)); this.name = OtherViewGraphicSelectionSection.sectionNamePrefix + viewId; this.sectionProperties.viewId = viewId; diff --git a/browser/src/canvas/sections/URLPopUpSection.ts b/browser/src/canvas/sections/URLPopUpSection.ts index d1c820b507475..bda0ed03ad476 100644 --- a/browser/src/canvas/sections/URLPopUpSection.ts +++ b/browser/src/canvas/sections/URLPopUpSection.ts @@ -58,7 +58,7 @@ class URLPopUpSection extends HTMLObjectSection { copyBtn.setAttribute('title', _('Copy link location')); const imgCopyBtn = L.DomUtil.create('img', 'hyperlink-pop-up-copyimg', copyBtn); - L.LOUtil.setImage(imgCopyBtn, 'lc_copyhyperlinklocation.svg', app.map); + app.LOUtil.setImage(imgCopyBtn, 'lc_copyhyperlinklocation.svg', app.map); imgCopyBtn.setAttribute('width', 18); imgCopyBtn.setAttribute('height', 18); imgCopyBtn.style.padding = '4px'; @@ -68,7 +68,7 @@ class URLPopUpSection extends HTMLObjectSection { editBtn.setAttribute('title', _('Edit link')); const imgEditBtn = L.DomUtil.create('img', 'hyperlink-pop-up-editimg', editBtn); - L.LOUtil.setImage(imgEditBtn, 'lc_edithyperlink.svg', app.map); + app.LOUtil.setImage(imgEditBtn, 'lc_edithyperlink.svg', app.map); imgEditBtn.setAttribute('width', 18); imgEditBtn.setAttribute('height', 18); imgEditBtn.style.padding = '4px'; @@ -78,7 +78,7 @@ class URLPopUpSection extends HTMLObjectSection { removeBtn.setAttribute('title', _('Remove link')); const imgRemoveBtn = L.DomUtil.create('img', 'hyperlink-pop-up-removeimg', removeBtn); - L.LOUtil.setImage(imgRemoveBtn, 'lc_removehyperlink.svg', app.map); + app.LOUtil.setImage(imgRemoveBtn, 'lc_removehyperlink.svg', app.map); imgRemoveBtn.setAttribute('width', 18); imgRemoveBtn.setAttribute('height', 18); imgRemoveBtn.style.padding = '4px'; diff --git a/browser/src/control/Control.AboutDialog.ts b/browser/src/control/Control.AboutDialog.ts index e72439db296cd..ac0e61fe9db9f 100644 --- a/browser/src/control/Control.AboutDialog.ts +++ b/browser/src/control/Control.AboutDialog.ts @@ -178,7 +178,7 @@ class AboutDialog { _('Copy all version information in English'), ); var img = L.DomUtil.create('img', null, null); - L.LOUtil.setImage(img, 'lc_copy.svg', this.map); + app.LOUtil.setImage(img, 'lc_copy.svg', this.map); copyversion.innerHTML = ''; copyversion.addEventListener( @@ -285,9 +285,9 @@ class AboutDialog { const copybutton = document.querySelector( '#modal-dialog-about-dialog-box-copybutton > img', ); - L.LOUtil.setImage(copybutton, 'lc_clipboard-check.svg', this.map); + app.LOUtil.setImage(copybutton, 'lc_clipboard-check.svg', this.map); setTimeout(() => { - L.LOUtil.setImage(copybutton, 'lc_copy.svg', this.map); + app.LOUtil.setImage(copybutton, 'lc_copy.svg', this.map); }, timeout); } diff --git a/browser/src/control/Control.Command.js b/browser/src/control/Control.Command.js index 49c350dafd5cb..986ca75eed01f 100644 --- a/browser/src/control/Control.Command.js +++ b/browser/src/control/Control.Command.js @@ -12,7 +12,7 @@ * Feature blocking handler */ -/* global $ _ */ +/* global $ _ app */ L.Map.include({ @@ -56,7 +56,7 @@ L.Map.include({ if (window.mode.isMobile()) { var overlay = L.DomUtil.create('div', 'locking-overlay', DOMParentElement); var lock = L.DomUtil.create('img', 'locking-overlay-lock', overlay); - L.LOUtil.setImage(lock, 'lc_lock.svg', this); + app.LOUtil.setImage(lock, 'lc_lock.svg', this); } $(DOMParentElement).click(function(event) { diff --git a/browser/src/control/Control.DownloadProgress.js b/browser/src/control/Control.DownloadProgress.js index a4553ceb80c4e..bb657bc585bde 100644 --- a/browser/src/control/Control.DownloadProgress.js +++ b/browser/src/control/Control.DownloadProgress.js @@ -57,7 +57,7 @@ L.Control.DownloadProgress = L.Control.extend({ var modalId = this._getDownloadProgressDialogId(); var msg = this._getLargeCopyPasteMessage(); - var buttonText = _('Download') + L.Util.replaceCtrlAltInMac(' (Ctrl + C)'); + var buttonText = _('Download') + app.util.replaceCtrlAltInMac(' (Ctrl + C)'); if (inSnackbar) { this._map.uiManager.showSnackbar( @@ -83,7 +83,7 @@ L.Control.DownloadProgress = L.Control.extend({ this._map.uiManager.showProgressBar(msg, buttonText, this._onClose.bind(this)); } else if (this._isLargeCopy) { // downloading for copy, next: show download complete dialog - buttonText = _('Copy') + L.Util.replaceCtrlAltInMac(' (Ctrl + C)'); + buttonText = _('Copy') + app.util.replaceCtrlAltInMac(' (Ctrl + C)'); this._map.uiManager.showProgressBarDialog(modalId, this._getDialogTitle(), msg, buttonText, this._onConfirmCopyAction.bind(this), 0, this._onClose.bind(this)); @@ -108,7 +108,7 @@ L.Control.DownloadProgress = L.Control.extend({ var modalId = this._getDownloadProgressDialogId(); var snackbarMsg = _('Download completed and ready to be copied to clipboard.'); var dialogMsg = snackbarMsg + ' ' + _('From now on clipboard notifications will discreetly appear at the bottom.'); - var buttonText = _('Copy') + L.Util.replaceCtrlAltInMac(' (Ctrl + C)'); + var buttonText = _('Copy') + app.util.replaceCtrlAltInMac(' (Ctrl + C)'); if (inSnackbar) { this._map.uiManager.setSnackbarProgress(100); diff --git a/browser/src/control/Control.IdleHandler.ts b/browser/src/control/Control.IdleHandler.ts index d90dc1fe9256a..b0e9aae429f7d 100644 --- a/browser/src/control/Control.IdleHandler.ts +++ b/browser/src/control/Control.IdleHandler.ts @@ -187,13 +187,13 @@ class IdleHandler { if (message === '') { document.getElementById(dialogId).style.display = 'none'; - L.LOUtil.onRemoveHTMLElement(document.getElementById(this.dimId), restartConnection); + app.LOUtil.onRemoveHTMLElement(document.getElementById(this.dimId), restartConnection); } else { var overlayId = dialogId + '-overlay'; var overlay = document.getElementById(overlayId); overlay.onmouseover = () => { restartConnection(); uiManager.closeModal(dialogId); }; - L.LOUtil.onRemoveHTMLElement(overlay, restartConnection); + app.LOUtil.onRemoveHTMLElement(overlay, restartConnection); } this._sendInactiveMessage(); diff --git a/browser/src/control/Control.JSDialogBuilder.js b/browser/src/control/Control.JSDialogBuilder.js index 98cdae8c2a1d7..803fb8b6027da 100644 --- a/browser/src/control/Control.JSDialogBuilder.js +++ b/browser/src/control/Control.JSDialogBuilder.js @@ -420,7 +420,7 @@ L.Control.JSDialogBuilder = L.Control.extend({ for (var i = 0; i < handlers.length; ++i) { var event = handlers[i].event; var handler = handlers[i].handler; - if (!L.isEmpty(event) && handler) { + if (!app.util.isEmpty(event) && handler) { if (event === 'click') { var eventData = { id: controlElement.id @@ -608,7 +608,7 @@ L.Control.JSDialogBuilder = L.Control.extend({ } if (iconURL) { var icon = L.DomUtil.create('img', 'menu-entry-icon', leftDiv); - L.LOUtil.setImage(icon, iconURL, builder.map); + app.LOUtil.setImage(icon, iconURL, builder.map); icon.alt = ''; titleClass = 'menu-entry-with-icon'; @@ -814,12 +814,12 @@ L.Control.JSDialogBuilder = L.Control.extend({ $(sectionTitle).css('justify-content', 'space-between'); var commandName = dataid; - if (commandName && commandName.length && L.LOUtil.existsIconForCommand(commandName, builder.map.getDocType())) { + if (commandName && commandName.length && app.LOUtil.existsIconForCommand(commandName, builder.map.getDocType())) { var iconName = builder._generateMenuIconName(commandName); var iconSpan = L.DomUtil.create('span', 'menu-entry-icon ' + iconName, sectionTitle); iconName = builder._createIconURL(iconName, true); icon = L.DomUtil.create('img', '', iconSpan); - L.LOUtil.setImage(icon, iconName, builder.map); + app.LOUtil.setImage(icon, iconName, builder.map); icon.alt = ''; var titleSpan2 = L.DomUtil.create('span', 'menu-entry-with-icon flex-fullwidth', sectionTitle); titleSpan2.innerHTML = title; @@ -1541,7 +1541,7 @@ L.Control.JSDialogBuilder = L.Control.extend({ } else if (data.symbol) { L.DomUtil.addClass(pushbutton, 'has-img d-flex align-content-center justify-content-center align-items-center'); image = L.DomUtil.create('img', '', pushbutton); - L.LOUtil.setImage(image, 'symbol_' + data.symbol + '.svg', builder.map); + app.LOUtil.setImage(image, 'symbol_' + data.symbol + '.svg', builder.map); } else { pushbutton.innerText = pushbuttonText; builder._stressAccessKey(pushbutton, pushbutton.accessKey); @@ -1712,13 +1712,13 @@ L.Control.JSDialogBuilder = L.Control.extend({ if (image) { image = image.substr(0, image.lastIndexOf('.')); image = image.substr(image.lastIndexOf('/') + 1); - image = 'url("' + L.LOUtil.getImageURL(image + '.svg') + '")'; + image = 'url("' + app.LOUtil.getImageURL(image + '.svg') + '")'; } if (image64) { image = 'url("' + image64 + '")'; } - L.LOUtil.checkIfImageExists(image); + app.LOUtil.checkIfImageExists(image); elem = L.DomUtil.create('div', 'layout ' + (data.entries[index].selected ? ' cool-context-down' : ''), parentContainer); $(elem).data('id', data.entries[index].id); @@ -1946,7 +1946,7 @@ L.Control.JSDialogBuilder = L.Control.extend({ L.DomUtil.addClass(parentContainer, 'content-has-no-comments'); var emptyCommentWizard = L.DomUtil.create('figure', 'empty-comment-wizard-container', parentContainer); var imgNode = L.DomUtil.create('img', 'empty-comment-wizard-img', emptyCommentWizard); - L.LOUtil.setImage(imgNode, 'lc_showannotations.svg', builder.map); + app.LOUtil.setImage(imgNode, 'lc_showannotations.svg', builder.map); imgNode.alt = data.text; var textNode = L.DomUtil.create('figcaption', 'empty-comment-wizard', emptyCommentWizard); @@ -2287,7 +2287,7 @@ L.Control.JSDialogBuilder = L.Control.extend({ else if (hasImage !== false){ if (data.icon) { buttonImage = L.DomUtil.create('img', '', button); - this._isStringCloseToURL(data.icon) ? buttonImage.src = data.icon : L.LOUtil.setImage(buttonImage, data.icon, builder.map); + this._isStringCloseToURL(data.icon) ? buttonImage.src = data.icon : app.LOUtil.setImage(buttonImage, data.icon, builder.map); } else if (data.image) { buttonImage = L.DomUtil.create('img', '', button); @@ -2295,7 +2295,7 @@ L.Control.JSDialogBuilder = L.Control.extend({ } else { buttonImage = L.DomUtil.create('img', '', button); - L.LOUtil.setImage(buttonImage, builder._createIconURL(data.command), builder.map); + app.LOUtil.setImage(buttonImage, builder._createIconURL(data.command), builder.map); } } else { buttonImage = false; @@ -2672,12 +2672,12 @@ L.Control.JSDialogBuilder = L.Control.extend({ var icon = null; var commandName = data.command && data.command.startsWith('.uno:') ? data.command.substring('.uno:'.length) : data.id; - if (commandName && commandName.length && L.LOUtil.existsIconForCommand(commandName, builder.map.getDocType())) { + if (commandName && commandName.length && app.LOUtil.existsIconForCommand(commandName, builder.map.getDocType())) { var iconName = builder._generateMenuIconName(commandName); var iconSpan = L.DomUtil.create('span', 'menu-entry-icon ' + iconName, menuEntry); iconName = builder._createIconURL(iconName, true); icon = L.DomUtil.create('img', '', iconSpan); - L.LOUtil.setImage(icon, iconName, builder.map); + app.LOUtil.setImage(icon, iconName, builder.map); icon.alt = ''; } if (data.checked && data.checked === true) { diff --git a/browser/src/control/Control.Layers.js b/browser/src/control/Control.Layers.js index 5b04da8829d62..270f4735d76b7 100644 --- a/browser/src/control/Control.Layers.js +++ b/browser/src/control/Control.Layers.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ /* * L.Control.Layers is a control to allow users to switch between different layers on the map. */ @@ -37,7 +38,7 @@ L.Control.Layers = L.Control.extend({ removeLayer: function (layer) { layer.off('add remove', this._onLayerChange, this); - delete this._layers[L.stamp(layer)]; + delete this._layers[app.util.stamp(layer)]; return this._update(); }, @@ -93,7 +94,7 @@ L.Control.Layers = L.Control.extend({ _addLayer: function (layer, name, overlay) { layer.on('add remove', this._onLayerChange, this); - var id = L.stamp(layer); + var id = app.util.stamp(layer); this._layers[id] = { layer: layer, @@ -139,7 +140,7 @@ L.Control.Layers = L.Control.extend({ this._update(); } - var overlay = this._layers[L.stamp(e.target)].overlay; + var overlay = this._layers[app.util.stamp(e.target)].overlay; var type = overlay ? (e.type === 'add' ? 'overlayadd' : 'overlayremove') : @@ -176,7 +177,7 @@ L.Control.Layers = L.Control.extend({ input = this._createRadioElement('leaflet-base-layers', checked); } - input.layerId = L.stamp(obj.layer); + input.layerId = app.util.stamp(obj.layer); L.DomEvent.on(input, 'click', this._onInputClick, this); diff --git a/browser/src/control/Control.Menubar.js b/browser/src/control/Control.Menubar.js index a068888458aa5..26ba20fe2e08d 100644 --- a/browser/src/control/Control.Menubar.js +++ b/browser/src/control/Control.Menubar.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ /* * Copyright the Collabora Online contributors. * @@ -53,7 +54,7 @@ L.Control.MenubarShortcuts = { shortcut = shortcut.replace('Ctrl', 'Krmilka').replace('Alt', 'izmenjalka').replace('Shift', 'dvigalka'); } - var newText = _(text).replace('~', '') + ' (' + L.Util.replaceCtrlAltInMac(shortcut) + ')'; + var newText = _(text).replace('~', '') + ' (' + app.util.replaceCtrlAltInMac(shortcut) + ')'; return newText; } @@ -2082,7 +2083,7 @@ L.Control.Menubar = L.Control.extend({ } else if (id === 'zoomreset') { app.dispatcher.dispatch('zoomreset'); } else if (id === 'fullscreen') { - L.toggleFullScreen(); + app.util.toggleFullScreen(); } else if (id === 'showruler') { app.dispatcher.dispatch('showruler'); } else if (id === 'togglea11ystate') { @@ -2529,7 +2530,7 @@ L.Control.Menubar = L.Control.extend({ }, _initializeMenu: function(menu) { - this._isFileODF = L.LOUtil.isFileODF(this._map); + this._isFileODF = app.LOUtil.isFileODF(this._map); var menuHtml = this._createMenu(menu); for (var i in menuHtml) { this._menubarCont.appendChild(menuHtml[i]); diff --git a/browser/src/control/Control.MobileWizardBuilder.js b/browser/src/control/Control.MobileWizardBuilder.js index 5d9f1ce1ec002..2b98b7943fc34 100644 --- a/browser/src/control/Control.MobileWizardBuilder.js +++ b/browser/src/control/Control.MobileWizardBuilder.js @@ -14,7 +14,7 @@ * variants for mobile/touch devices from the JSON description provided by the server. */ -/* global $ _UNO _ JSDialog */ +/* global $ _UNO _ JSDialog app */ L.Control.MobileWizardBuilder = L.Control.JSDialogBuilder.extend({ _customizeOptions: function() { @@ -77,10 +77,10 @@ L.Control.MobileWizardBuilder = L.Control.JSDialogBuilder.extend({ div.id = data.id; controls['container'] = div; var commandName = data.id && data.id.startsWith('.uno:') ? data.id.substring('.uno:'.length) : data.id; - if (commandName && commandName.length && L.LOUtil.existsIconForCommand(commandName, builder.map.getDocType())) { + if (commandName && commandName.length && app.LOUtil.existsIconForCommand(commandName, builder.map.getDocType())) { var image = L.DomUtil.create('img', 'spinfieldimage', div); var icon = (data.id === 'Transparency') ? builder._createIconURL('settransparency') : builder._createIconURL(data.id); - L.LOUtil.setImage(image, icon, builder.map); + app.LOUtil.setImage(image, icon, builder.map); icon.alt = ''; } diff --git a/browser/src/control/Control.MobileWizardWindow.js b/browser/src/control/Control.MobileWizardWindow.js index 4801422a36128..0204548326c35 100644 --- a/browser/src/control/Control.MobileWizardWindow.js +++ b/browser/src/control/Control.MobileWizardWindow.js @@ -618,13 +618,13 @@ L.Control.MobileWizardWindow = L.Control.extend({ }, _isSlidePropertyPanel: function(data) { - var backgroundPanel = L.LOUtil.findItemWithAttributeRecursive(data, 'id', 'SlideBackgroundPanel'); - var layoutPanel = L.LOUtil.findItemWithAttributeRecursive(data, 'id', 'SdLayoutsPanel'); + var backgroundPanel = app.LOUtil.findItemWithAttributeRecursive(data, 'id', 'SlideBackgroundPanel'); + var layoutPanel = app.LOUtil.findItemWithAttributeRecursive(data, 'id', 'SdLayoutsPanel'); return backgroundPanel && layoutPanel; }, _insertCalcBorders: function(deck) { - var replaceMe = L.LOUtil.findItemWithAttributeRecursive(deck, 'id', 'cellbordertype'); + var replaceMe = app.LOUtil.findItemWithAttributeRecursive(deck, 'id', 'cellbordertype'); if (replaceMe) { replaceMe.id = 'borderstyle'; replaceMe.type = 'borderstyle'; @@ -638,12 +638,12 @@ L.Control.MobileWizardWindow = L.Control.extend({ if (data.children && data.children.length && data.children[0].type !== 'deck') data.children.splice(0, 1); - var deck = L.LOUtil.findItemWithAttributeRecursive(data, 'type', 'deck'); + var deck = app.LOUtil.findItemWithAttributeRecursive(data, 'type', 'deck'); if (deck) { // merge styles into text-panel for elegance - var stylesIdx = L.LOUtil.findIndexInParentByAttribute(deck, 'id', 'StylesPropertyPanel'); - var textIdx = L.LOUtil.findIndexInParentByAttribute(deck, 'id', 'TextPropertyPanel'); + var stylesIdx = app.LOUtil.findIndexInParentByAttribute(deck, 'id', 'StylesPropertyPanel'); + var textIdx = app.LOUtil.findIndexInParentByAttribute(deck, 'id', 'TextPropertyPanel'); if (stylesIdx >= 0 && this.map.getDocType() === 'spreadsheet') { // remove rather useless calc styles panel diff --git a/browser/src/control/Control.NotebookbarCalc.js b/browser/src/control/Control.NotebookbarCalc.js index b22e1d83e2630..f736c406bae89 100644 --- a/browser/src/control/Control.NotebookbarCalc.js +++ b/browser/src/control/Control.NotebookbarCalc.js @@ -13,7 +13,7 @@ * L.Control.NotebookbarCalc - definition of notebookbar content in Calc */ -/* global _ _UNO */ +/* global _ _UNO app */ L.Control.NotebookbarCalc = L.Control.NotebookbarWriter.extend({ getTabs: function() { @@ -1527,7 +1527,7 @@ L.Control.NotebookbarCalc = L.Control.NotebookbarWriter.extend({ 'text': _UNO('.uno:FontworkGalleryFloater'), 'command': '.uno:FontworkGalleryFloater', // Fontwork export/import not supported in other formats. - 'visible': (L.LOUtil.isFileODF(this._map)) ? 'true' : 'false', + 'visible': (app.LOUtil.isFileODF(this._map)) ? 'true' : 'false', 'accessibility': { focusBack: true, combination: 'IF', de: null } } ] @@ -2426,7 +2426,7 @@ L.Control.NotebookbarCalc = L.Control.NotebookbarWriter.extend({ 'text': _UNO('.uno:FontworkGalleryFloater'), 'command': '.uno:FontworkGalleryFloater', // Fontwork export/import not supported in other formats. - 'visible': (L.LOUtil.isFileODF(this._map)) ? 'true' : 'false', + 'visible': (app.LOUtil.isFileODF(this._map)) ? 'true' : 'false', 'accessibility': { focusBack: true, combination: 'FW', de: null } } ] diff --git a/browser/src/control/Control.NotebookbarDraw.js b/browser/src/control/Control.NotebookbarDraw.js index 4b9deabe63f40..e4b87a7d85f4e 100644 --- a/browser/src/control/Control.NotebookbarDraw.js +++ b/browser/src/control/Control.NotebookbarDraw.js @@ -13,7 +13,7 @@ * L.Control.NotebookbarDraw - definition of notebookbar content in Draw */ -/* global _ _UNO */ +/* global _ _UNO app */ L.Control.NotebookbarDraw = L.Control.NotebookbarImpress.extend({ getShortcutsBarData: function() { @@ -648,7 +648,7 @@ L.Control.NotebookbarDraw = L.Control.NotebookbarImpress.extend({ 'text': _UNO('.uno:FontworkGalleryFloater'), 'command': '.uno:FontworkGalleryFloater', // Fontwork export/import not supported in other formats. - 'visible': L.LOUtil.isFileODF(this._map) ? 'true' : 'false', + 'visible': app.LOUtil.isFileODF(this._map) ? 'true' : 'false', 'accessibility': { focusBack: true, combination: 'FW', de: null } }, { @@ -1401,7 +1401,7 @@ L.Control.NotebookbarDraw = L.Control.NotebookbarImpress.extend({ 'text': _UNO('.uno:FontworkGalleryFloater'), 'command': '.uno:FontworkGalleryFloater', // Fontwork export/import not supported in other formats. - 'visible': L.LOUtil.isFileODF(this._map) ? 'true' : 'false', + 'visible': app.LOUtil.isFileODF(this._map) ? 'true' : 'false', 'accessibility': { focusBack: true, combination: 'FG', de: null } } ] diff --git a/browser/src/control/Control.NotebookbarImpress.js b/browser/src/control/Control.NotebookbarImpress.js index 3f25bb798c80d..6e9099dc03337 100644 --- a/browser/src/control/Control.NotebookbarImpress.js +++ b/browser/src/control/Control.NotebookbarImpress.js @@ -13,7 +13,7 @@ * L.Control.NotebookbarImpress - definition of notebookbar content in Impress */ -/* global _ _UNO */ +/* global _ _UNO app */ L.Control.NotebookbarImpress = L.Control.NotebookbarWriter.extend({ @@ -699,7 +699,7 @@ L.Control.NotebookbarImpress = L.Control.NotebookbarWriter.extend({ 'text': _UNO('.uno:FontworkGalleryFloater'), 'command': '.uno:FontworkGalleryFloater', // Fontwork export/import not supported in other formats. - 'visible': (L.LOUtil.isFileODF(this._map)) ? 'true' : 'false', + 'visible': (app.LOUtil.isFileODF(this._map)) ? 'true' : 'false', 'accessibility': { focusBack: true, combination: 'FL', de: null } }, { @@ -1392,7 +1392,7 @@ L.Control.NotebookbarImpress = L.Control.NotebookbarWriter.extend({ 'text': _UNO('.uno:FontworkGalleryFloater'), 'command': '.uno:FontworkGalleryFloater', // Fontwork export/import not supported in other formats. - 'visible': L.LOUtil.isFileODF(this._map) ? 'true' : 'false', + 'visible': app.LOUtil.isFileODF(this._map) ? 'true' : 'false', 'accessibility': { focusBack: true, combination: 'FW', de: null } } ] @@ -2455,7 +2455,7 @@ L.Control.NotebookbarImpress = L.Control.NotebookbarWriter.extend({ 'text': _UNO('.uno:FontworkGalleryFloater'), 'command': '.uno:FontworkGalleryFloater', // Fontwork export/import not supported in other formats. - 'visible': (L.LOUtil.isFileODF(this._map)) ? 'true' : 'false', + 'visible': (app.LOUtil.isFileODF(this._map)) ? 'true' : 'false', 'accessibility': { focusBack: true, combination: 'FW', de: null } } ] diff --git a/browser/src/control/Control.NotebookbarWriter.js b/browser/src/control/Control.NotebookbarWriter.js index ea43e86e441e7..a7caa2706d7fe 100644 --- a/browser/src/control/Control.NotebookbarWriter.js +++ b/browser/src/control/Control.NotebookbarWriter.js @@ -13,7 +13,7 @@ * L.Control.NotebookbarWriter - definition of notebookbar content in Writer */ -/* global _ _UNO */ +/* global _ _UNO app */ var fileTabName = 'File'; var homeTabName = 'Home'; @@ -1078,7 +1078,7 @@ L.Control.NotebookbarWriter = L.Control.Notebookbar.extend({ }, getInsertTab: function() { - var isODF = L.LOUtil.isFileODF(this._map); + var isODF = app.LOUtil.isFileODF(this._map); var content = [ { 'id': 'insert-insert-page-break', @@ -2675,7 +2675,7 @@ L.Control.NotebookbarWriter = L.Control.Notebookbar.extend({ }, getDrawTab: function() { - var isODF = L.LOUtil.isFileODF(this._map); + var isODF = app.LOUtil.isFileODF(this._map); var content = [ { 'type': 'bigtoolitem', diff --git a/browser/src/control/Control.Tooltip.js b/browser/src/control/Control.Tooltip.js index bc756510d9bab..f6558dc2b2e58 100644 --- a/browser/src/control/Control.Tooltip.js +++ b/browser/src/control/Control.Tooltip.js @@ -13,7 +13,7 @@ * Class Tooltip - tooltip manager */ -/* global */ +/* global app */ class Tooltip { constructor(options) { @@ -135,7 +135,7 @@ class Tooltip { do { rectTooltip = this.position(rectElem, rectCont, index++); - } while (index < 8 && !L.LOUtil.containsDOMRect(rectView, rectTooltip)); + } while (index < 8 && !app.LOUtil.containsDOMRect(rectView, rectTooltip)); // containsDOMRect() checks if the tooltip box(rectTooltip) is inside the boundaries of the window(rectView) this._container.style.left = rectTooltip.left + 'px'; diff --git a/browser/src/control/Control.UserList.ts b/browser/src/control/Control.UserList.ts index f5daf461de1d7..53b89dc421171 100644 --- a/browser/src/control/Control.UserList.ts +++ b/browser/src/control/Control.UserList.ts @@ -11,6 +11,7 @@ /* * L.Control.UserList */ +/* global app */ interface UserExtraInfo { avatar: string; @@ -163,7 +164,7 @@ class UserList extends L.Control { img = L.DomUtil.create('img', 'avatar-img') as HTMLImageElement; } - L.LOUtil.setUserImage(img, this.map, viewId); + app.LOUtil.setUserImage(img, this.map, viewId); img.alt = this.options.userAvatarAlt.replace('{user}', username); @@ -387,7 +388,7 @@ class UserList extends L.Control { you = true; } else { username = e.username; - color = L.LOUtil.rgbToHex(this.map.getViewColor(e.viewId)); + color = app.LOUtil.rgbToHex(this.map.getViewColor(e.viewId)); you = false; } diff --git a/browser/src/control/Control.Zotero.js b/browser/src/control/Control.Zotero.js index 41f1e4005970e..805e7c1aacbf7 100644 --- a/browser/src/control/Control.Zotero.js +++ b/browser/src/control/Control.Zotero.js @@ -84,7 +84,7 @@ L.Control.Zotero = L.Control.extend({ } var that = this; this.citationCluster[values.citationID] = []; - var citationString = L.Util.trim(values.properties.plainCitation, this.settings.layout.prefix, this.settings.layout.suffix); + var citationString = app.util.trim(values.properties.plainCitation, this.settings.layout.prefix, this.settings.layout.suffix); var citations = citationString.split(this.settings.layout.delimiter); var itemUriList = []; values.citationItems.forEach(function(item, i) { @@ -93,7 +93,7 @@ L.Control.Zotero = L.Control.extend({ var itemUri = item.uris[0]; var citationId = that.extractItemKeyFromLink(itemUri); that.citationCluster[values.citationID].push(citationId); - that.citations[citationId] = L.Util.trim(citations[i], that.settings.group.prefix, that.settings.group.suffix); + that.citations[citationId] = app.util.trim(citations[i], that.settings.group.prefix, that.settings.group.suffix); that.setCitationNumber(that.citations[citationId]); itemUriList.push(itemUri); }); @@ -520,7 +520,7 @@ L.Control.Zotero = L.Control.extend({ this.settings.citationNumber = 1; this.citations[citationId] = this.settings.citationNumber++; } else { - this.citations[citationId] = L.Util.trim(text, this.settings.layout.prefix, this.settings.layout.suffix); + this.citations[citationId] = app.util.trim(text, this.settings.layout.prefix, this.settings.layout.suffix); } return this.settings.group.prefix + this.citations[citationId] + this.settings.group.suffix; @@ -546,7 +546,7 @@ L.Control.Zotero = L.Control.extend({ }); }); - citationString = this.settings.layout.prefix + L.Util.trimEnd(citationString, this.settings.layout.delimiter) + this.settings.layout.suffix; + citationString = this.settings.layout.prefix + app.util.trimEnd(citationString, this.settings.layout.delimiter) + this.settings.layout.suffix; // last-child works here only because its a single chain of nodes var innerText = citationNode.querySelector('*:last-child'); if (!innerText) @@ -574,7 +574,7 @@ L.Control.Zotero = L.Control.extend({ getCitationJSONString: function(items) { var resultJSON = {}; - resultJSON['citationID'] = L.Util.randomString(10); + resultJSON['citationID'] = app.util.randomString(10); var citationNode = this.handleCitationText(items); @@ -916,7 +916,7 @@ L.Control.Zotero = L.Control.extend({ dataNode.setAttribute('data-version', '3'); var sessionNode = xmlDoc.createElement('session'); - sessionNode.setAttribute('id', L.Util.randomString(8)); + sessionNode.setAttribute('id', app.util.randomString(8)); dataNode.appendChild(sessionNode); @@ -1610,10 +1610,10 @@ L.Control.Zotero = L.Control.extend({ field['FieldResult'] = {type: 'string', value: citationString}; } else if (this.getFieldType() === 'ReferenceMark') { field['TypeName'] = {type: 'string', value: 'SetRef'}; - field['Name'] = {type: 'string', value: 'ZOTERO_ITEM CSL_CITATION ' + cslJSON + ' RND' + L.Util.randomString(10)}; + field['Name'] = {type: 'string', value: 'ZOTERO_ITEM CSL_CITATION ' + cslJSON + ' RND' + app.util.randomString(10)}; field['Content'] = {type: 'string', value: citationString}; } else if (this.getFieldType() == 'Bookmark') { - field['Bookmark'] = {type: 'string', value: 'ZOTERO_BREF_' + L.Util.randomString(12)}; + field['Bookmark'] = {type: 'string', value: 'ZOTERO_BREF_' + app.util.randomString(12)}; field['BookmarkText'] = {type: 'string', value: citationString}; } @@ -1689,7 +1689,7 @@ L.Control.Zotero = L.Control.extend({ 'value': { 'Bookmark': { 'type': 'string', - 'value': 'ZOTERO_BREF_' + L.Util.randomString(12) + 'value': 'ZOTERO_BREF_' + app.util.randomString(12) }, 'BookmarkText': { 'type': 'string', @@ -1710,10 +1710,10 @@ L.Control.Zotero = L.Control.extend({ field['FieldCommand'] = {type: 'string', value: 'ADDIN ZOTERO_BIBL ' + JSON.stringify(this.settings.bib) + ' CSL_BIBLIOGRAPHY'}; field['FieldResult'] = {type: 'string', value: html}; } else if (this.getFieldType() == 'Bookmark') { - field['Bookmark'] = {type: 'string', value: 'ZOTERO_BREF_' + L.Util.randomString(12)}; + field['Bookmark'] = {type: 'string', value: 'ZOTERO_BREF_' + app.util.randomString(12)}; field['BookmarkText'] = {type: 'string', value: html}; } else { - field['RegionName'] = {type: 'string', value: 'ZOTERO_BIBL ' + JSON.stringify(this.settings.bib) + ' CSL_BIBLIOGRAPHY ' + ' RND' + L.Util.randomString(10)}; + field['RegionName'] = {type: 'string', value: 'ZOTERO_BIBL ' + JSON.stringify(this.settings.bib) + ' CSL_BIBLIOGRAPHY ' + ' RND' + app.util.randomString(10)}; field['Content'] = {type: 'string', value: html}; } diff --git a/browser/src/control/Toolbar.js b/browser/src/control/Toolbar.js index b28521c2281fc..cfe8a630e2e2f 100644 --- a/browser/src/control/Toolbar.js +++ b/browser/src/control/Toolbar.js @@ -566,10 +566,10 @@ L.Map.include({ for (i = 0, max = productNameContent.length; i < max; i++) { productNameContent[i].innerHTML = productNameContent[i].innerHTML.replace('{productname}', productName); } - document.getElementById('online-help-content').innerHTML = L.Util.replaceCtrlAltInMac(document.getElementById('online-help-content').innerHTML); + document.getElementById('online-help-content').innerHTML = app.util.replaceCtrlAltInMac(document.getElementById('online-help-content').innerHTML); } if (id === 'keyboard-shortcuts-content') { - document.getElementById('keyboard-shortcuts-content').innerHTML = L.Util.replaceCtrlAltInMac(document.getElementById('keyboard-shortcuts-content').innerHTML); + document.getElementById('keyboard-shortcuts-content').innerHTML = app.util.replaceCtrlAltInMac(document.getElementById('keyboard-shortcuts-content').innerHTML); } var searchInput = document.getElementById('online-help-search-input'); searchInput.setAttribute('placeholder',_('Search')); diff --git a/browser/src/control/jsdialog/Widget.Combobox.js b/browser/src/control/jsdialog/Widget.Combobox.js index 14fbe9125ff06..441b0a698af57 100644 --- a/browser/src/control/jsdialog/Widget.Combobox.js +++ b/browser/src/control/jsdialog/Widget.Combobox.js @@ -24,7 +24,7 @@ * customEntryRenderer - specifies if entries have custom content which is rendered by the core */ -/* global JSDialog $ */ +/* global JSDialog app $ */ JSDialog.comboboxEntry = function (parentContainer, data, builder) { var entry = L.DomUtil.create('div', 'ui-combobox-entry ' + builder.options.cssClass, parentContainer); @@ -40,7 +40,7 @@ JSDialog.comboboxEntry = function (parentContainer, data, builder) { if (data.icon) { var icon = L.DomUtil.create('img', 'ui-combobox-icon', entry); - builder._isStringCloseToURL(data.icon) ? icon.src = data.icon : L.LOUtil.setImage(icon, builder._createIconURL(data.icon), builder.map); + builder._isStringCloseToURL(data.icon) ? icon.src = data.icon : app.LOUtil.setImage(icon, builder._createIconURL(data.icon), builder.map); } if (data.hint) { diff --git a/browser/src/control/jsdialog/Widget.MobileBorderSelector.js b/browser/src/control/jsdialog/Widget.MobileBorderSelector.js index f4c1f42059985..f555244a94ed2 100644 --- a/browser/src/control/jsdialog/Widget.MobileBorderSelector.js +++ b/browser/src/control/jsdialog/Widget.MobileBorderSelector.js @@ -19,7 +19,7 @@ * } */ -/* global _ JSDialog $ */ +/* global _ JSDialog $ app */ function _getCurrentBorderNumber(builder) { var outer = builder.map['stateChangeHandler'].getItemValue('.uno:BorderOuter'); @@ -69,7 +69,7 @@ function _borderControlItem(parentContainer, data, builder, i, selected) { var buttonId = 'border-' + i; button = L.DomUtil.create('img', 'ui-content borderbutton', div); - L.LOUtil.setImage(button, 'fr0' + i + '.svg', builder.map); + app.LOUtil.setImage(button, 'fr0' + i + '.svg', builder.map); button.id = buttonId; if (selected) $(button).addClass('selected'); @@ -77,7 +77,7 @@ function _borderControlItem(parentContainer, data, builder, i, selected) { $(div).click(function () { var color = 0; // Find our associated color picker - var item = L.LOUtil.findItemWithAttributeRecursive(data.parent, 'command', '.uno:FrameLineColor'); + var item = app.LOUtil.findItemWithAttributeRecursive(data.parent, 'command', '.uno:FrameLineColor'); if (item) color = JSDialog.getCurrentColor(item, builder); window.setBorderStyle(i, color); diff --git a/browser/src/control/jsdialog/Widget.TreeView.ts b/browser/src/control/jsdialog/Widget.TreeView.ts index befd741724d5d..2a93fa4611ead 100644 --- a/browser/src/control/jsdialog/Widget.TreeView.ts +++ b/browser/src/control/jsdialog/Widget.TreeView.ts @@ -59,6 +59,7 @@ */ declare var JSDialog: any; +declare var app: any; // TODO: remove this hack var lastClickHelperRow: string | number = -1; @@ -471,7 +472,7 @@ class TreeViewControl { const iconId = this.getCellIconId(entry.columns[index]); L.DomUtil.addClass(icon, iconId + 'img'); const iconName = builder._createIconURL(iconId, true); - L.LOUtil.setImage(icon, iconName, builder.map); + app.LOUtil.setImage(icon, iconName, builder.map); icon.tabIndex = -1; icon.alt = ''; //In this case, it is advisable to use an empty alt tag for the icons, as the information of the function is available in text form } diff --git a/browser/src/core/Events.js b/browser/src/core/Events.js index 9a670c9d9a759..c30962843a2f2 100644 --- a/browser/src/core/Events.js +++ b/browser/src/core/Events.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ /* * L.Evented is a base class that Leaflet classes inherit from to handle custom events. */ @@ -17,7 +18,7 @@ L.Evented = L.Class.extend({ } else { // types can be a string of space-separated words - types = L.Util.splitWords(types); + types = app.util.splitWords(types); for (var i = 0, len = types.length; i < len; i++) { this._on(types[i], fn, context); @@ -39,7 +40,7 @@ L.Evented = L.Class.extend({ } } else { - types = L.Util.splitWords(types); + types = app.util.splitWords(types); for (var i = 0, len = types.length; i < len; i++) { this._off(types[i], fn, context); @@ -53,7 +54,7 @@ L.Evented = L.Class.extend({ _on: function (type, fn, context) { var events = this._events = this._events || {}, - contextId = context && context !== this && L.stamp(context); + contextId = context && context !== this && app.util.stamp(context); if (contextId) { // store listeners with custom context in a separate hash (if it has an id); @@ -62,7 +63,7 @@ L.Evented = L.Class.extend({ var indexKey = type + '_idx', indexLenKey = type + '_len', typeIndex = events[indexKey] = events[indexKey] || {}, - id = L.stamp(fn) + '_' + contextId; + id = app.util.stamp(fn) + '_' + contextId; if (!typeIndex[id]) { typeIndex[id] = {fn: fn, ctx: context}; @@ -95,11 +96,11 @@ L.Evented = L.Class.extend({ return; } - var contextId = context && context !== this && L.stamp(context), + var contextId = context && context !== this && app.util.stamp(context), listeners, i, len, listener, id; if (contextId) { - id = L.stamp(fn) + '_' + contextId; + id = app.util.stamp(fn) + '_' + contextId; listeners = events[indexKey]; if (listeners && listeners[id]) { @@ -124,7 +125,7 @@ L.Evented = L.Class.extend({ // set the removed listener to noop so that's not called if remove happens in fire if (listener) { - listener.fn = L.Util.falseFn; + listener.fn = app.util.falseFn; } }, @@ -199,13 +200,13 @@ L.Evented = L.Class.extend({ // adds a parent to propagate events to (when you fire with true as a 3rd argument) addEventParent: function (obj) { this._eventParents = this._eventParents || {}; - this._eventParents[L.stamp(obj)] = obj; + this._eventParents[app.util.stamp(obj)] = obj; return this; }, removeEventParent: function (obj) { if (this._eventParents) { - delete this._eventParents[L.stamp(obj)]; + delete this._eventParents[app.util.stamp(obj)]; } return this; }, diff --git a/browser/src/core/LOUtil.js b/browser/src/core/LOUtil.js deleted file mode 100644 index 4eca63b765586..0000000000000 --- a/browser/src/core/LOUtil.js +++ /dev/null @@ -1,328 +0,0 @@ -/* -*- js-indent-level: 8 -*- */ -/* - * L.LOUtil contains various LO related utility functions used throughout the code - */ - -L.LOUtil = { - // Based on core.git's colordata.hxx: COL_AUTHOR1_DARK...COL_AUTHOR9_DARK - // consisting of arrays of RGB values - // Maybe move the color logic to separate file when it becomes complex - darkColors: [ - [198, 146, 0], - [6, 70, 162], - [87, 157, 28], - [105, 43, 157], - [197, 0, 11], - [0, 128, 128], - [140, 132, 0], - [53, 85, 107], - [209, 118, 0] - ], - - // https://stackoverflow.com/a/32726412 - onRemoveHTMLElement: function(element, onDetachCallback) { - var observer = new MutationObserver(function () { - function isDetached(el) { - return !el.closest('html'); - } - - if (isDetached(element)) { - onDetachCallback(); - observer.disconnect(); - } - }); - - observer.observe(document, { - childList: true, - subtree: true - }); - }, - - startSpinner: function (spinnerCanvas, spinnerSpeed) { - var spinnerInterval; - spinnerCanvas.width = 50; - spinnerCanvas.height = 50; - - var context = spinnerCanvas.getContext('2d'); - context.lineWidth = 8; - context.strokeStyle = 'grey'; - var x = spinnerCanvas.width / 2; - var y = spinnerCanvas.height / 2; - var radius = y - context.lineWidth / 2; - spinnerInterval = setInterval(function() { - context.clearRect(0, 0, x * 2, y * 2); - // Move to center - context.translate(x, y); - context.rotate(spinnerSpeed * Math.PI / 180); - context.translate(-x, -y); - context.beginPath(); - context.arc(x, y, radius, 0, Math.PI * 1.3); - context.stroke(); - }, 30); - - return spinnerInterval; - }, - - getViewIdColor: function(viewId) { - var color = this.darkColors[(viewId + 1) % this.darkColors.length]; - return (color[2] | (color[1] << 8) | (color[0] << 16)); - }, - - rgbToHex: function(color) { - return '#' + ('000000' + color.toString(16)).slice(-6); - }, - - stringToBounds: function(bounds) { - var numbers = bounds.match(/\d+/g); - var topLeft = L.point(parseInt(numbers[0]), parseInt(numbers[1])); - var bottomRight = topLeft.add(L.point(parseInt(numbers[2]), parseInt(numbers[3]))); - return L.bounds(topLeft, bottomRight); - }, - - stringToRectangles: function(strRect) { - var matches = strRect.match(/\d+/g); - var rectangles = []; - if (matches !== null) { - for (var itMatch = 0; itMatch < matches.length; itMatch += 4) { - var topLeft = L.point(parseInt(matches[itMatch]), parseInt(matches[itMatch + 1])); - var size = L.point(parseInt(matches[itMatch + 2]), parseInt(matches[itMatch + 3])); - var topRight = topLeft.add(L.point(size.x, 0)); - var bottomLeft = topLeft.add(L.point(0, size.y)); - var bottomRight = topLeft.add(size); - rectangles.push([bottomLeft, bottomRight, topLeft, topRight]); - } - } - return rectangles; - }, - - // Some items will only present in dark mode so we will not check errors for those in other mode - onlydarkModeItems : ['invertbackground'], - - // Common images used in all modes, so the default one will be used. - commonItems: ['serverauditok', 'serverauditerror'], - - // Helper function to strip '.svg' suffix and 'lc_' prefix - stripName: function(name) { - // Remove the '.svg' suffix - var strippedName = name.replace(/\.svg$/, ''); - - // Remove the 'lc_' prefix if it exists - if (strippedName.startsWith('lc_')) { - strippedName = strippedName.substring(3); - } - - return strippedName; - }, - - isDarkModeItem: function(name) { - var strippedName = this.stripName(name); - - // Check if the stripped name is in the onlydarkModeItems array - return this.onlydarkModeItems.includes(strippedName); - }, - - isCommonForAllMode: function(name) { - var strippedName = this.stripName(name); - - // Check if the stripped name is in the commonItems array - return this.commonItems.includes(strippedName); - }, - - /// unwind things to get a good absolute URL - getURL: function(path) { - if (path === '') - return ''; - if (window.host === '' && window.serviceRoot === '') - return path; // mobile app - - var url = window.makeHttpUrl('/browser/' + window.versionPath); - if (path.substr(0,1) !== '/') - url += '/'; - url += path; - return url; - }, - setImage: function(img, name, map) { - var setupIcon = function () { - img.src = this.getImageURL(name); - this.checkIfImageExists(img); - }.bind(this); - setupIcon(); - - map.on('themechanged', setupIcon, this); - }, - setUserImage: function(img, map, viewId) { - // set avatar image if it exist in user extract info - var defaultImage = L.LOUtil.getImageURL('user.svg'); - var viewInfo = map._viewInfo[viewId]; - if ( - viewInfo !== undefined - && viewInfo.userextrainfo !== undefined - && viewInfo.userextrainfo.avatar !== undefined - ) { - // set user avatar - img.src = viewInfo.userextrainfo.avatar; - // Track if error event is already bound to this image - img.addEventListener('error', function () { - img.src = defaultImage; - this.checkIfImageExists(img, true); - }.bind(this), {once:true}); - return; - } - img.src = defaultImage; - this.checkIfImageExists(img, true); - }, - - getImageURL: function(imgName) { - var defaultImageURL = this.getURL('images/' + imgName); - - // Check if the image name is in the commonItems list and return the normal image path - if (this.isCommonForAllMode(imgName)) { - return defaultImageURL; - } - - if (window.prefs.getBoolean('darkTheme')) { - return this.getURL('images/dark/' + imgName); - } - - var dummyEmptyImg = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='; - defaultImageURL = this.isDarkModeItem(imgName) ? dummyEmptyImg : defaultImageURL; - return defaultImageURL; - }, - - checkIfImageExists: function (imageElement, imageIsLayoutCritical) { - imageElement.addEventListener('error', function (e) { - if (e.loUtilProcessed) { - return; - } - - if (imageElement.src && imageElement.src.includes('/images/branding/dark/')) { - imageElement.src = imageElement.src.replace('/images/branding/dark/', '/images/dark/'); - e.loUtilProcessed = true; - return; - } - if (imageElement.src && (imageElement.src.includes('/images/dark/') || imageElement.src.includes('/images/branding/'))) { - imageElement.src = imageElement.src.replace('/images/dark/', '/images/'); - imageElement.src = imageElement.src.replace('/images/branding/', '/images/'); - e.loUtilProcessed = true; - return; - } - - if (imageIsLayoutCritical) { - imageElement.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='; - // We cannot set visibility: hidden because that would hide other attributes of the image, e.g. its border - e.loUtilProcessed = true; - return; - } - - imageElement.style.display = 'none'; - e.loUtilProcessed = true; - }); - }, - /// oldFileName = Example.odt, suffix = new - /// returns: Example_new.odt - generateNewFileName: function(oldFileName, suffix) { - var idx = oldFileName.lastIndexOf('.'); - return oldFileName.substring(0, idx) + suffix + oldFileName.substring(idx); - }, - - commandWithoutIcon: [ - 'InsertPageHeader', - 'InsertPageFooter', - 'FLD_COL_NUMBER', - 'MTR_FLD_COL_SPACING', - 'rows', - 'cols', - 'None' - ], - - existsIconForCommand: function(command, docType) { - var commandName = command.startsWith('.uno:') ? command.substring('.uno:'.length) : command; - var res = !this.commandWithoutIcon.find(function (el) { - return el.startsWith(commandName); - }); - if (commandName.indexOf('?')!== -1) { - if (commandName.indexOf('SpellCheckIgnore') !== -1 || commandName.indexOf('SpellCheckIgnoreAll') !== -1) - return true; - - if ((docType === 'spreadsheet' || docType === 'presentation') && - commandName.indexOf('LanguageStatus') !== -1) - return true; - - if (commandName === 'LanguageStatus?Language:string=Current_LANGUAGE_NONE' || - commandName === 'LanguageStatus?Language:string=Current_RESET_LANGUAGES' || - commandName === 'LanguageStatus?Language:string=Paragraph_LANGUAGE_NONE' || - commandName === 'LanguageStatus?Language:string=Paragraph_RESET_LANGUAGES') - return true; - - return false; - } - return res; - }, - - /// Searching in JSON trees for data with a given field - findItemWithAttributeRecursive: function(node, idName, idValue) { - var found = null; - if (node[idName] === idValue) - return node; - if (node.children) - { - for (var i = 0; !found && i < node.children.length; i++) - found = L.LOUtil.findItemWithAttributeRecursive(node.children[i], idName, idValue); - } - return found; - }, - - /// Searching in JSON trees for an identifier and return the index in parent - findIndexInParentByAttribute: function(node, idName, idValue) { - if (node.children) - { - for (var i = 0; i < node.children.length; i++) - if (node.children[i][idName] === idValue) - return i; - } - return -1; - }, - - _doRectanglesIntersect: function (rectangle1, rectangle2) { // Format: (x, y, w, h). - // Don't use equality in comparison, that's not an intersection. - if (Math.abs((rectangle1[0] + rectangle1[2] * 0.5) - (rectangle2[0] + rectangle2[2] * 0.5)) < rectangle1[2] + rectangle2[2]) { - if (Math.abs((rectangle1[1] + rectangle1[3] * 0.5) - (rectangle2[1] + rectangle2[3] * 0.5)) < rectangle1[3] + rectangle2[3]) - return true; - else - return false; - } - else - return false; - }, - - // Returns the intersecting area of 2 rectangles. Rectangle format: (x, y, w, h). Return format is the same or null. - _getIntersectionRectangle: function (rectangle1, rectangle2) { - if (this._doRectanglesIntersect(rectangle1, rectangle2)) { - var x = (rectangle1[0] > rectangle2[0] ? rectangle1[0]: rectangle2[0]); - var y = (rectangle1[1] > rectangle2[1] ? rectangle1[1]: rectangle2[1]); - var w = (rectangle1[0] + rectangle1[2] < rectangle2[0] + rectangle2[2] ? rectangle1[0] + rectangle1[2] - x: rectangle2[0] + rectangle2[2] - x); - var h = (rectangle1[1] + rectangle1[3] < rectangle2[1] + rectangle2[3] ? rectangle1[1] + rectangle1[3] - y: rectangle2[1] + rectangle2[3] - y); - - return [x, y, w, h]; - } - else - return null; - }, - - getFileExtension: function (map) { - var filename = map['wopi'].BaseFileName; - return filename.substring(filename.lastIndexOf('.') + 1); - }, - - isFileODF: function (map) { - var ext = this.getFileExtension(map); - return ext === 'odt' || ext === 'ods' || ext === 'odp' || ext == 'odg'; - }, - - containsDOMRect: function (viewRect, rect) { - return (rect.top >= viewRect.top && - rect.right <= viewRect.right && - rect.bottom <= viewRect.bottom && - rect.left >= viewRect.left) - } -}; diff --git a/browser/src/core/Matrix.js b/browser/src/core/Matrix.js deleted file mode 100644 index bd1612a285a1e..0000000000000 --- a/browser/src/core/Matrix.js +++ /dev/null @@ -1,206 +0,0 @@ -/* -*- js-indent-level: 8 -*- */ - -/** - * @class L.Matrix - * - * @param {Number} a - * @param {Number} b - * @param {Number} c - * @param {Number} d - * @param {Number} e - * @param {Number} f - */ -L.Matrix = function(a, b, c, d, e, f) { - - /** - * @type {Array.} - */ - this._matrix = [a, b, c, d, e, f]; -}; - - -L.Matrix.prototype = { - - - /** - * @param {L.Point} point - * @return {L.Point} - */ - transform: function(point) { - return this._transform(point.clone()); - }, - - - /** - * Destructive - * - * [ x ] = [ a b tx ] [ x ] = [ a * x + b * y + tx ] - * [ y ] = [ c d ty ] [ y ] = [ c * x + d * y + ty ] - * - * @param {L.Point} point - * @return {L.Point} - */ - _transform: function(point) { - var matrix = this._matrix; - var x = point.x, y = point.y; - point.x = matrix[0] * x + matrix[1] * y + matrix[4]; - point.y = matrix[2] * x + matrix[3] * y + matrix[5]; - return point; - }, - - - /** - * @param {L.Point} point - * @return {L.Point} - */ - untransform: function (point) { - var matrix = this._matrix; - return new L.Point( - (point.x / matrix[0] - matrix[4]) / matrix[0], - (point.y / matrix[2] - matrix[5]) / matrix[2] - ); - }, - - - /** - * @return {L.Matrix} - */ - clone: function() { - var matrix = this._matrix; - return new L.Matrix( - matrix[0], matrix[1], matrix[2], - matrix[3], matrix[4], matrix[5] - ); - }, - - - /** - * @param {L.Point=|Number=} translate - * @return {L.Matrix|L.Point} - */ - translate: function(translate) { - if (translate === undefined) { - return new L.Point(this._matrix[4], this._matrix[5]); - } - - var translateX, translateY; - if (typeof translate === 'number') { - translateX = translateY = translate; - } else { - translateX = translate.x; - translateY = translate.y; - } - - return this._add(1, 0, 0, 1, translateX, translateY); - }, - - - /** - * @param {L.Point=|Number=} scale - * @return {L.Matrix|L.Point} - */ - scale: function(scale, origin) { - if (scale === undefined) { - return new L.Point(this._matrix[0], this._matrix[3]); - } - - var scaleX, scaleY; - origin = origin || L.point(0, 0); - if (typeof scale === 'number') { - scaleX = scaleY = scale; - } else { - scaleX = scale.x; - scaleY = scale.y; - } - - return this - ._add(scaleX, 0, 0, scaleY, origin.x, origin.y) - ._add(1, 0, 0, 1, -origin.x, -origin.y); - }, - - - /** - * m00 m01 x - m00 * x - m01 * y - * m10 m11 y - m10 * x - m11 * y - * @param {Number} angle - * @param {L.Point=} origin - * @return {L.Matrix} - */ - rotate: function(angle, origin) { - var cos = Math.cos(angle); - var sin = Math.sin(angle); - - origin = origin || new L.Point(0, 0); - - return this - ._add(cos, sin, -sin, cos, origin.x, origin.y) - ._add(1, 0, 0, 1, -origin.x, -origin.y); - }, - - - /** - * Invert rotation - * @return {L.Matrix} - */ - flip: function() { - this._matrix[1] *= -1; - this._matrix[2] *= -1; - return this; - }, - - - /** - * @param {Number|L.Matrix} a - * @param {Number} b - * @param {Number} c - * @param {Number} d - * @param {Number} e - * @param {Number} f - */ - _add: function(a, b, c, d, e, f) { - var result = [[], [], []]; - var src = this._matrix; - var m = [ - [src[0], src[2], src[4]], - [src[1], src[3], src[5]], - [ 0, 0, 1] - ]; - var other = [ - [a, c, e], - [b, d, f], - [0, 0, 1] - ], val; - - - if (a && a instanceof L.Matrix) { - src = a._matrix; - other = [ - [src[0], src[2], src[4]], - [src[1], src[3], src[5]], - [ 0, 0, 1]]; - } - - for (var i = 0; i < 3; i++) { - for (var j = 0; j < 3; j++) { - val = 0; - for (var k = 0; k < 3; k++) { - val += m[i][k] * other[k][j]; - } - result[i][j] = val; - } - } - - this._matrix = [ - result[0][0], result[1][0], result[0][1], - result[1][1], result[0][2], result[1][2] - ]; - return this; - } - - -}; - - -L.matrix = function(a, b, c, d, e, f) { - return new L.Matrix(a, b, c, d, e, f); -}; diff --git a/browser/src/core/Rectangle.ts b/browser/src/core/Rectangle.ts deleted file mode 100644 index aeb5a7298d45f..0000000000000 --- a/browser/src/core/Rectangle.ts +++ /dev/null @@ -1,265 +0,0 @@ -/* -*- js-indent-level: 8 -*- */ -/* - * Copyright the Collabora Online contributors. - * - * SPDX-License-Identifier: MPL-2.0 - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -declare var L: any; - -namespace cool { - -/** - * Represents a rectangle object which works with core pixels. - * x1 and y1 should always <= x2 and y2. In other words width >= 0 && height >= 0 is a precondition. - * This class doesn't check for above conditions. There is a isValid function for use when needed. - */ -export class Rectangle { - private x1: number; - private y1: number; - private width: number; - private height: number; - - constructor (x: number, y: number, width: number, height: number) { - this.x1 = x; - this.y1 = y; - this.width = width; - this.height = height; - } - - // convenience private getters - - private get x2(): number { - return this.x1 + this.width; - } - - private get y2(): number { - return this.y1 + this.height; - } - - private get area(): number { - return this.width * this.height; - } - - // Rounded coordinates private getters - - private get rx1(): number { - return Math.round(this.x1); - } - - private get ry1(): number { - return Math.round(this.y1); - } - - private get rx2(): number { - return Math.round(this.x2); - } - - private get ry2(): number { - return Math.round(this.y2); - } - - private get rwidth(): number { - return this.rx2 - this.rx1; - } - - private get rheight(): number { - return this.ry2 - this.ry1; - } - - private get rarea(): number { - return this.rwidth * this.rheight; - } - - public isValid(): boolean { - if (this.x1 <= this.x2 && this.y1 <= this.y2) - return true; - return false; - } - - public clone(): Rectangle { - return new Rectangle(this.x1, this.x2, this.width, this.height); - } - - public containsPoint (x: number, y: number): boolean { - if (x >= this.x1 && x <= this.x2 - && y >= this.y1 && y <= this.y2) - return true; - - return false; - } - - public containsPixel (px: number, py: number): boolean { - if (px >= this.rx1 && px <= this.rx2 - && py >= this.ry1 && py <= this.ry2) - return true; - - return false; - } - - public containsXOrdinate (ox: number): boolean { - if (ox >= this.x1 && ox <= this.x2) - return true; - - return false; - } - - public containsYOrdinate (oy: number): boolean { - if (oy >= this.y1 && oy <= this.y2) - return true; - - return false; - } - - public containsPixelOrdinateX (ox: number): boolean { - if (ox >= this.rx1 && ox <= this.rx2) - return true; - - return false; - } - - public containsPixelOrdinateY (oy: number): boolean { - if (oy >= this.ry1 && oy <= this.ry2) - return true; - - return false; - } - - /// Sets x1 of the rectangle without changing x2. - public setX1 (x1: number): void { - this.width += (this.x1 - x1); - this.x1 = x1; - } - - /// Sets x2 of the rectangle without changing x1. - public setX2 (x2: number): void { - this.width = x2 - this.x1; - } - - /// Sets y1 of the rectangle without changing y2. - public setY1 (y1: number): void { - this.height += (this.y1 - y1); - this.y1 = y1; - } - - /// Sets y2 of the rectangle without changing y1. - public setY2 (y2: number): void { - this.height = y2 - this.y1; - } - - /// Sets width keeping x1 constant. - public setWidth (width: number): void { - this.width = width; - } - - /// Sets height keeping y1 constant. - public setHeight (height: number): void { - this.height = height; - } - - /// Sets area by either keeping height or width as constant. - public setArea (area: number, preserveHeight: boolean): void { - if (!preserveHeight) { //preserve width - const height = area / this.width; - this.setHeight(height); - } - else { // preserve height - const width = area / this.height; - this.setWidth(width); - } - } - - /// Moves the whole rectangle by (dx, dy) by preserving width and height. - public moveBy (dx: number, dy: number): void { - this.x1 += dx; - this.y1 += dy; - } - - /** - * Moves the rectangle to (x, y) as its new x1, y1 without changing - * its size. - */ - public moveTo (x: number, y: number): void { - this.x1 = x; - this.y1 = y; - } - - // TODO: Following methods could be replaced with js getters - // but we need to change their users to access getters. - - public getX1(): number { - return this.x1; - } - - public getX2(): number { - return this.x2; - } - - public getY1(): number { - return this.y1; - } - - public getY2(): number { - return this.y2; - } - - public getWidth(): number { - return this.width; - } - - public getHeight(): number { - return this.height; - } - - public getArea(): number { - return this.area; - } - - public getCenter(): number[] { - return [(this.x2 + this.x1) / 2, (this.y2 + this.y1) / 2]; - } - - public getPxX1(): number { - return this.rx1; - } - - public getPxX2(): number { - return this.rx2; - } - - public getPxY1(): number { - return this.ry1; - } - - public getPxY2(): number { - return this.ry2; - } - - public getPxWidth(): number { - return this.rwidth; - } - - public getPxHeight(): number { - return this.rheight; - } - - public getPxArea(): number { - return this.rarea; - } - - public getPxCenter(): number[] { - return [Math.round((this.rx2 + this.rx1) / 2), Math.round((this.ry2 + this.ry1) / 2)]; - } -} - -export function createRectangle(x: number, y: number, width: number, height: number): Rectangle { - return new Rectangle(x, y, width, height); -} - -} - -L.LOUtil.Rectangle = cool.Rectangle; -L.LOUtil.createRectangle = cool.createRectangle; diff --git a/browser/src/core/Socket.js b/browser/src/core/Socket.js index 196ac58bf63cd..730c79f9335ba 100644 --- a/browser/src/core/Socket.js +++ b/browser/src/core/Socket.js @@ -1215,7 +1215,7 @@ app.definitions.Socket = L.Class.extend({ this._map.fire('infobar', { msg: textMsg, - action: L.Util.getProduct(), + action: app.util.getProduct(), actionLabel: errorMessages.infoandsupport }); } @@ -1431,7 +1431,7 @@ app.definitions.Socket = L.Class.extend({ callbackList.push({ id: 'save-to-new-file', func_: function() { var filename = this._map['wopi'].BaseFileName; if (filename) { - filename = L.LOUtil.generateNewFileName(filename, '_new'); + filename = app.LOUtil.generateNewFileName(filename, '_new'); this._map.saveAs(filename); } }.bind(this)}); @@ -1617,7 +1617,7 @@ app.definitions.Socket = L.Class.extend({ _onJSDialog: function(textMsg, callback) { var msgData = JSON.parse(textMsg.substring('jsdialog:'.length + 1)); - if (msgData.children && !L.Util.isArray(msgData.children)) { + if (msgData.children && !app.util.isArray(msgData.children)) { window.app.console.warn('_onJSDialogMsg: The children\'s data should be created of array type'); return; } diff --git a/browser/src/core/Util.js b/browser/src/core/Util.js index 2be44e2f1a0fc..bc6b64626644a 100644 --- a/browser/src/core/Util.js +++ b/browser/src/core/Util.js @@ -3,8 +3,6 @@ * L.Util contains various utility functions used throughout Leaflet code. */ -/* global brandProductFAQURL */ - L.Util = { // extend an object with properties of one or more other objects extend: function (dest) { @@ -43,93 +41,6 @@ L.Util = { }; }, - // return unique ID of an object - stamp: function (obj) { - /*eslint-disable */ - obj._leaflet_id = obj._leaflet_id || ++L.Util.lastId; - return obj._leaflet_id; - /*eslint-enable */ - }, - - lastId: 0, - - // return a function that won't be called more often than the given interval - throttle: function (fn, time, context) { - var lock, args, wrapperFn, later; - - later = function () { - // reset lock and call if queued - lock = false; - if (args) { - wrapperFn.apply(context, args); - args = false; - } - }; - - wrapperFn = function () { - if (lock) { - // called too soon, queue to call later - args = arguments; - - } else { - // call and lock until later - fn.apply(context, arguments); - setTimeout(later, time); - lock = true; - } - }; - - return wrapperFn; - }, - - // wrap the given number to lie within a certain range (used for wrapping longitude) - wrapNum: function (x, range, includeMax) { - var max = range[1], - min = range[0], - d = max - min; - return x === max && includeMax ? x : ((x - min) % d + d) % d + min; - }, - - // do nothing (used as a noop throughout the code) - falseFn: function () { return false; }, - - // round a given number to a given precision - formatNum: function (num, digits) { - var pow = Math.pow(10, digits || 5); - return Math.round(num * pow) / pow; - }, - - // removes given prefix and suffix from the string if exists - // if suffix is not specified prefix is trimmed from both end of string - // trim whitespace from both sides of a string if prefix and suffix are not given - trim: function (str, prefix, suffix) { - if (!prefix) - return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); - var result = this.trimStart(str, prefix); - result = this.trimEnd(result, suffix); - return result; - }, - - // removes prefix from string if string starts with that prefix - trimStart: function (str, prefix) { - if (str.indexOf(prefix) === 0) - return str.substring(prefix.length); - return str; - }, - - // removes suffix from string if string ends with that suffix - trimEnd: function (str, suffix) { - var suffixIndex = str.lastIndexOf(suffix); - if (suffixIndex !== -1 && (str.length - suffix.length === suffixIndex)) - return str.substring(0, suffixIndex); - return str; - }, - - // split a string into words - splitWords: function (str) { - return L.Util.trim(str).split(/\s+/); - }, - // set options to an object, inheriting parent's options as well setOptions: function (obj, options) { if (!Object.prototype.hasOwnProperty.call(obj, 'options')) { @@ -141,162 +52,9 @@ L.Util = { return obj.options; }, - round: function(x, e) { - if (!e) { - return Math.round(x); - } - var f = 1.0/e; - return Math.round(x * f) * e; - }, - - // super-simple templating facility, used for TileLayer URLs - template: function (str, data) { - return str.replace(L.Util.templateRe, function (str, key) { - var value = data[key]; - - if (value === undefined) { - throw new Error('No value provided for variable ' + str); - - } else if (typeof value === 'function') { - value = value(data); - } - return value; - }); - }, - - templateRe: /\{ *([\w_]+) *\}/g, - - isArray: Array.isArray || function (obj) { - return (Object.prototype.toString.call(obj) === '[object Array]'); - }, - - // minimal image URI, set to an image when disposing to flush memory - emptyImageUrl: 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=', - - toggleFullScreen: function() { - if (!document.fullscreenElement && - !document.mozFullscreenElement && - !document.msFullscreenElement && - !document.webkitFullscreenElement) { - if (document.documentElement.requestFullscreen) { - document.documentElement.requestFullscreen(); - } else if (document.documentElement.msRequestFullscreen) { - document.documentElement.msRequestFullscreen(); - } else if (document.documentElement.mozRequestFullScreen) { - document.documentElement.mozRequestFullScreen(); - } else if (document.documentElement.webkitRequestFullscreen) { - document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); - } - } else if (document.exitFullscreen) { - document.exitFullscreen(); - } else if (document.msExitFullscreen) { - document.msExitFullscreen(); - } else if (document.mozCancelFullScreen) { - document.mozCancelFullScreen(); - } else if (document.webkitExitFullscreen) { - document.webkitExitFullscreen(); - } - }, - - isEmpty: function(o) { - return !(o && o.length); - }, - - mm100thToInch: function(mm) { - return mm / 2540; - }, - - getTextWidth: function(text, font) { - var canvas = L.Util.getTextWidth._canvas || (L.Util.getTextWidth._canvas = document.createElement('canvas')); - var context = canvas.getContext('2d'); - context.font = font; - var metrics = context.measureText(text); - return Math.floor(metrics.width); - }, - - getProduct: function () { - var brandFAQURL = (typeof brandProductFAQURL !== 'undefined') ? - brandProductFAQURL : 'https://collaboraonline.github.io/post/faq/'; - if (window.feedbackUrl && window.buyProductUrl) { - var integratorUrl = encodeURIComponent(window.buyProductUrl); - brandFAQURL = window.feedbackUrl; - brandFAQURL = brandFAQURL.substring(0, brandFAQURL.lastIndexOf('/')) + - '/product.html?integrator='+ integratorUrl; - } - return brandFAQURL; - }, - - replaceCtrlAltInMac: function(msg) { - if (L.Browser.mac) { - var ctrl = /Ctrl/g; - var alt = /Alt/g; - if (String.locale.startsWith('de') || String.locale.startsWith('dsb') || String.locale.startsWith('hsb')) { - ctrl = /Strg/g; - } - if (String.locale.startsWith('lt')) { - ctrl = /Vald/g; - } - if (String.locale.startsWith('sl')) { - ctrl = /Krmilka/gi; - alt = /Izmenjalka/gi; - } - return msg.replace(ctrl, '⌘').replace(alt, '⌥'); - } - return msg; - }, - randomString: function(len) { - var result = ''; - var ValidCharacters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; - for (var i = 0; i < len; i++) { - result += ValidCharacters.charAt(Math.floor(Math.random() * ValidCharacters.length)); - } - return result; - } }; -(function () { - // inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/ - - function getPrefixed(name) { - return window['webkit' + name] || window['moz' + name] || window['ms' + name]; - } - - var lastTime = 0; - - // fallback for IE 7-8 - function timeoutDefer(fn) { - var time = +new Date(), - timeToCall = Math.max(0, 16 - (time - lastTime)); - - lastTime = time + timeToCall; - return window.setTimeout(fn, timeToCall); - } - - var requestFn = window.requestAnimationFrame || getPrefixed('RequestAnimationFrame') || timeoutDefer, - cancelFn = window.cancelAnimationFrame || getPrefixed('CancelAnimationFrame') || - getPrefixed('CancelRequestAnimationFrame') || function (id) { window.clearTimeout(id); }; - - - L.Util.requestAnimFrame = function (fn, context, immediate) { - if (immediate && requestFn === timeoutDefer) { - fn.call(context); - } else { - return requestFn.call(window, L.bind(fn, context)); - } - }; - - L.Util.cancelAnimFrame = function (id) { - if (id) { - cancelFn.call(window, id); - } - }; - - // on IE11 Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER are not supported - L.Util.MAX_SAFE_INTEGER = Math.pow(2, 53)-1; - L.Util.MIN_SAFE_INTEGER = -L.Util.MAX_SAFE_INTEGER; -})(); - if (!String.prototype.startsWith) { String.prototype.startsWith = function(searchString, position) { position = position || 0; @@ -323,10 +81,4 @@ if (!Number.MAX_SAFE_INTEGER) { // shortcuts for most used utility functions L.extend = L.Util.extend; L.bind = L.Util.bind; -L.stamp = L.Util.stamp; L.setOptions = L.Util.setOptions; -L.round = L.Util.round; -L.toggleFullScreen = L.Util.toggleFullScreen; -L.isEmpty = L.Util.isEmpty; -L.mm100thToInch = L.Util.mm100thToInch; -L.getTextWidth = L.Util.getTextWidth; diff --git a/browser/src/docdispatcher.ts b/browser/src/docdispatcher.ts index 9d201be2f3a7b..53ad28493baab 100644 --- a/browser/src/docdispatcher.ts +++ b/browser/src/docdispatcher.ts @@ -497,7 +497,7 @@ class Dispatcher { }; this.actionsMap['fullscreen-drawing'] = () => { - L.toggleFullScreen(); + app.util.toggleFullScreen(); }; this.actionsMap['deletepage'] = function () { diff --git a/browser/src/docstate.js b/browser/src/docstate.js index c9a57170529bc..bb3187a88489d 100644 --- a/browser/src/docstate.js +++ b/browser/src/docstate.js @@ -36,6 +36,8 @@ window.app = { twipsCorrection: 0.567 // There is a constant ratio between tiletwips and impress page twips. For now, this seems safe to use. }, map: null, // Make map object a part of this. + util: null, // Attach the Util class. + LOUtil: null, // Attach the LOUtil class. dispatcher: null, // A Dispatcher class instance is assigned to this. twipsToPixels: 0, // Twips to pixels multiplier. pixelsToTwips: 0, // Pixels to twips multiplier. diff --git a/browser/src/dom/DomEvent.js b/browser/src/dom/DomEvent.js index 55949cd0da9ec..ea15e71eaa1a0 100644 --- a/browser/src/dom/DomEvent.js +++ b/browser/src/dom/DomEvent.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ /* * L.DomEvent contains functions for working with DOM events. * Inspired by John Resig, Dean Edwards and YUI addEvent implementations. @@ -15,7 +16,7 @@ L.DomEvent = { this._on(obj, type, types[type], fn); } } else { - types = L.Util.splitWords(types); + types = app.util.splitWords(types); for (var i = 0, len = types.length; i < len; i++) { this._on(obj, types[i], fn, context); @@ -32,7 +33,7 @@ L.DomEvent = { this._off(obj, type, types[type], fn); } } else { - types = L.Util.splitWords(types); + types = app.util.splitWords(types); for (var i = 0, len = types.length; i < len; i++) { this._off(obj, types[i], fn, context); @@ -43,7 +44,7 @@ L.DomEvent = { }, _on: function (obj, type, fn, context) { - var id = type + L.stamp(fn) + (context ? '_' + L.stamp(context) : ''); + var id = type + app.util.stamp(fn) + (context ? '_' + app.util.stamp(context) : ''); if (obj[eventsKey] && obj[eventsKey][id]) { return this; } @@ -98,7 +99,7 @@ L.DomEvent = { _off: function (obj, type, fn, context) { - var id = type + L.stamp(fn) + (context ? '_' + L.stamp(context) : ''), + var id = type + app.util.stamp(fn) + (context ? '_' + app.util.stamp(context) : ''), handler = obj[eventsKey] && obj[eventsKey][id]; if (!handler) { return this; } diff --git a/browser/src/dom/DomUtil.js b/browser/src/dom/DomUtil.js index 9b2419bd6a9b4..12e87d920f938 100644 --- a/browser/src/dom/DomUtil.js +++ b/browser/src/dom/DomUtil.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ /* * L.DomUtil contains various utility functions for working with DOM. */ @@ -89,7 +90,7 @@ L.DomUtil = { } if (el.classList !== undefined) { - var classes = L.Util.splitWords(name); + var classes = app.util.splitWords(name); for (var i = 0, len = classes.length; i < len; i++) { el.classList.add(classes[i]); } @@ -107,7 +108,7 @@ L.DomUtil = { if (el.classList !== undefined) { el.classList.remove(name); } else { - L.DomUtil.setClass(el, L.Util.trim((' ' + L.DomUtil.getClass(el) + ' ').replace(' ' + name + ' ', ' '))); + L.DomUtil.setClass(el, app.util.trim((' ' + L.DomUtil.getClass(el) + ' ').replace(' ' + name + ' ', ' '))); } }, diff --git a/browser/src/dom/Draggable.js b/browser/src/dom/Draggable.js index 691c54585e8af..25ed284457422 100644 --- a/browser/src/dom/Draggable.js +++ b/browser/src/dom/Draggable.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ /* * L.Draggable allows you to add dragging capabilities to any element. Supports mobile devices too. */ @@ -171,10 +172,10 @@ L.Draggable = L.Evented.extend({ this._moving = true; - L.Util.cancelAnimFrame(this._animRequest); + app.util.cancelAnimFrame(this._animRequest); this._lastEvent = e; - this._animRequest = L.Util.requestAnimFrame(this._updatePosition, this, true, this._dragStartTarget); + this._animRequest = app.util.requestAnimFrame(this._updatePosition, this, true, this._dragStartTarget); }, _updatePosition: function () { @@ -203,7 +204,7 @@ L.Draggable = L.Evented.extend({ if (this._moved && this._moving) { // ensure drag is not fired after dragend - L.Util.cancelAnimFrame(this._animRequest); + app.util.cancelAnimFrame(this._animRequest); this.fire('dragend', { originalEvent: e, diff --git a/browser/src/dom/PosAnimation.Timer.js b/browser/src/dom/PosAnimation.Timer.js index 6a7957de44626..7c3dfd2a4be39 100644 --- a/browser/src/dom/PosAnimation.Timer.js +++ b/browser/src/dom/PosAnimation.Timer.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ /* * L.PosAnimation fallback implementation that powers Leaflet pan animations * in browsers that don't support CSS3 Transitions. @@ -32,7 +33,7 @@ L.PosAnimation = L.DomUtil.TRANSITION ? L.PosAnimation : L.PosAnimation.extend({ _animate: function () { // animation loop - this._animId = L.Util.requestAnimFrame(this._animate, this); + this._animId = app.util.requestAnimFrame(this._animate, this); this._step(); }, @@ -56,7 +57,7 @@ L.PosAnimation = L.DomUtil.TRANSITION ? L.PosAnimation : L.PosAnimation.extend({ }, _complete: function () { - L.Util.cancelAnimFrame(this._animId); + app.util.cancelAnimFrame(this._animId); this._inProgress = false; this.fire('end'); diff --git a/browser/src/dom/PosAnimation.js b/browser/src/dom/PosAnimation.js index b5ac8d1ec6053..6bf1addb9f714 100644 --- a/browser/src/dom/PosAnimation.js +++ b/browser/src/dom/PosAnimation.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ /* * L.PosAnimation is used by Leaflet internally for pan animations. */ @@ -34,7 +35,7 @@ L.PosAnimation = L.Class.extend({ L.DomUtil.setPosition(el, newPos); // toggle reflow, Chrome flickers for some reason if you don't do this - L.Util.falseFn(el.offsetWidth); + app.util.falseFn(el.offsetWidth); // there's no native way to track value updates of transitioned properties, so we imitate this this._stepTimer = setInterval(L.bind(this._onStep, this), 50); @@ -48,7 +49,7 @@ L.PosAnimation = L.Class.extend({ L.DomUtil.setPosition(this._el, this._getPos()); this._onTransitionEnd(); - L.Util.falseFn(this._el.offsetWidth); // force reflow in case we are about to start a new animation + app.util.falseFn(this._el.offsetWidth); // force reflow in case we are about to start a new animation }, _onStep: function () { diff --git a/browser/src/geo/LatLng.js b/browser/src/geo/LatLng.js index 4fad29b55362b..62add5591fe5c 100644 --- a/browser/src/geo/LatLng.js +++ b/browser/src/geo/LatLng.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ /* * L.LatLng represents a geographical point with latitude and longitude coordinates. */ @@ -31,8 +32,8 @@ L.LatLng.prototype = { toString: function (precision) { return 'LatLng(' + - L.Util.formatNum(this.lat, precision) + ', ' + - L.Util.formatNum(this.lng, precision) + ')'; + app.util.formatNum(this.lat, precision) + ', ' + + app.util.formatNum(this.lng, precision) + ')'; }, distanceTo: function () { @@ -52,7 +53,7 @@ L.latLng = function (a, b, c) { if (a instanceof L.LatLng) { return a; } - if (L.Util.isArray(a) && typeof a[0] !== 'object') { + if (app.util.isArray(a) && typeof a[0] !== 'object') { if (a.length === 3) { return new L.LatLng(a[0], a[1], a[2]); } diff --git a/browser/src/layer/FormFieldButtonLayer.js b/browser/src/layer/FormFieldButtonLayer.js index 472c242388bab..e6fcad2d59b93 100644 --- a/browser/src/layer/FormFieldButtonLayer.js +++ b/browser/src/layer/FormFieldButtonLayer.js @@ -90,7 +90,7 @@ L.FormFieldButton = L.Layer.extend({ button.style.width = container.style.height; var image = L.DomUtil.create('img', 'form-field-button-image', button); - L.LOUtil.setImage(image, 'unfold.svg', this.map); + app.LOUtil.setImage(image, 'unfold.svg', this.map); button.addEventListener('click', this._onClickDropDown); // Stop propagation to the main document diff --git a/browser/src/layer/Layer.js b/browser/src/layer/Layer.js index 208da54b57e9e..8ede4119c5e12 100644 --- a/browser/src/layer/Layer.js +++ b/browser/src/layer/Layer.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ L.Layer = L.Evented.extend({ @@ -27,12 +28,12 @@ L.Layer = L.Evented.extend({ }, addInteractiveTarget: function (targetEl) { - this._map._targets[L.stamp(targetEl)] = this; + this._map._targets[app.util.stamp(targetEl)] = this; return this; }, removeInteractiveTarget: function (targetEl) { - delete this._map._targets[L.stamp(targetEl)]; + delete this._map._targets[app.util.stamp(targetEl)]; return this; }, @@ -59,7 +60,7 @@ L.Layer = L.Evented.extend({ L.Map.include({ addLayer: function (layer) { - var id = L.stamp(layer); + var id = app.util.stamp(layer); if (this._layers[id]) { return layer; } this._layers[id] = layer; @@ -75,7 +76,7 @@ L.Map.include({ }, removeLayer: function (layer) { - var id = L.stamp(layer); + var id = app.util.stamp(layer); if (!this._layers[id]) { return this; } @@ -100,7 +101,7 @@ L.Map.include({ }, hasLayer: function (layer) { - return !!layer && (L.stamp(layer) in this._layers); + return !!layer && (app.util.stamp(layer) in this._layers); }, eachLayer: function (method, context) { @@ -111,7 +112,7 @@ L.Map.include({ }, _addLayers: function (layers) { - layers = layers ? (L.Util.isArray(layers) ? layers : [layers]) : []; + layers = layers ? (app.util.isArray(layers) ? layers : [layers]) : []; for (var i = 0, len = layers.length; i < len; i++) { this.addLayer(layers[i]); @@ -120,13 +121,13 @@ L.Map.include({ _addZoomLimit: function (layer) { if (isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom)) { - this._zoomBoundLayers[L.stamp(layer)] = layer; + this._zoomBoundLayers[app.util.stamp(layer)] = layer; this._updateZoomLevels(); } }, _removeZoomLimit: function (layer) { - var id = L.stamp(layer); + var id = app.util.stamp(layer); if (this._zoomBoundLayers[id]) { delete this._zoomBoundLayers[id]; diff --git a/browser/src/layer/LayerGroup.js b/browser/src/layer/LayerGroup.js index a43e0eee04cd4..afb3987c41c2f 100644 --- a/browser/src/layer/LayerGroup.js +++ b/browser/src/layer/LayerGroup.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ /* * L.LayerGroup is a class to combine several layers into one so that * you can manipulate the group (e.g. add/remove it) as one layer. @@ -101,7 +102,7 @@ L.LayerGroup = L.Layer.extend({ }, getLayerId: function (layer) { - return L.stamp(layer); + return app.util.stamp(layer); } }); diff --git a/browser/src/layer/marker/ProgressOverlay.js b/browser/src/layer/marker/ProgressOverlay.js index 22e3cbf1d98fa..9c294c730345e 100644 --- a/browser/src/layer/marker/ProgressOverlay.js +++ b/browser/src/layer/marker/ProgressOverlay.js @@ -3,7 +3,7 @@ * L.ProgressOverlay is used to overlay progress images over the map. */ -/* global brandProductName $ */ +/* global app brandProductName $ */ L.ProgressOverlay = L.Layer.extend({ options: { @@ -59,7 +59,7 @@ L.ProgressOverlay = L.Layer.extend({ showSpinner: function() { L.DomUtil.get('document-container').appendChild(this._container); - this._spinnerInterval = L.LOUtil.startSpinner(this._spinnerCanvas, this.options.spinnerSpeed); + this._spinnerInterval = app.LOUtil.startSpinner(this._spinnerCanvas, this.options.spinnerSpeed); }, hideSpinner: function() { diff --git a/browser/src/layer/tile/CalcTileLayer.js b/browser/src/layer/tile/CalcTileLayer.js index 7f6ed386c97c5..c879054d1c4ea 100644 --- a/browser/src/layer/tile/CalcTileLayer.js +++ b/browser/src/layer/tile/CalcTileLayer.js @@ -1025,7 +1025,7 @@ L.CalcTileLayer = L.CanvasTileLayer.extend({ var bottomRightTwips = topLeftTwips.add(offset); var boundsTwips = that._convertToTileTwipsSheetArea(new L.Bounds(topLeftTwips, bottomRightTwips)); - element = L.LOUtil.createRectangle(boundsTwips.min.x * ratio, boundsTwips.min.y * ratio, boundsTwips.getSize().x * ratio, boundsTwips.getSize().y * ratio); + element = app.LOUtil.createRectangle(boundsTwips.min.x * ratio, boundsTwips.min.y * ratio, boundsTwips.getSize().x * ratio, boundsTwips.getSize().y * ratio); return element; }); } diff --git a/browser/src/layer/tile/CanvasTileLayer.js b/browser/src/layer/tile/CanvasTileLayer.js index a7cdf57a22e3a..96b39fd885ae8 100644 --- a/browser/src/layer/tile/CanvasTileLayer.js +++ b/browser/src/layer/tile/CanvasTileLayer.js @@ -104,7 +104,7 @@ var CSelections = L.Class.extend({ if (!this._selection) { if (!this._isOle) { var fillColor = this._isView ? - L.LOUtil.rgbToHex(this._map.getViewColor(this._viewId)) : + app.LOUtil.rgbToHex(this._map.getViewColor(this._viewId)) : this._styleData.getPropValue('background-color'); var opacity = this._styleData.getFloatPropValue('opacity'); var weight = this._styleData.getFloatPropWithoutUnit('border-top-width'); @@ -298,7 +298,7 @@ L.TileSectionManager = L.Class.extend({ stopUpdates: function () { if (this._updatesRunning) { - L.Util.cancelAnimFrame(this._canvasRAF); + app.util.cancelAnimFrame(this._canvasRAF); this.update(); this._updatesRunning = false; return true; @@ -347,7 +347,7 @@ L.TileSectionManager = L.Class.extend({ else { var ratio = this._layer._tileSize / this._layer._tileHeightTwips; var partHeightPixels = Math.round((this._layer._partHeightTwips + this._layer._spaceBetweenParts) * ratio); - return L.LOUtil._doRectanglesIntersect(app.file.viewedRectangle.pToArray(), [coords.x, coords.y + partHeightPixels * coords.part, app.tile.size.pixels[0], app.tile.size.pixels[1]]); + return app.LOUtil._doRectanglesIntersect(app.file.viewedRectangle.pToArray(), [coords.x, coords.y + partHeightPixels * coords.part, app.tile.size.pixels[0], app.tile.size.pixels[1]]); } }, @@ -391,7 +391,7 @@ L.TileSectionManager = L.Class.extend({ _updateWithRAF: function () { // update-loop with requestAnimationFrame - this._canvasRAF = L.Util.requestAnimFrame(this._updateWithRAF, this, false /* immediate */); + this._canvasRAF = app.util.requestAnimFrame(this._updateWithRAF, this, false /* immediate */); app.sectionContainer.requestReDraw(); }, @@ -2344,7 +2344,7 @@ L.CanvasTileLayer = L.Layer.extend({ _addView: function(viewInfo) { if (viewInfo.color === 0 && this._map.getDocType() !== 'text') { - viewInfo.color = L.LOUtil.getViewIdColor(viewInfo.id); + viewInfo.color = app.LOUtil.getViewIdColor(viewInfo.id); } this._map.addView(viewInfo); @@ -2943,7 +2943,7 @@ L.CanvasTileLayer = L.Layer.extend({ var topLeftPixels = this._twipsToCorePixels(topLeftTwips); var offsetPixels = this._twipsToCorePixels(offset); - this._cellAutoFillAreaPixels = L.LOUtil.createRectangle(topLeftPixels.x, topLeftPixels.y, offsetPixels.x, offsetPixels.y); + this._cellAutoFillAreaPixels = app.LOUtil.createRectangle(topLeftPixels.x, topLeftPixels.y, offsetPixels.x, offsetPixels.y); } else { this._cellAutoFillAreaPixels = null; @@ -4153,10 +4153,10 @@ L.CanvasTileLayer = L.Layer.extend({ _getTilesSectionRectangle: function () { var section = app.sectionContainer.getSectionWithName(L.CSections.Tiles.name); if (section) { - return L.LOUtil.createRectangle(section.myTopLeft[0] / app.dpiScale, section.myTopLeft[1] / app.dpiScale, section.size[0] / app.dpiScale, section.size[1] / app.dpiScale); + return app.LOUtil.createRectangle(section.myTopLeft[0] / app.dpiScale, section.myTopLeft[1] / app.dpiScale, section.size[0] / app.dpiScale, section.size[1] / app.dpiScale); } else { - return L.LOUtil.createRectangle(0, 0, 0, 0); + return app.LOUtil.createRectangle(0, 0, 0, 0); } }, @@ -4408,7 +4408,7 @@ L.CanvasTileLayer = L.Layer.extend({ viewreset: this._viewReset, movestart: this._moveStart, // update tiles on move, but not more often than once per given interval - move: L.Util.throttle(this._move, this.options.updateInterval, this), + move: app.util.throttle(this._move, this.options.updateInterval, this), moveend: this._moveEnd, splitposchanged: this._move, }; @@ -4664,7 +4664,7 @@ L.CanvasTileLayer = L.Layer.extend({ docBoundsRectangle[3] = docBoundsRectangle[3] - docBoundsRectangle[1]; for (i = 0; i < parts.length; i++) { rectangle = [0, partHeightPixels * parts[i].part, partWidthPixels, partHeightPixels]; - rectangle = L.LOUtil._getIntersectionRectangle(rectangle, docBoundsRectangle); + rectangle = app.LOUtil._getIntersectionRectangle(rectangle, docBoundsRectangle); if (rectangle) { if (rectangle[2] * rectangle[3] > maxArea) { maxArea = rectangle[2] * rectangle[3]; @@ -4757,7 +4757,7 @@ L.CanvasTileLayer = L.Layer.extend({ var partWidthPixels = Math.round((this._partWidthTwips) * ratio); var mode = 0; // mode is different only in Impress MasterPage mode so far - var intersectionAreaRectangle = L.LOUtil._getIntersectionRectangle(app.file.viewedRectangle.pToArray(), [0, 0, partWidthPixels, partHeightPixels * this._parts]); + var intersectionAreaRectangle = app.LOUtil._getIntersectionRectangle(app.file.viewedRectangle.pToArray(), [0, 0, partWidthPixels, partHeightPixels * this._parts]); var queue = []; diff --git a/browser/src/layer/vector/Canvas.js b/browser/src/layer/vector/Canvas.js index bb7d1fe850ecf..8469e42aaff51 100644 --- a/browser/src/layer/vector/Canvas.js +++ b/browser/src/layer/vector/Canvas.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ /* * L.Canvas handles Canvas vector layers rendering and mouse events handling. All Canvas-specific code goes here. */ @@ -47,10 +48,10 @@ L.Canvas = L.Renderer.extend({ }, _initPath: function (layer) { - this._layers[L.stamp(layer)] = layer; + this._layers[app.util.stamp(layer)] = layer; }, - _addPath: L.Util.falseFn, + _addPath: app.util.falseFn, _removePath: function (layer) { layer._removed = true; @@ -76,7 +77,7 @@ L.Canvas = L.Renderer.extend({ this._redrawBounds = this._redrawBounds || new L.Bounds(); this._redrawBounds.extend(layer._pxBounds.min).extend(layer._pxBounds.max); - this._redrawRequest = this._redrawRequest || L.Util.requestAnimFrame(this._redraw, this); + this._redrawRequest = this._redrawRequest || app.util.requestAnimFrame(this._redraw, this); }, _redraw: function () { @@ -231,8 +232,8 @@ L.Canvas = L.Renderer.extend({ // TODO _bringToFront & _bringToBack, pretty tricky - _bringToFront: L.Util.falseFn, - _bringToBack: L.Util.falseFn + _bringToFront: app.util.falseFn, + _bringToBack: app.util.falseFn }); L.Browser.canvas = (function () { diff --git a/browser/src/layer/vector/Path.Drag.js b/browser/src/layer/vector/Path.Drag.js index e51fe8c5dce8a..1e46f2e77e7d2 100644 --- a/browser/src/layer/vector/Path.Drag.js +++ b/browser/src/layer/vector/Path.Drag.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ var END = { mousedown: 'mouseup', @@ -253,8 +254,8 @@ L.Handler.PathDrag = L.Handler.extend(/** @lends L.Path.Drag.prototype */ { // hack for skipping the click in canvas-rendered layers var contains = this._path._containsPoint; - this._path._containsPoint = L.Util.falseFn; - L.Util.requestAnimFrame(function() { + this._path._containsPoint = app.util.falseFn; + app.util.requestAnimFrame(function() { L.DomEvent._skipped({ type: 'click' }); this._path._containsPoint = contains; }, this); @@ -316,7 +317,7 @@ L.Handler.PathDrag = L.Handler.extend(/** @lends L.Path.Drag.prototype */ { var rings = path._rings || path._parts; var latlngs = path._latlngs; dest = dest || latlngs; - if (!L.Util.isArray(latlngs[0])) { // polyline + if (!app.util.isArray(latlngs[0])) { // polyline latlngs = [latlngs]; dest = [dest]; } @@ -346,14 +347,14 @@ L.Handler.PathDrag = L.Handler.extend(/** @lends L.Path.Drag.prototype */ { _replaceCoordGetters: function() { if (this._path.getLatLng) { // Circle, CircleMarker this._path.getLatLng_ = this._path.getLatLng; - this._path.getLatLng = L.Util.bind(function() { + this._path.getLatLng = function() { return this.dragging._transformPoints(this.dragging._matrix, {}); - }, this._path); + }.bind(this._path); } else if (this._path.getLatLngs) { this._path.getLatLngs_ = this._path.getLatLngs; - this._path.getLatLngs = L.Util.bind(function() { + this._path.getLatLngs = function() { return this.dragging._transformPoints(this.dragging._matrix, []); - }, this._path); + }.bind(this._path); } }, diff --git a/browser/src/layer/vector/Path.Transform.Util.js b/browser/src/layer/vector/Path.Transform.Util.js index 0759d59201f99..5aedbe08d4549 100644 --- a/browser/src/layer/vector/Path.Transform.Util.js +++ b/browser/src/layer/vector/Path.Transform.Util.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ /** * @namespace @@ -49,7 +50,7 @@ L.PathTransform.merge = function() { val = obj[key]; if (isObject(val) && isObject(target[key])) { - target[key] = L.Util.merge(target[key], val); + target[key] = app.util.merge(target[key], val); } else { target[key] = val; } diff --git a/browser/src/layer/vector/Path.js b/browser/src/layer/vector/Path.js index 806d103944d48..e47c6debb7e54 100644 --- a/browser/src/layer/vector/Path.js +++ b/browser/src/layer/vector/Path.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ /* * L.Path is the base class for all Leaflet vector layers like polygons and circles. */ @@ -178,7 +179,7 @@ L.Path.PathNodeData = L.Class.extend({ }); L.Path.PathNodeData.key = function (layer) { - return L.stamp(layer); + return app.util.stamp(layer); }; L.Path.PathNodeCollection = L.Class.extend({ diff --git a/browser/src/layer/vector/Polyline.js b/browser/src/layer/vector/Polyline.js index ac721e02095e4..8f4dc24686876 100644 --- a/browser/src/layer/vector/Polyline.js +++ b/browser/src/layer/vector/Polyline.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ /* * L.Polyline implements polyline vector layer (a set of points connected with lines) */ @@ -82,7 +83,7 @@ L.Polyline = L.Path.extend({ _flat: function (latlngs) { // true if it's a flat array of latlngs; false if nested - return !L.Util.isArray(latlngs[0]) || typeof latlngs[0][0] !== 'object'; + return !app.util.isArray(latlngs[0]) || typeof latlngs[0][0] !== 'object'; }, _project: function () { diff --git a/browser/src/layer/vector/Renderer.js b/browser/src/layer/vector/Renderer.js index e1d376949050a..e5f50f2d03271 100644 --- a/browser/src/layer/vector/Renderer.js +++ b/browser/src/layer/vector/Renderer.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8 -*- */ +/* global app */ /* * L.Renderer is a base class for renderer implementations (SVG, Canvas); * handles renderer container, bounds and zoom animation. @@ -14,7 +15,7 @@ L.Renderer = L.Layer.extend({ initialize: function (options) { L.setOptions(this, options); - L.stamp(this); + app.util.stamp(this); }, setParentRenderer: function (parent) { diff --git a/browser/src/map/Clipboard.js b/browser/src/map/Clipboard.js index b918d86c8131e..7502d9ca5d13e 100644 --- a/browser/src/map/Clipboard.js +++ b/browser/src/map/Clipboard.js @@ -1277,7 +1277,7 @@ L.Clipboard = L.Class.extend({ innerDiv.appendChild(p); } else { - const ctrlText = L.Util.replaceCtrlAltInMac('Ctrl'); + const ctrlText = app.util.replaceCtrlAltInMac('Ctrl'); const p = document.createElement('p'); p.textContent = 'Your browser has very limited access to the clipboard, so use these keyboard shortcuts:'; innerDiv.appendChild(p); @@ -1358,7 +1358,7 @@ L.Clipboard = L.Class.extend({ var innerDiv = L.DomUtil.create('div', '', null); box.insertBefore(innerDiv, box.firstChild); - const ctrlText = L.Util.replaceCtrlAltInMac('Ctrl'); + const ctrlText = app.util.replaceCtrlAltInMac('Ctrl'); let p = document.createElement('p'); p.textContent = _('Your browser has very limited access to the clipboard'); diff --git a/browser/src/map/Map.js b/browser/src/map/Map.js index a3c88b700cbab..6e33e23dae2cd 100644 --- a/browser/src/map/Map.js +++ b/browser/src/map/Map.js @@ -45,7 +45,7 @@ L.Map = L.Evented.extend({ tileHeightTwips: window.tileSize * 15, urlPrefix: 'cool', wopiSrc: '', - cursorURL: L.LOUtil.getURL('cursors'), + cursorURL: app.LOUtil.getURL('cursors'), // cursorURL // The path (local to the server) where custom cursor files are stored. }, @@ -260,7 +260,7 @@ L.Map = L.Evented.extend({ }, this); this.on('commandvalues', function(e) { - if (e.commandName === '.uno:LanguageStatus' && L.Util.isArray(e.commandValues)) { + if (e.commandName === '.uno:LanguageStatus' && app.util.isArray(e.commandValues)) { app.languages = []; e.commandValues.forEach(function(language) { var split = language.split(';'); @@ -396,7 +396,7 @@ L.Map = L.Evented.extend({ if (viewInfo.userextrainfo !== undefined && viewInfo.userextrainfo.avatar !== undefined) { this._viewInfoByUserName[viewInfo.username] = viewInfo; } - this.fire('postMessage', {msgId: 'View_Added', args: {Deprecated: true, ViewId: viewInfo.id, UserId: viewInfo.userid, UserName: viewInfo.username, UserExtraInfo: viewInfo.userextrainfo, Color: L.LOUtil.rgbToHex(viewInfo.color), ReadOnly: viewInfo.readonly}}); + this.fire('postMessage', {msgId: 'View_Added', args: {Deprecated: true, ViewId: viewInfo.id, UserId: viewInfo.userid, UserName: viewInfo.username, UserExtraInfo: viewInfo.userextrainfo, Color: app.LOUtil.rgbToHex(viewInfo.color), ReadOnly: viewInfo.readonly}}); // Fire last, otherwise not all events are handled correctly. this.fire('addview', {viewId: viewInfo.id, username: viewInfo.username, extraInfo: viewInfo.userextrainfo, readonly: this.isViewReadOnly(viewInfo.id)}); @@ -841,7 +841,7 @@ L.Map = L.Evented.extend({ }, stop: function () { - L.Util.cancelAnimFrame(this._flyToFrame); + app.util.cancelAnimFrame(this._flyToFrame); if (this._panAnim) { this._panAnim.stop(); } @@ -1050,7 +1050,7 @@ L.Map = L.Evented.extend({ project: function (latlng, zoom) { // (LatLng[, Number]) -> Point zoom = zoom === undefined ? this.getZoom() : zoom; var projectedPoint = this.options.crs.latLngToPoint(L.latLng(latlng), zoom); - return new L.Point(L.round(projectedPoint.x, 1e-6), L.round(projectedPoint.y, 1e-6)); + return new L.Point(app.util.round(projectedPoint.x, 1e-6), app.util.round(projectedPoint.y, 1e-6)); }, unproject: function (point, zoom) { // (Point[, Number]) -> LatLng @@ -1383,8 +1383,8 @@ L.Map = L.Evented.extend({ }, _onResize: function () { - L.Util.cancelAnimFrame(this._resizeRequest); - this._resizeRequest = L.Util.requestAnimFrame( + app.util.cancelAnimFrame(this._resizeRequest); + this._resizeRequest = app.util.requestAnimFrame( function () { this.invalidateSize({debounceMoveend: true}); }, this, false, this._container); if (this.sidebar) @@ -1532,7 +1532,7 @@ L.Map = L.Evented.extend({ if (!this._docLayer || !this._loaded || !this._enabled || L.DomEvent._skipped(e)) { return; } // find the layer the event is propagating from - var target = this._targets[L.stamp(e.target || e.srcElement)], + var target = this._targets[app.util.stamp(e.target || e.srcElement)], //type = e.type === 'keypress' && e.keyCode === 13 ? 'click' : e.type; type = e.type; diff --git a/browser/src/map/handler/Map.TouchGesture.js b/browser/src/map/handler/Map.TouchGesture.js index e1e7deadc66b3..88516401fe8ee 100644 --- a/browser/src/map/handler/Map.TouchGesture.js +++ b/browser/src/map/handler/Map.TouchGesture.js @@ -1,4 +1,5 @@ /* -*- js-indent-level: 8; fill-column: 100 -*- */ +/* global app */ /* * L.Map.CalcTap is used to enable mobile taps. */ @@ -438,7 +439,7 @@ L.Map.TouchGesture = L.Handler.extend({ if (window.IgnorePanning) return; - L.Util.cancelAnimFrame(this.autoscrollAnimReq); + app.util.cancelAnimFrame(this.autoscrollAnimReq); var point = e.pointers[0], containerPoint = this._map.mouseEventToContainerPoint(point), layerPoint = this._map.containerPointToLayerPoint(containerPoint), @@ -644,7 +645,7 @@ L.Map.TouchGesture = L.Handler.extend({ this._map.dragging._draggable._onDown(evt); this._timeStamp = Date.now(); this._inSwipeAction = true; - this.autoscrollAnimReq = L.Util.requestAnimFrame(this._autoscroll, this, true); + this.autoscrollAnimReq = app.util.requestAnimFrame(this._autoscroll, this, true); }, _cancelAutoscrollRAF: function () { @@ -652,7 +653,7 @@ L.Map.TouchGesture = L.Handler.extend({ this._inSwipeAction = false; if (app.file.fileBasedView) this._map._docLayer._checkSelectedPart(); - L.Util.cancelAnimFrame(this.autoscrollAnimReq); + app.util.cancelAnimFrame(this.autoscrollAnimReq); return; }, @@ -704,7 +705,7 @@ L.Map.TouchGesture = L.Handler.extend({ this._map._docLayer._preFetchTiles(true /* forceBorderCalc */); if (!horizontalEnd || !verticalEnd) { - this.autoscrollAnimReq = L.Util.requestAnimFrame(this._autoscroll, this, true); + this.autoscrollAnimReq = app.util.requestAnimFrame(this._autoscroll, this, true); } else { this._inSwipeAction = false; if (app.file.fileBasedView) diff --git a/browser/src/map/handler/Map.WOPI.js b/browser/src/map/handler/Map.WOPI.js index a6289069dfad4..f9418ab3b7ec1 100644 --- a/browser/src/map/handler/Map.WOPI.js +++ b/browser/src/map/handler/Map.WOPI.js @@ -545,7 +545,7 @@ L.Map.WOPI = L.Handler.extend({ this._map.remove(); } else if (msg.MessageId === 'Action_Fullscreen') { - L.toggleFullScreen(); + app.util.toggleFullScreen(); } else if (msg.MessageId === 'Action_FullscreenPresentation' && this._map.getDocType() === 'presentation') { if (msg.Values) { diff --git a/browser/src/map/handler/Map.Welcome.js b/browser/src/map/handler/Map.Welcome.js index 706fe1bb016cd..84dfed14b7e9f 100644 --- a/browser/src/map/handler/Map.Welcome.js +++ b/browser/src/map/handler/Map.Welcome.js @@ -11,7 +11,7 @@ L.Map.mergeOptions({ L.Map.Welcome = L.Handler.extend({ _getLocalWelcomeUrl: function() { - var welcomeLocation = L.LOUtil.getURL('/welcome/welcome.html'); + var welcomeLocation = app.LOUtil.getURL('/welcome/welcome.html'); if (window.socketProxy) welcomeLocation = window.makeWsUrl(welcomeLocation); return welcomeLocation;