This is an automated email from the ASF dual-hosted git repository. solomax pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/openmeetings.git
The following commit(s) were added to refs/heads/master by this push: new fe90729 [OPENMEETINGS-2000] moving JS code to npm (more or less working) fe90729 is described below commit fe90729de51224ecd869f3a2cbdbee9f59c56c8f Author: Maxim Solodovnik <solomax...@gmail.com> AuthorDate: Sat Dec 26 18:45:56 2020 +0700 [OPENMEETINGS-2000] moving JS code to npm (more or less working) --- openmeetings-web/src/main/front/wb/package.json | 9 +- .../src/main/front/wb/src/raw-tool-math.js | 143 --------------------- .../src/main/front/wb/src/wb-tool-math.js | 101 +++++++++++++++ .../src/main/front/wb/src/wb-tool-stat-math.js | 86 +++++++++++++ openmeetings-web/src/main/front/wb/src/wb-tools.js | 12 +- openmeetings-web/src/main/front/wb/src/wb.js | 78 +++++------ 6 files changed, 240 insertions(+), 189 deletions(-) diff --git a/openmeetings-web/src/main/front/wb/package.json b/openmeetings-web/src/main/front/wb/package.json index 7f5b724..9b63ae5 100644 --- a/openmeetings-web/src/main/front/wb/package.json +++ b/openmeetings-web/src/main/front/wb/package.json @@ -4,8 +4,8 @@ "description": "Methods for WB", "main": "src/index.js", "scripts": { - "build-dev": "browserify src/index.js --transform-key=staging -o ${outDir}${npm_package_name}.js", - "build-prod": "browserify src/index.js --transform-key=production -p tinyify -o ${outDir}${npm_package_name}.min.js", + "build-dev": "browserify src/index.js --transform-key=staging -p esmify -o ${outDir}${npm_package_name}.js", + "build-prod": "browserify src/index.js --transform-key=production -p esmify | terser -o ${outDir}${npm_package_name}.min.js", "build": "npm run build-dev && npm run build-prod" }, "author": "", @@ -13,9 +13,12 @@ "rat-license": "Licensed under the Apache License, Version 2.0 (the \"License\") http://www.apache.org/licenses/LICENSE-2.0", "devDependencies": { "browserify": "^17.0.0", + "esmify": "^2.1.1", + "terser": "^5.5.1", "tinyify": "^3.0.0" }, "dependencies": { - "fabric": "^3.6.6" + "fabric": "^3.6.6", + "mathjax-full": "^3.1.2" } } diff --git a/openmeetings-web/src/main/front/wb/src/raw-tool-math.js b/openmeetings-web/src/main/front/wb/src/raw-tool-math.js deleted file mode 100644 index 4598eb4..0000000 --- a/openmeetings-web/src/main/front/wb/src/raw-tool-math.js +++ /dev/null @@ -1,143 +0,0 @@ -/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */ -var StaticTMath = (function() { - function tex2svg(tex, callback, _errCallback) { - const errCallback = _errCallback || function() {}; - let error = false; - const wrapper = $('<div>').html('\\[' + tex + '\\]'); - MathJax.Hub.Register.MessageHook('TeX Jax - parse error', function(message) { - errCallback(message[1]); - error = true; - }); - MathJax.Hub.Register.MessageHook('Math Processing Error', function(message) { - errCallback(message[2]); - error = true; - }); - MathJax.Hub.Queue(['Typeset', MathJax.Hub, wrapper[0]]); - MathJax.Hub.Queue(function() { - if (!error) { - const mjOut = wrapper[0].getElementsByTagName('svg')[0]; - callback(mjOut); - } - }); - } - function create(o, canvas, callback, errCallback) { - tex2svg(o.formula, function(svg) { - fabric.parseSVGDocument(svg, function(objects, options) { - const opts = $.extend({}, o, options) - , obj = objects.length === 1 - ? new fabric.Group(objects, opts) - : fabric.util.groupSVGElements(objects, opts); - obj.selectable = canvas.selection; - obj.type = 'group'; - if (typeof(callback) === 'function') { - callback(obj); - } - canvas.add(obj).requestRenderAll(); - }); - }, errCallback); - } - function highlight(el) { - el.addClass('ui-state-highlight', 2000, function() { - el.focus(); - el.removeClass('ui-state-highlight', 2000); - }); - } - - return { - tex2svg: tex2svg - , create: create - , highlight: highlight - } -})(); -var TMath = function(wb, s, sBtn) { - const math = ShapeBase(); - math.obj = null; - - function _enableUpdate(upd, obj) { - upd.data('uid', obj.uid); - upd.data('slide', obj.slide); - upd.button('enable'); - } - function _updateDisabled(cnvs) { - const canvas = cnvs || wb.getCanvas() - , ao = canvas.getActiveObject() - , fml = wb.getFormula() - , ta = fml.find('textarea') - , upd = fml.find('.update-btn'); - if (!!ao && ao.omType === 'Math') { - _enableUpdate(upd, ao); - ta.val(ao.formula); - return false; - } else { - upd.button('disable'); - return true; - } - } - math.mouseDown = function(o) { - const canvas = this - , pointer = canvas.getPointer(o.e) - , fml = wb.getFormula() - , ta = fml.find('textarea') - , upd = fml.find('.update-btn'); - fml.show(); - if (_updateDisabled(canvas)) { - const err = fml.find('.status'); - err.text(''); - if (ta.val().trim() === '') { - StaticTMath.highlight(ta); - return; - } - StaticTMath.create( - { - scaleX: 10 - , scaleY: 10 - , left: pointer.x - , top: pointer.y - , omType: 'Math' - , formula: ta.val() - } - , canvas - , function(obj) { - math.obj = obj; - math.objectCreated(math.obj, canvas); - if (wb.getRole() !== NONE) { - canvas.setActiveObject(math.obj); - } - _enableUpdate(upd, math.obj); - } - , function(msg) { - err.text(msg); - StaticTMath.highlight(err); - } - ); - } - }; - math.activate = function() { - wb.eachCanvas(function(canvas) { - canvas.on('mouse:down', math.mouseDown); - canvas.selection = true; - canvas.forEachObject(function(o) { - if (o.omType === 'Math') { - o.selectable = true; - } - }); - }); - _updateDisabled(); - ToolUtil.disableAllProps(s); - sBtn.addClass('disabled'); - }; - math.deactivate = function() { - wb.eachCanvas(function(canvas) { - canvas.off('mouse:down', math.mouseDown); - canvas.selection = false; - canvas.forEachObject(function(o) { - if (o.omType === 'Math') { - o.selectable = false; - } - }); - }); - wb.getFormula().find('.update-btn').button('disable'); - }; - - return math; -}; diff --git a/openmeetings-web/src/main/front/wb/src/wb-tool-math.js b/openmeetings-web/src/main/front/wb/src/wb-tool-math.js new file mode 100644 index 0000000..8e179c4 --- /dev/null +++ b/openmeetings-web/src/main/front/wb/src/wb-tool-math.js @@ -0,0 +1,101 @@ +/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */ +const WbShapeBase = require('./wb-tool-shape-base'); +const ToolUtil = require('./wb-tool-util'); +const Role = require('./wb-role'); +const StaticTMath = require('./wb-tool-stat-math'); + +module.exports = class TMath extends WbShapeBase { + static TYPE = 'Math'; + + constructor(wb, settings, sBtn) { + super(); + this.obj = null; + + const self = this; + function _enableUpdate(upd, obj) { + upd.data('uid', obj.uid); + upd.data('slide', obj.slide); + upd.button('enable'); + } + function _updateDisabled(cnvs) { + const canvas = cnvs || wb.getCanvas() + , ao = canvas.getActiveObject() + , fml = wb.getFormula() + , ta = fml.find('textarea') + , upd = fml.find('.update-btn'); + if (!!ao && ao.omType === TMath.TYPE) { + _enableUpdate(upd, ao); + ta.val(ao.formula); + return false; + } else { + upd.button('disable'); + return true; + } + } + function _mouseDown(o) { + const canvas = this + , pointer = canvas.getPointer(o.e) + , fml = wb.getFormula() + , ta = fml.find('textarea') + , upd = fml.find('.update-btn'); + fml.show(); + if (_updateDisabled(canvas)) { + const err = fml.find('.status'); + err.text(''); + if (ta.val().trim() === '') { + StaticTMath.highlight(ta); + return; + } + StaticTMath.create( + { + scaleX: 10 + , scaleY: 10 + , left: pointer.x + , top: pointer.y + , omType: TMath.TYPE + , formula: ta.val() + } + , canvas + , function(obj) { + self.obj = obj; + self.objectCreated.call(self, self.obj, canvas); + if (wb.getRole() !== Role.NONE) { + canvas.setActiveObject(self.obj); + } + _enableUpdate(upd, self.obj); + } + , function(msg) { + err.text(msg); + StaticTMath.highlight(err); + } + ); + } + } + this.activate = () => { + wb.eachCanvas(function(canvas) { + canvas.on('mouse:down', _mouseDown); + canvas.selection = true; + canvas.forEachObject(function(o) { + if (o.omType === TMath.TYPE) { + o.selectable = true; + } + }); + }); + _updateDisabled(); + ToolUtil.disableAllProps(settings); + sBtn.addClass('disabled'); + }; + this.deactivate = () => { + wb.eachCanvas(function(canvas) { + canvas.off('mouse:down', _mouseDown); + canvas.selection = false; + canvas.forEachObject(function(o) { + if (o.omType === TMath.TYPE) { + o.selectable = false; + } + }); + }); + wb.getFormula().find('.update-btn').button('disable'); + }; + } +}; diff --git a/openmeetings-web/src/main/front/wb/src/wb-tool-stat-math.js b/openmeetings-web/src/main/front/wb/src/wb-tool-stat-math.js new file mode 100644 index 0000000..30e5d80 --- /dev/null +++ b/openmeetings-web/src/main/front/wb/src/wb-tool-stat-math.js @@ -0,0 +1,86 @@ +/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */ +require('fabric'); + +// Based on this example: https://github.com/mathjax/MathJax-demos-node/blob/master/preload/tex2svg +const packages = 'base, autoload, require, ams, newcommand, noundefined'.split(/\s*,\s*/); + +MathJax = { + options: {} + , tex: { + packages: packages + , noundefined: { + color: 'red' + , background: '' + , size: '' + } + } + , svg: { + fontCache: 'local' + } + , startup: { + typeset: false + } +}; + +require('mathjax-full/components/src/startup/lib/startup.js'); +require('mathjax-full/components/src/core/core.js'); +require('mathjax-full/js/adaptors/browserAdaptor'); +require('mathjax-full/components/src/input/tex-base/tex-base.js'); +require('mathjax-full/components/src/input/tex/extensions/all-packages/all-packages.js'); +require('mathjax-full/components/src/input/tex/extensions/noundefined/noundefined'); +require('mathjax-full/components/src/output/svg/svg.js'); +require('mathjax-full/components/src/output/svg/fonts/tex/tex.js'); +require('mathjax-full/components/src/startup/startup.js'); + +MathJax.loader.preLoad( + 'core' + , 'adaptors/browserAdaptor' + , 'input/tex-base' + , '[tex]/all-packages' + , '[tex]/noundefined' + , 'output/svg' + , 'output/svg/fonts/tex' +); + +MathJax.config.startup.ready(); + +function _tex2svg(tex, callback, _errCallback) { + MathJax.tex2svgPromise(tex, { + display: false + , em: 16 // em-size in pixels + , ex: 8 // ex-size in pixels + , containerWidth: 80 * 16 + }).then(function (node) { + console.log(node); + callback(node.firstElementChild); + }).catch(function (err) { + console.error(err); + }); +} +function create(o, canvas, callback, errCallback) { + _tex2svg(o.formula, function(svg) { + fabric.parseSVGDocument(svg, function(objects, options) { + const opts = $.extend({}, o, options) + , obj = objects.length === 1 + ? new fabric.Group(objects, opts) + : fabric.util.groupSVGElements(objects, opts); + obj.selectable = canvas.selection; + obj.type = 'group'; + if (typeof(callback) === 'function') { + callback(obj); + } + canvas.add(obj).requestRenderAll(); + }); + }, errCallback); +} +function highlight(el) { + el.addClass('ui-state-highlight', 2000, function() { + el.focus(); + el.removeClass('ui-state-highlight', 2000); + }); +} + +module.exports = { + create: create + , highlight: highlight +}; diff --git a/openmeetings-web/src/main/front/wb/src/wb-tools.js b/openmeetings-web/src/main/front/wb/src/wb-tools.js index 01a7d08..abccb40 100644 --- a/openmeetings-web/src/main/front/wb/src/wb-tools.js +++ b/openmeetings-web/src/main/front/wb/src/wb-tools.js @@ -13,6 +13,8 @@ const Rect = require('./wb-tool-rect'); const Ellipse = require('./wb-tool-ellipse'); const Arrow = require('./wb-tool-arrow'); const Clipart = require('./wb-tool-clipart'); +const StaticTMath = require('./wb-tool-stat-math'); +const TMath = require('./wb-tool-math'); const ACTIVE = 'active'; @@ -247,16 +249,16 @@ module.exports = class WbTools { math.hide(); }); math.find('.update-btn').button().click(function() { - const o = _findObject({ + const o = wb._findObject({ uid: $(this).data('uid') , slide: $(this).data('slide') }); - const json = toOmJson(o); + const json = wb._toOmJson(o); json.formula = math.find('textarea').val(); - const cnvs = canvases[o.slide]; + const cnvs = wb.getCanvas(o.slide); StaticTMath.create(json, cnvs , function(obj) { - _removeHandler(o); + wb.removeObj([o]); cnvs.fire('object:modified', {target: obj}); } , function(msg) { @@ -332,7 +334,7 @@ module.exports = class WbTools { _firstToolItem = false; _initTexts(sBtn); _initDrawings(sBtn); - // FIXME TODO _initToolBtn('math', _firstToolItem, TMath(wb, settings, sBtn)); + _initToolBtn('math', _firstToolItem, new TMath(wb, settings, sBtn)); _initCliparts(sBtn); tools.find('.om-icon.settings').click(function() { settings.show(); diff --git a/openmeetings-web/src/main/front/wb/src/wb.js b/openmeetings-web/src/main/front/wb/src/wb.js index 3ea1992..b065bd4 100644 --- a/openmeetings-web/src/main/front/wb/src/wb.js +++ b/openmeetings-web/src/main/front/wb/src/wb.js @@ -4,6 +4,8 @@ const WbTools = require('./wb-tools'); const WbZoom = require('./wb-zoom'); const APointer = require('./wb-tool-apointer'); const Player = require('./wb-player'); +const TMath = require('./wb-tool-math'); +const StaticTMath = require('./wb-tool-stat-math'); require('fabric'); // will produce `fabric` namespace const BUMPER = 100 @@ -22,21 +24,8 @@ module.exports = class Wb { let wbEl, tools, zoomBar , role = null, scrollTimeout = null; - function _findObject(o) { - let _o = null; - const cnvs = canvases[o.slide]; - if (!!cnvs) { - cnvs.forEachObject(function(__o) { - if (!!__o && o.uid === __o.uid) { - _o = __o; - return false; - } - }); - } - return _o; - } function _removeHandler(o) { - const __o = _findObject(o); + const __o = self._findObject(o); if (!!__o) { const cnvs = canvases[o.slide]; if (!!cnvs) { @@ -116,20 +105,6 @@ module.exports = class Wb { }); } - function toOmJson(o) { - const r = o.toJSON(extraProps); - switch (o.omType) { - case 'Video': - delete r.objects; - break; - case 'Math': - delete r.objects; - break; - default: - //no-op - } - return r; - } //events function objCreatedHandler(o) { if (role === Role.NONE && o.omType !== 'pointer') { @@ -142,7 +117,7 @@ module.exports = class Wb { break; default: o.includeDefaultValues = false; - json = toOmJson(o); + json = self._toOmJson(o); break; } OmUtil.wbAction({action: 'createObj', data: { @@ -179,11 +154,11 @@ module.exports = class Wb { _o.includeDefaultValues = false; const _items = _o.destroy().getObjects(); for (let i = 0; i < _items.length; ++i) { - items.push(toOmJson(_items[i])); + items.push(self._toOmJson(_items[i])); } }, extraProps); } else { - items.push(toOmJson(o)); + items.push(self._toOmJson(o)); } OmUtil.wbAction({action: 'modifyObj', data: { wbId: self.id @@ -307,12 +282,39 @@ module.exports = class Wb { self._doSetSlide(self.slide); } function _videoStatus(json) { - const g = _findObject(json); + const g = self._findObject(json); if (!!g) { g.videoStatus(json.status); } } + this._toOmJson = (o) => { + const r = o.toJSON(extraProps); + switch (o.omType) { + case 'Video': + delete r.objects; + break; + case TMath.TYPE: + delete r.objects; + break; + default: + //no-op + } + return r; + }; + this._findObject = (o) => { + let _o = null; + const cnvs = canvases[o.slide]; + if (!!cnvs) { + cnvs.forEachObject(function(__o) { + if (!!__o && o.uid === __o.uid) { + _o = __o; + return false; + } + }); + } + return _o; + }; this.setRole = (_role) => { if (role !== _role) { role = _role; @@ -397,12 +399,12 @@ module.exports = class Wb { case 'Video': Player.create(canvases[o.slide], o, self); break; - case 'Math': + case TMath.TYPE: StaticTMath.create(o, canvases[o.slide]); break; default: { - const __o = _findObject(o); + const __o = self._findObject(o); if (!__o) { arr.push(o); } @@ -429,13 +431,13 @@ module.exports = class Wb { break; case 'Video': { - const g = _findObject(o); + const g = self._findObject(o); if (!!g) { Player.modify(g, o); } } break; - case 'Math': + case TMath.TYPE: { _removeHandler(o); StaticTMath.create(o, canvases[o.slide]); @@ -480,8 +482,8 @@ module.exports = class Wb { canvas.requestRenderAll(); } }; - this.getCanvas = () => { - return canvases[self.slide]; + this.getCanvas = (_slide) => { + return canvases[typeof(_slide) === 'number' ? _slide : self.slide]; }; this.eachCanvas = (func) => { for (let i = 0; i < canvases.length; ++i) {