From c8fd2fac372238c86a79f615d51f603cdb762d98 Mon Sep 17 00:00:00 2001 From: Hadi Nategh Date: Thu, 31 Mar 2022 14:40:12 +0200 Subject: [PATCH] Add multi-video and pdf-player components --- .../CustomHtmlElements/multi-video.js | 374 ++++++++++++++++++ .../CustomHtmlElements/multi-video.ts | 16 +- .../CustomHtmlElements/pdf-player.js | 367 +++++++++++++++++ api/js/etemplate/et2_widget_vfs.js | 15 +- api/js/etemplate/et2_widget_vfs.ts | 16 +- api/js/etemplate/et2_widget_video.js | 11 +- api/js/etemplate/et2_widget_video.ts | 11 +- package-lock.json | 13 + package.json | 1 + 9 files changed, 811 insertions(+), 13 deletions(-) create mode 100644 api/js/etemplate/CustomHtmlElements/multi-video.js create mode 100644 api/js/etemplate/CustomHtmlElements/pdf-player.js diff --git a/api/js/etemplate/CustomHtmlElements/multi-video.js b/api/js/etemplate/CustomHtmlElements/multi-video.js new file mode 100644 index 0000000000..2d24542fff --- /dev/null +++ b/api/js/etemplate/CustomHtmlElements/multi-video.js @@ -0,0 +1,374 @@ +/** + * EGroupware Custom Html Elements - Multi Video Web Components + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link https://www.egroupware.org + * @author Hadi Nategh + * @copyright EGroupware GmbH + */ +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +// Create a class for the element +var multi_video = /** @class */ (function (_super) { + __extends(multi_video, _super); + function multi_video() { + var _this = _super.call(this) || this; + /** + * shadow dom container + * @private + */ + _this._shadow = null; + /** + * contains video objects of type VideoTagsArray + * @private + */ + _this._videos = []; + /** + * keeps duration time internally + * @private + */ + _this._duration = 0; + /** + * keeps currentTime internally + * @private + */ + _this._currentTime = 0; + /** + * Keeps video playing state internally + * @private + */ + _this.__playing = false; + // Create a shadow root + _this._shadow = _this.attachShadow({ mode: 'open' }); + // Create videos wrapper + _this._wrapper = document.createElement('div'); + _this._wrapper.setAttribute('class', 'wrapper'); + // Create some CSS to apply to the shadow dom + _this._style = document.createElement('style'); + _this._style.textContent = '.wrapper {' + + 'width: 100%;' + + 'height: auto;' + + 'display: block;' + + '}' + + '.wrapper video {' + + 'width: 100%;' + + 'height: auto;' + + '}'; + // attach to the shadow dom + _this._shadow.appendChild(_this._style); + _this._shadow.appendChild(_this._wrapper); + return _this; + } + Object.defineProperty(multi_video, "observedAttributes", { + /** + * set observable attributes + * @return {string[]} + */ + get: function () { + return ['src', 'type']; + }, + enumerable: false, + configurable: true + }); + /** + * Gets called on observable attributes changes + * @param name attribute name + * @param _ + * @param newVal new value + */ + multi_video.prototype.attributeChangedCallback = function (name, _, newVal) { + switch (name) { + case 'src': + this.__buildVideoTags(newVal); + break; + case 'type': + this._videos.forEach(function (_item) { + _item.node.setAttribute('type', newVal); + }); + break; + } + }; + /** + * init/update video tags + * @param _value + * @private + */ + multi_video.prototype.__buildVideoTags = function (_value) { + var value = _value.split(','); + var video = null; + var _loop_1 = function (i) { + video = document.createElement('video'); + video.src = value[i]; + this_1._videos[i] = { + node: this_1._wrapper.appendChild(video), + loadedmetadata: false, + timeupdate: false, + duration: 0, + previousDurations: 0, + currentTime: 0, + active: false, + index: i + }; + // loadmetadata event + this_1._videos[i]['node'].addEventListener("loadedmetadata", function (_i, _event) { + this._videos[_i]['loadedmetadata'] = true; + this.__check_loadedmetadata(); + }.bind(this_1, i)); + //timeupdate event + this_1._videos[i]['node'].addEventListener("timeupdate", function (_i, _event) { + this._currentTime = this._videos[i]['previousDurations'] + _event.target.currentTime; + // push the next video to start otherwise the time update gets paused as it ends automatically + // with the current video being ended + if (this._videos[i].node.ended && !this.ended) + this.currentTime = this._currentTime + 0.1; + this.__pushEvent('timeupdate'); + }.bind(this_1, i)); + }; + var this_1 = this; + for (var i = 0; i < value.length; i++) { + _loop_1(i); + } + }; + /** + * calculates duration of videos + * @return {number} returns accumulated durations + * @private + */ + multi_video.prototype.__duration = function () { + var duration = 0; + this._videos.forEach(function (_item) { + duration += _item.duration; + }); + return duration; + }; + /** + * Get current active video + * @return {*[]} returns an array of object consist of current video displayed node + * @private + */ + multi_video.prototype.__getActiveVideo = function () { + return this._videos.filter(function (_item) { + return (_item.active); + }); + }; + /** + * check if all meta data from videos are ready then pushes the event + * @private + */ + multi_video.prototype.__check_loadedmetadata = function () { + var _this = this; + var allReady = true; + this._videos.forEach(function (_item) { + allReady = allReady && _item.loadedmetadata; + }); + if (allReady) { + this._videos.forEach(function (_item) { + _item.duration = _item.node.duration; + _item.previousDurations = _item.index > 0 ? _this._videos[_item.index - 1]['duration'] + _this._videos[_item.index - 1]['previousDurations'] : 0; + }); + this.duration = this.__duration(); + this.currentTime = 0; + this.__pushEvent('loadedmetadata'); + } + }; + /** + * Creates event and dispatches it + * @param _name + */ + multi_video.prototype.__pushEvent = function (_name) { + var event = document.createEvent("Event"); + event.initEvent(_name, true, true); + this.dispatchEvent(event); + }; + Object.defineProperty(multi_video.prototype, "src", { + /** + * get src + * @return string returns comma separated sources + */ + get: function () { + return this.src; + }, + /**************************** PUBLIC ATTRIBUTES & METHODES *************************************************/ + /****************************** ATTRIBUTES **************************************/ + /** + * set src + * @param _value + */ + set: function (_value) { + var value = _value.split(','); + this._wrapper.children.forEach(function (_ch) { + _ch.remove(); + }); + this.__buildVideoTags(value); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(multi_video.prototype, "currentTime", { + /** + * get currentTime + * @return {number} + */ + get: function () { + return this._currentTime; + }, + /** + * currentTime + * @param _time + */ + set: function (_time) { + var _this = this; + var ctime = _time; + this._currentTime = _time; + this._videos.forEach(function (_item) { + if ((ctime < _item.duration + _item.previousDurations) + && ((ctime == 0 && _item.previousDurations == 0) || ctime > _item.previousDurations)) { + if (_this.__playing && _item.node.paused) + _item.node.play(); + _item.currentTime = Math.abs(_item.previousDurations - ctime); + _item.node.currentTime = _item.currentTime; + _item.active = true; + } + else { + _item.active = false; + _item.node.pause(); + } + _item.node.hidden = !_item.active; + }); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(multi_video.prototype, "duration", { + /** + * get video duration time + */ + get: function () { + return this._duration; + }, + /** + * set video duration time attribute + * @param _value + */ + set: function (_value) { + this._duration = _value; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(multi_video.prototype, "paused", { + /** + * get paused attribute + */ + get: function () { + var _a, _b; + return (_b = (_a = this.__getActiveVideo()[0]) === null || _a === void 0 ? void 0 : _a.node) === null || _b === void 0 ? void 0 : _b.paused; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(multi_video.prototype, "muted", { + /** + * get muted attribute + */ + get: function () { + var _a, _b; + return (_b = (_a = this.__getActiveVideo()[0]) === null || _a === void 0 ? void 0 : _a.node) === null || _b === void 0 ? void 0 : _b.muted; + }, + /** + * set muted attribute + * @param _value + */ + set: function (_value) { + this._videos.forEach(function (_item) { + _item.node.muted = _value; + }); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(multi_video.prototype, "ended", { + /** + * get video ended attribute + */ + get: function () { + var _a, _b; + return (_b = (_a = this._videos[this._videos.length - 1]) === null || _a === void 0 ? void 0 : _a.node) === null || _b === void 0 ? void 0 : _b.ended; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(multi_video.prototype, "playbackRate", { + /** + * get playbackRate + */ + get: function () { + var _a, _b; + return (_b = (_a = this.__getActiveVideo()[0]) === null || _a === void 0 ? void 0 : _a.node) === null || _b === void 0 ? void 0 : _b.playbackRate; + }, + /** + * set playbackRate + * @param _value + */ + set: function (_value) { + this._videos.forEach(function (_item) { + _item.node.playbackRate = _value; + }); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(multi_video.prototype, "volume", { + /** + * get volume + */ + get: function () { + var _a, _b; + return (_b = (_a = this.__getActiveVideo()[0]) === null || _a === void 0 ? void 0 : _a.node) === null || _b === void 0 ? void 0 : _b.volume; + }, + /** + * set volume + */ + set: function (_value) { + this._videos.forEach(function (_item) { + _item.node.volume = _value; + }); + }, + enumerable: false, + configurable: true + }); + /************************************************* METHODES ******************************************/ + /** + * Play video + */ + multi_video.prototype.play = function () { + var _a, _b; + this.__playing = true; + return (_b = (_a = this.__getActiveVideo()[0]) === null || _a === void 0 ? void 0 : _a.node) === null || _b === void 0 ? void 0 : _b.play(); + }; + /** + * pause video + */ + multi_video.prototype.pause = function () { + var _a, _b; + this.__playing = false; + (_b = (_a = this.__getActiveVideo()[0]) === null || _a === void 0 ? void 0 : _a.node) === null || _b === void 0 ? void 0 : _b.pause(); + }; + return multi_video; +}(HTMLElement)); +// Define the new multi-video element +customElements.define('multi-video', multi_video); +//# sourceMappingURL=multi-video.js.map \ No newline at end of file diff --git a/api/js/etemplate/CustomHtmlElements/multi-video.ts b/api/js/etemplate/CustomHtmlElements/multi-video.ts index cf5d4b03da..7b1f96eee8 100644 --- a/api/js/etemplate/CustomHtmlElements/multi-video.ts +++ b/api/js/etemplate/CustomHtmlElements/multi-video.ts @@ -304,7 +304,7 @@ class multi_video extends HTMLElement { */ get paused() { - return this.__getActiveVideo()[0].node.paused; + return this.__getActiveVideo()[0]?.node?.paused; } /** @@ -323,7 +323,7 @@ class multi_video extends HTMLElement { */ get muted() { - return this.__getActiveVideo()[0].node.muted; + return this.__getActiveVideo()[0]?.node?.muted; } /** @@ -331,7 +331,7 @@ class multi_video extends HTMLElement { */ get ended() { - return this._videos[this._videos.length-1].node.ended; + return this._videos[this._videos.length-1]?.node?.ended; } /** @@ -350,7 +350,7 @@ class multi_video extends HTMLElement { */ get playbackRate() { - return this.__getActiveVideo()[0].node.playbackRate; + return this.__getActiveVideo()[0]?.node?.playbackRate; } /** @@ -368,7 +368,7 @@ class multi_video extends HTMLElement { */ get volume() { - return this.__getActiveVideo()[0].node.volume; + return this.__getActiveVideo()[0]?.node?.volume; } @@ -380,7 +380,7 @@ class multi_video extends HTMLElement { play() { this.__playing = true; - return this.__getActiveVideo()[0].node.play(); + return this.__getActiveVideo()[0]?.node?.play(); } /** @@ -389,9 +389,9 @@ class multi_video extends HTMLElement { pause() { this.__playing = false; - this.__getActiveVideo()[0].node.pause(); + this.__getActiveVideo()[0]?.node?.pause(); } } // Define the new multi-video element -customElements.define('multi-video', multi_video); \ No newline at end of file +customElements.define('multi-video', multi_video); diff --git a/api/js/etemplate/CustomHtmlElements/pdf-player.js b/api/js/etemplate/CustomHtmlElements/pdf-player.js new file mode 100644 index 0000000000..fd9e3afe23 --- /dev/null +++ b/api/js/etemplate/CustomHtmlElements/pdf-player.js @@ -0,0 +1,367 @@ +"use strict"; +/** + * EGroupware Custom Html Elements - pdf player Web Components + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package etemplate + * @subpackage api + * @link https://www.egroupware.org + * @author Hadi Nategh + * @copyright EGroupware GmbH + */ +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +/*egw:uses + /node_modules/@bundled-es-modules/pdfjs-dist/build/pdf.js; + /node_modules/@bundled-es-modules/pdfjs-dist/build/pdf.worker.js; + +*/ +var pdf_1 = require("@bundled-es-modules/pdfjs-dist/build/pdf"); +/* + This web component allows to display and play pdf file like a video player widget/element. Its attributes and + methodes are mostley identical as video html. No controls attribute supported yet. +*/ +pdf_1.default.GlobalWorkerOptions.workerSrc = 'node_modules/@bundled-es-modules/pdfjs-dist/build/pdf.worker.js'; +// Create a class for the element +var pdf_player = /** @class */ (function (_super) { + __extends(pdf_player, _super); + function pdf_player() { + var _this = _super.call(this) || this; + /** + * shadow dom container + * @private + */ + _this._shadow = null; + /** + * keeps duration time internally + * @private + */ + _this._duration = 0; + /** + * keeps currentTime internally + * @private + */ + _this._currentTime = 0; + /** + * Keeps playing state internally + * @private + */ + _this.__playing = false; + /** + * keeps playing interval id + * @private + */ + _this.__playingInterval = 0; + /** + * keeps play back rate + * @private + */ + _this._playBackRate = 1000; + /** + * keeps ended state of playing pdf + * @private + */ + _this._ended = false; + /** + * keep paused state + * @private + */ + _this._paused = false; + /** + * keeps pdf doc states + * @private + */ + _this.__pdfViewState = { + pdf: null, + currentPage: 1, + zoom: 1 + }; + // Create a shadow root + _this._shadow = _this.attachShadow({ mode: 'open' }); + // Create wrapper + _this._wrapper = document.createElement('div'); + _this._wrapper.setAttribute('class', 'wrapper'); + // Create some CSS to apply to the shadow dom + _this._style = document.createElement('style'); + _this._style.textContent = '.wrapper {' + + 'width: 100%;' + + 'height: auto;' + + 'display: block;' + + '}' + + '.wrapper canvas {' + + 'width: 100%;' + + 'height: auto;' + + '}'; + // attach to the shadow dom + _this._shadow.appendChild(_this._style); + _this._shadow.appendChild(_this._wrapper); + return _this; + } + Object.defineProperty(pdf_player, "observedAttributes", { + /** + * set observable attributes + * @return {string[]} + */ + get: function () { + return ['src', 'type']; + }, + enumerable: false, + configurable: true + }); + /** + * Gets called on observable attributes changes + * @param name attribute name + * @param _ + * @param newVal new value + */ + pdf_player.prototype.attributeChangedCallback = function (name, _, newVal) { + switch (name) { + case 'src': + this.__buildPDFView(newVal); + break; + case 'type': + // do nothing + break; + } + }; + /** + * init/update pdf tag + * @param _value + * @private + */ + pdf_player.prototype.__buildPDFView = function (_value) { + var _this = this; + this._canvas = document.createElement('canvas'); + this._wrapper.appendChild(this._canvas); + var longTask = pdf_1.default.getDocument(_value); + longTask.promise.then(function (pdf) { + _this.__pdfViewState.pdf = pdf; + _this._duration = _this.__pdfViewState.pdf._pdfInfo.numPages; + // initiate the pdf file viewer for the first time after loading + _this.__render(1).then(function (_) { + _this.__pushEvent('loadedmetadata'); + }); + }); + }; + /** + * Render given page from pdf into the canvas container + * + * @param _page + * @private + */ + pdf_player.prototype.__render = function (_page) { + if (!this.__pdfViewState.pdf) + return; + var p = _page || this.__pdfViewState.currentPage; + var self = this; + return this.__pdfViewState.pdf.getPage(p).then(function (page) { + var canvasContext = self._canvas.getContext('2d'); + var viewport = page.getViewport({ scale: self.__pdfViewState.zoom }); + self._canvas.width = viewport.width; + self._canvas.height = viewport.height; + page.render({ + canvasContext: canvasContext, + viewport: viewport + }); + }); + }; + /** + * Creates event and dispatches it + * @param _name + */ + pdf_player.prototype.__pushEvent = function (_name) { + var event = document.createEvent("Event"); + event.initEvent(_name, true, true); + this.dispatchEvent(event); + }; + Object.defineProperty(pdf_player.prototype, "src", { + /** + * get src + * @return string returns comma separated sources + */ + get: function () { + return this.src; + }, + /**************************** PUBLIC ATTRIBUTES & METHODES *************************************************/ + /****************************** ATTRIBUTES **************************************/ + /** + * set src + * @param _value + */ + set: function (_value) { + this._wrapper.children.forEach(function (_ch) { + _ch.remove(); + }); + this.__buildPDFView(_value); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(pdf_player.prototype, "currentTime", { + /** + * get currentTime + * @return {number} + */ + get: function () { + return this._currentTime; + }, + /** + * currentTime + * @param _time + */ + set: function (_time) { + var time = Math.floor(_time < 1 ? 1 : _time); + if (time > this._duration) { + // set ended state to true as it's the last page of pdf + this._ended = true; + // don't go further because it's litterally the last page + return; + } + // set ended state to false as it's not the end of the pdf + this._ended = false; + this._currentTime = time; + this.__pdfViewState.currentPage = time; + this.__render(time); + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(pdf_player.prototype, "duration", { + /** + * get duration time + */ + get: function () { + return this._duration; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(pdf_player.prototype, "paused", { + /** + * get paused attribute + */ + get: function () { + return this._paused; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(pdf_player.prototype, "muted", { + /** + * get muted attribute + */ + get: function () { + return true; + }, + /** + * set muted attribute + * @param _value + */ + set: function (_value) { + return; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(pdf_player.prototype, "ended", { + /** + * get ended attribute + */ + get: function () { + return this._ended; + }, + set: function (_value) { + this._ended = _value; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(pdf_player.prototype, "playbackRate", { + /** + * get playbackRate + */ + get: function () { + return this._playBackRate; + }, + /** + * set playbackRate + * @param _value + */ + set: function (_value) { + this._playBackRate = _value * 1000; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(pdf_player.prototype, "volume", { + /** + * get volume + */ + get: function () { + return 0; + }, + /** + * set volume + */ + set: function (_value) { + return; + }, + enumerable: false, + configurable: true + }); + /************************************************* METHODES ******************************************/ + /** + * Play + */ + pdf_player.prototype.play = function () { + this.__playing = true; + var self = this; + return new Promise(function (_resolve, _reject) { + self.__playingInterval = window.setInterval(function (_) { + if (self.currentTime >= self._duration) { + self.ended = true; + self.pause(); + } + self.currentTime += 1; + self.__pushEvent('timeupdate'); + }, self._playBackRate); + _resolve(); + }); + }; + /** + * pause + */ + pdf_player.prototype.pause = function () { + this.__playing = false; + this._paused = true; + window.clearInterval(this.__playingInterval); + }; + /** + * seek previous page + */ + pdf_player.prototype.prevPage = function () { + this.currentTime -= 1; + }; + /** + * seek next page + */ + pdf_player.prototype.nextPage = function () { + this.currentTime += 1; + }; + return pdf_player; +}(HTMLElement)); +// Define pdf-player element +customElements.define('pdf-player', pdf_player); +//# sourceMappingURL=pdf-player.js.map \ No newline at end of file diff --git a/api/js/etemplate/et2_widget_vfs.js b/api/js/etemplate/et2_widget_vfs.js index a0decf20a1..139b2115fc 100644 --- a/api/js/etemplate/et2_widget_vfs.js +++ b/api/js/etemplate/et2_widget_vfs.js @@ -24,7 +24,7 @@ var __extends = (this && this.__extends) || (function () { })(); var _a; Object.defineProperty(exports, "__esModule", { value: true }); -exports.et2_vfsSelect = exports.et2_vfsPath = exports.et2_vfs = void 0; +exports.et2_vfsSelect = exports.et2_vfsUpload = exports.et2_vfsMime = exports.et2_vfsPath = exports.et2_vfs = void 0; /*egw:uses /vendor/bower-asset/jquery/dist/jquery.js; vfsSelectUI; @@ -620,6 +620,7 @@ var et2_vfsMime = /** @class */ (function (_super) { }, _a.legacyOptions = ["size"], _a)))); +exports.et2_vfsMime = et2_vfsMime; ; et2_core_widget_1.et2_register_widget(et2_vfsMime, ["vfs-mime"]); /** @@ -839,6 +840,11 @@ var et2_vfsUpload = /** @class */ (function (_super) { _this.set_multiple(true); } _this.list = jQuery(document.createElement('table')).appendTo(_this.node); + if (_this.options.listonly) { + _this.input.remove(); + _this.span.remove(); + _this.progress.remove(); + } return _this; } /** @@ -1011,11 +1017,18 @@ var et2_vfsUpload = /** @class */ (function (_super) { "description": "Upload files to the specified VFS path", "type": "string", "default": '' + }, + "listonly": { + "name": "List Only", + "description": "Display given file objects only as list (removes span,input and progress from the dom)", + "type": "boolean", + "default": false } }; et2_vfsUpload.legacyOptions = ["mime"]; return et2_vfsUpload; }(et2_widget_file_1.et2_file)); +exports.et2_vfsUpload = et2_vfsUpload; et2_core_widget_1.et2_register_widget(et2_vfsUpload, ["vfs-upload"]); var et2_vfsSelect = /** @class */ (function (_super) { __extends(et2_vfsSelect, _super); diff --git a/api/js/etemplate/et2_widget_vfs.ts b/api/js/etemplate/et2_widget_vfs.ts index 83578bcece..276a347e25 100644 --- a/api/js/etemplate/et2_widget_vfs.ts +++ b/api/js/etemplate/et2_widget_vfs.ts @@ -484,7 +484,7 @@ et2_register_widget(et2_vfsName_ro, ["vfs-name_ro"]); * span.overlayContainer is optional and only generated for symlinks * @augments et2_valueWidget */ -class et2_vfsMime extends expose(class et2_vfsMime extends et2_valueWidget implements et2_IDetachedDOM, et2_IExposable +export class et2_vfsMime extends expose(class et2_vfsMime extends et2_valueWidget implements et2_IDetachedDOM, et2_IExposable { static readonly _attributes : any = { "value": { @@ -918,7 +918,7 @@ et2_register_widget(et2_vfsUid, ["vfs-uid","vfs-gid"]); * * @augments et2_file */ -class et2_vfsUpload extends et2_file +export class et2_vfsUpload extends et2_file { static readonly _attributes : any = { "value": { @@ -929,6 +929,12 @@ class et2_vfsUpload extends et2_file "description": "Upload files to the specified VFS path", "type": "string", "default": '' + }, + "listonly": { + "name": "List Only", + "description": "Display given file objects only as list (removes span,input and progress from the dom)", + "type": "boolean", + "default": false } }; @@ -960,6 +966,12 @@ class et2_vfsUpload extends et2_file this.set_multiple(true); } this.list = jQuery(document.createElement('table')).appendTo(this.node); + if (this.options.listonly) + { + this.input.remove(); + this.span.remove(); + this.progress.remove(); + } } /** diff --git a/api/js/etemplate/et2_widget_video.js b/api/js/etemplate/et2_widget_video.js index bb1d6ccffb..6b597a6051 100644 --- a/api/js/etemplate/et2_widget_video.js +++ b/api/js/etemplate/et2_widget_video.js @@ -29,6 +29,8 @@ exports.et2_video = void 0; /vendor/bower-asset/jquery/dist/jquery.js; et2_core_interfaces; et2_core_baseWidget; + /api/js/etemplate/CustomHtmlElements/multi-video.js; + /api/js/etemplate/CustomHtmlElements/pdf-player.js; */ var et2_core_baseWidget_1 = require("./et2_core_baseWidget"); var et2_core_inheritance_1 = require("./et2_core_inheritance"); @@ -80,7 +82,8 @@ var et2_video = /** @class */ (function (_super) { return; } //Create Video tag - this.video = jQuery(document.createElement(this._isYoutube() ? "div" : "video")) + this.video = jQuery(document.createElement(this._isYoutube() ? "div" : + (_type.match('pdf') ? "pdf-player" : (this.options.multi_src ? 'multi-video' : 'video')))) .addClass('et2_video') .attr('id', this.dom_id); if (this._isYoutube()) { @@ -493,6 +496,12 @@ var et2_video = /** @class */ (function (_super) { "type": "string", "description": "Defines the type the stream source provided" }, + "multi_src": { + "name": "Multi Video source", + "type": "boolean", + "default": false, + "description": "creates a multi-video tag in order to render all provided video sources" + }, "muted": { "name": "Audio control", "type": "boolean", diff --git a/api/js/etemplate/et2_widget_video.ts b/api/js/etemplate/et2_widget_video.ts index 4b9d078b29..aebf65911c 100644 --- a/api/js/etemplate/et2_widget_video.ts +++ b/api/js/etemplate/et2_widget_video.ts @@ -14,6 +14,8 @@ /vendor/bower-asset/jquery/dist/jquery.js; et2_core_interfaces; et2_core_baseWidget; + /api/js/etemplate/CustomHtmlElements/multi-video.js; + /api/js/etemplate/CustomHtmlElements/pdf-player.js; */ import { et2_baseWidget } from './et2_core_baseWidget' @@ -61,6 +63,12 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode "type": "string", "description": "Defines the type the stream source provided" }, + "multi_src": { + "name": "Multi Video source", + "type": "boolean", + "default": false, + "description": "creates a multi-video tag in order to render all provided video sources" + }, "muted": { "name": "Audio control", "type": "boolean", @@ -167,7 +175,8 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode return; } //Create Video tag - this.video = jQuery(document.createElement(this._isYoutube()?"div":"video")) + this.video = jQuery(document.createElement(this._isYoutube() ? "div" : + (_type.match('pdf') ? "pdf-player" : (this.options.multi_src ? 'multi-video' : 'video' )))) .addClass('et2_video') .attr('id', this.dom_id); diff --git a/package-lock.json b/package-lock.json index 721aeadede..89c7c15715 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "21.1.20210316", "license": "GPL-2.0", "devDependencies": { + "@bundled-es-modules/pdfjs-dist": "^2.5.207-rc1", "@types/jquery": "^3.5.5", "@types/jqueryui": "^1.12.14", "grunt": "^1.3.0", @@ -19,6 +20,12 @@ "typescript": "^3.9.7" } }, + "node_modules/@bundled-es-modules/pdfjs-dist": { + "version": "2.5.207-rc1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/pdfjs-dist/-/pdfjs-dist-2.5.207-rc1.tgz", + "integrity": "sha512-e/UVP1g6dwjQLnu4MPf/mlESCIvyr/KgpoMUyxGcv4evCIuJwKR/fcfhG3p1NYo+49gJsd0hL2yz9kzhkCZ32A==", + "dev": true + }, "node_modules/@types/jquery": { "version": "3.5.5", "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.5.tgz", @@ -2642,6 +2649,12 @@ } }, "dependencies": { + "@bundled-es-modules/pdfjs-dist": { + "version": "2.5.207-rc1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/pdfjs-dist/-/pdfjs-dist-2.5.207-rc1.tgz", + "integrity": "sha512-e/UVP1g6dwjQLnu4MPf/mlESCIvyr/KgpoMUyxGcv4evCIuJwKR/fcfhG3p1NYo+49gJsd0hL2yz9kzhkCZ32A==", + "dev": true + }, "@types/jquery": { "version": "3.5.5", "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.5.tgz", diff --git a/package.json b/package.json index 8817b53c0a..a72a571a1a 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "devDependencies": { "@types/jquery": "^3.5.5", "@types/jqueryui": "^1.12.14", + "@bundled-es-modules/pdfjs-dist": "^2.5.207-rc1", "grunt": "^1.3.0", "grunt-contrib-cssmin": "^2.2.1", "grunt-newer": "^1.3.0",