--- a/src/js/widgets-container/widget.js Sun Nov 12 22:07:33 2017 +0100
+++ b/src/js/widgets-container/widget.js Wed Sep 04 17:32:50 2024 +0200
@@ -1,8 +1,6 @@
/* widgetsDefinition of an ancestor for the Widget classes */
-
-if (typeof IriSP.Widgets === "undefined") {
- IriSP.Widgets = {};
-}
+import Mustache from "mustache";
+import jQuery from "jquery";
/**
* @class IriSP.Widget is an "abstract" class. It's mostly used to define some properties common to every widget.
@@ -13,273 +11,333 @@
* @constructor
* @param player - a reference to the player widget
* @param config - configuration options for the widget
+ *
*/
+import _ from "lodash";
-IriSP.Widgets.Widget = function(player, config) {
+export default function (IriSP) {
+ const Widgets = {};
+
+ Widgets.Widget = class {
+
+ static defaults = {};
- if( typeof player === "undefined") {
+ static template = "";
+
+ static messages = { en: {} };
+
+ constructor(player, config) {
+ if (typeof player === "undefined") {
/* Probably an abstract call of the class when
* individual widgets set their prototype */
return;
- }
+ }
- this.__subwidgets = [];
+ this.__subwidgets = [];
- /* Setting all the configuration options */
- var _type = config.type || "(unknown)",
- _config = IriSP._.defaults({}, config, (player && player.config ? player.config.default_options : {}), this.defaults),
+ /* Setting all the configuration options */
+ var _type = config.type || "(unknown)",
+ _config = _.defaults(
+ {},
+ config,
+ player && player.config ? player.config.default_options : {},
+ this.constructor.defaults
+ ),
_this = this;
- IriSP._(_config).forEach(function(_value, _key) {
- _this[_key] = _value;
- });
+ _(_config).forEach(function (_value, _key) {
+ _this[_key] = _value;
+ });
- this.$ = IriSP.jQuery('#' + this.container);
+ this.$ = jQuery("#" + this.container);
- if (typeof this.width === "undefined") {
+ if (typeof this.width === "undefined") {
this.width = this.$.width();
- } else {
+ } else {
this.$.css("width", this.width);
- }
+ }
- if (typeof this.height !== "undefined") {
+ if (typeof this.height !== "undefined") {
this.$.css("height", this.height);
- }
+ }
- /* Setting this.player at the end in case it's been overriden
- * by a configuration option of the same name :-(
- */
- this.player = player || new IriSP.FakeClass(["on","trigger","off","loadWidget","loadMetadata"]);
+ /* Setting this.player at the end in case it's been overriden
+ * by a configuration option of the same name :-(
+ */
+ this.player =
+ player ||
+ new IriSP.FakeClass([
+ "on",
+ "trigger",
+ "off",
+ "loadWidget",
+ "loadMetadata",
+ ]);
- /* Adding classes and html attributes */
- this.$.addClass("Ldt-TraceMe Ldt-Widget").attr("widget-type", _type);
+ /* Adding classes and html attributes */
+ this.$.addClass("Ldt-TraceMe Ldt-Widget").attr("widget-type", _type);
- this.l10n = (
- typeof this.messages[IriSP.language] !== "undefined"
- ? this.messages[IriSP.language]
- : (
- IriSP.language.length > 2 && typeof this.messages[IriSP.language.substr(0,2)] !== "undefined"
- ? this.messages[IriSP.language.substr(0,2)]
- : this.messages["en"]
- )
- );
+ this.l10n =
+ typeof this.constructor.messages[IriSP.language] !== "undefined"
+ ? this.constructor.messages[IriSP.language]
+ : IriSP.language.length > 2 &&
+ typeof this.constructor.messages[IriSP.language.substr(0, 2)] !== "undefined"
+ ? this.constructor.messages[IriSP.language.substr(0, 2)]
+ : this.constructor.messages["en"];
- /* Loading Metadata if required */
+ /* Loading Metadata if required */
- function onsourceloaded() {
+ function onsourceloaded() {
if (_this.localannotations) {
- _this.localsource = player.loadLocalAnnotations(_this.localannotations);
- _this.source.merge(_this.localsource);
+ _this.localsource = player.loadLocalAnnotations(
+ _this.localannotations
+ );
+ _this.source.merge(_this.localsource);
}
if (_this.media_id) {
- _this.media = this.getElement(_this.media_id);
- } else {
- var _mediaopts = {
- is_mashup: _this.is_mashup || false
- };
- _this.media = _this.source.getCurrentMedia(_mediaopts);
- }
- if (_this.pre_draw_callback){
- IriSP.jQuery.when(_this.pre_draw_callback()).done(_this.draw());
+ _this.media = this.getElement(_this.media_id);
+ } else {
+ var _mediaopts = {
+ is_mashup: _this.is_mashup || false,
+ };
+ _this.media = _this.source.getCurrentMedia(_mediaopts);
}
- else {
- _this.draw();
+ if (_this.pre_draw_callback) {
+ jQuery.when(_this.pre_draw_callback()).done(_this.draw());
+ } else {
+ _this.draw();
}
_this.player.trigger("widget-loaded");
- }
+ }
- if (this.metadata) {
+ if (this.metadata) {
/* Getting metadata */
this.source = player.loadMetadata(this.metadata);
/* Call draw when loaded */
this.source.onLoad(onsourceloaded);
- } else {
+ } else {
if (this.source) {
- onsourceloaded();
+ onsourceloaded();
}
+ }
+ }
+
+ toString() {
+ return "Widget " + this.type;
+ }
+
+ templateToHtml(_template) {
+ return Mustache.render(_template, this);
+ }
+
+ renderTemplate() {
+ this.$.append(this.templateToHtml(this.constructor.template));
+ }
+
+ functionWrapper(_name) {
+ var _this = this,
+ _function = this[_name];
+ if (typeof _function !== "undefined") {
+ return function () {
+ return _function.apply(
+ _this,
+ Array.prototype.slice.call(arguments, 0)
+ );
+ };
+ } else {
+ console.log(
+ "Error, Unknown function IriSP.Widgets." + this.type + "." + _name
+ );
+ }
+ }
+
+ getFunctionOrName(_functionOrName) {
+ switch (typeof _functionOrName) {
+ case "function":
+ return _functionOrName;
+ case "string":
+ return this.functionWrapper(_functionOrName);
+ default:
+ return undefined;
+ }
+ }
+
+ onMdpEvent(_eventName, _functionOrName) {
+ this.player.on(_eventName, this.getFunctionOrName(_functionOrName));
+ }
+
+ onMediaEvent(_eventName, _functionOrName) {
+ this.media.on(_eventName, this.getFunctionOrName(_functionOrName));
+ }
+
+ getWidgetAnnotations() {
+ var result = null;
+ if (typeof this.annotation_type === "undefined") {
+ result = this.media.getAnnotations();
+ } else if (this.annotation_type.elementType === "annotationType") {
+ result = this.annotation_type.getAnnotations();
+ } else {
+ result = this.media.getAnnotationsByTypeTitle(this.annotation_type);
+ }
+ if (typeof this.annotation_filter !== "undefined") {
+ return this.annotation_filter(result);
+ } else {
+ return result;
+ }
+ }
+
+ getWidgetAnnotationsAtTime() {
+ var _time = this.media.getCurrentTime();
+ return this.getWidgetAnnotations().filter(function (_annotation) {
+ return _annotation.begin <= _time && _annotation.end > _time;
+ });
+ }
+
+ isLoaded() {
+ var isloaded = !_(this.__subwidgets).some(function (w) {
+ return !(w && w.isLoaded());
+ });
+ return isloaded;
+ }
+
+ insertSubwidget(_selector, _widgetoptions, _propname) {
+ var _id = _selector.attr("id"),
+ _this = this,
+ key = this.__subwidgets.length;
+ this.__subwidgets.push(null);
+ if (typeof _id == "undefined") {
+ _id = _.uniqueId(this.container + "_sub_widget_" + _widgetoptions.type);
+ _selector.attr("id", _id);
+ }
+ _widgetoptions.container = _id;
+ _this.player.loadWidget(_widgetoptions, function (_widget) {
+ if (_propname) {
+ _this[_propname] = _widget;
+ }
+ _this.__subwidgets[key] = _widget;
+ });
}
-
-};
-
-IriSP.Widgets.Widget.prototype.defaults = {};
-
-IriSP.Widgets.Widget.prototype.template = '';
-
-IriSP.Widgets.Widget.prototype.messages = {"en":{}};
-
-IriSP.Widgets.Widget.prototype.toString = function() {
- return "Widget " + this.type;
-};
-
-IriSP.Widgets.Widget.prototype.templateToHtml = function(_template) {
- return Mustache.to_html(_template, this);
-};
-
-IriSP.Widgets.Widget.prototype.renderTemplate = function() {
- this.$.append(this.templateToHtml(this.template));
-};
-
-IriSP.Widgets.Widget.prototype.functionWrapper = function(_name) {
- var _this = this,
- _function = this[_name];
- if (typeof _function !== "undefined") {
- return function() {
- return _function.apply(_this, Array.prototype.slice.call(arguments, 0));
- };
- } else {
- console.log("Error, Unknown function IriSP.Widgets." + this.type + "." + _name);
+ /*
+ * Position the player to the next/previous annotations based on current player position
+ *
+ * Parameter: offset: -1 for previous annotation, +1 for next annotation
+ */
+ navigate(offset) {
+ // offset is normally either -1 (previous slide) or +1 (next slide)
+ var _this = this;
+ var currentTime = _this.media.getCurrentTime();
+ var annotations = _this
+ .getWidgetAnnotations()
+ .sortBy(function (_annotation) {
+ return _annotation.begin;
+ });
+ for (var i = 0; i < annotations.length; i++) {
+ if (
+ annotations[i].begin <= currentTime &&
+ currentTime < annotations[i].end
+ ) {
+ // Found a current annotation - clamp i+offset value to [0, length - 1]
+ i = Math.min(annotations.length - 1, Math.max(0, i + offset));
+ _this.media.setCurrentTime(annotations[i].begin);
+ break;
+ }
+ }
}
-};
-IriSP.Widgets.Widget.prototype.getFunctionOrName = function(_functionOrName) {
- switch (typeof _functionOrName) {
- case "function":
- return _functionOrName;
- case "string":
- return this.functionWrapper(_functionOrName);
- default:
- return undefined;
- }
-};
-
-IriSP.Widgets.Widget.prototype.onMdpEvent = function(_eventName, _functionOrName) {
- this.player.on(_eventName, this.getFunctionOrName(_functionOrName));
-};
-
-IriSP.Widgets.Widget.prototype.onMediaEvent = function(_eventName, _functionOrName) {
- this.media.on(_eventName, this.getFunctionOrName(_functionOrName));
-};
+ /*
+ * Propose an export of the widget's annotations
+ *
+ * Parameter: a list of annotations. If not specified, the widget's annotations will be exported.
+ */
+ exportAnnotations(annotations) {
+ var widget = this;
+ if (annotations === undefined) annotations = this.getWidgetAnnotations();
+ var $ = jQuery;
-IriSP.Widgets.Widget.prototype.getWidgetAnnotations = function() {
- var result = null;
- if (typeof this.annotation_type === "undefined") {
- result = this.media.getAnnotations();
- } else if (this.annotation_type.elementType === "annotationType") {
- result = this.annotation_type.getAnnotations();
- } else {
- result = this.media.getAnnotationsByTypeTitle(this.annotation_type);
- }
- if (typeof this.annotation_filter !== "undefined") {
- return this.annotation_filter(result);
- } else {
- return result;
- }
-};
-
-IriSP.Widgets.Widget.prototype.getWidgetAnnotationsAtTime = function() {
- var _time = this.media.getCurrentTime();
- return this.getWidgetAnnotations().filter(function(_annotation) {
- return _annotation.begin <= _time && _annotation.end > _time;
- });
-};
-
-IriSP.Widgets.Widget.prototype.isLoaded = function() {
- var isloaded = !IriSP._(this.__subwidgets).any(function(w) {
- return !(w && w.isLoaded());
- });
- return isloaded;
-};
+ // FIXME: this should belong to a proper serialize/deserialize component?
+ var content =
+ Mustache.render("[video:{{url}}]\n", { url: widget.media.url }) +
+ annotations
+ .map(function (a) {
+ return Mustache.render(
+ "[{{ a.begin }}]{{ a.title }} {{ a.description }}[{{ a.end }}]",
+ { a: a }
+ );
+ })
+ .join("\n");
-IriSP.Widgets.Widget.prototype.insertSubwidget = function(_selector, _widgetoptions, _propname) {
- var _id = _selector.attr("id"),
- _this = this,
- _type = _widgetoptions.type,
- $L = $LAB,
- key = this.__subwidgets.length;
- this.__subwidgets.push(null);
- if (typeof _id == "undefined") {
- _id = IriSP._.uniqueId(this.container + '_sub_widget_' + _widgetoptions.type);
- _selector.attr("id", _id);
- }
- _widgetoptions.container = _id;
- if (typeof IriSP.widgetsRequirements[_type] !== "undefined" && typeof IriSP.widgetsRequirements[_type].requires !== "undefined" ) {
- for (var _j = 0; _j < IriSP.widgetsRequirements[_type].requires.length; _j++) {
- $L.script(IriSP.getLib(IriSP.widgetsRequirements[_type].requires[_j]));
- }
- }
- $L.wait(function() {
- _this.player.loadWidget(_widgetoptions, function(_widget) {
- if (_propname) {
- _this[_propname] = _widget;
+ var el = $("<pre>")
+ .addClass("exportContainer")
+ .text(content)
+ .dialog({
+ title: "Annotation export",
+ open: function (event, ui) {
+ // Select text
+ var range;
+ if (document.selection) {
+ range = document.body.createTextRange();
+ range.moveToElementText(this[0]);
+ range.select();
+ } else if (window.getSelection) {
+ range = document.createRange();
+ range.selectNode(this[0]);
+ window.getSelection().addRange(range);
}
- _this.__subwidgets[key] = _widget;
+ },
+ autoOpen: true,
+ width: "80%",
+ minHeight: "400",
+ height: 400,
+ buttons: [
+ {
+ text: "Close",
+ click: function () {
+ $(this).dialog("close");
+ },
+ },
+ {
+ text: "Download",
+ click: function () {
+ a = document.createElement("a");
+ a.setAttribute(
+ "href",
+ "data:text/plain;base64," + btoa(content)
+ );
+ a.setAttribute(
+ "download",
+ "Annotations - " +
+ widget.media.title.replace(/[^ \w]/g, "") +
+ ".txt"
+ );
+ a.click();
+ },
+ },
+ ],
});
- });
-};
-
-/*
- * Position the player to the next/previous annotations based on current player position
- *
- * Parameter: offset: -1 for previous annotation, +1 for next annotation
- */
-IriSP.Widgets.Widget.prototype.navigate = function(offset) {
- // offset is normally either -1 (previous slide) or +1 (next slide)
- var _this = this;
- var currentTime = _this.media.getCurrentTime();
- var annotations = _this.getWidgetAnnotations().sortBy(function(_annotation) {
- return _annotation.begin;
- });
- for (var i = 0; i < annotations.length; i++) {
- if (annotations[i].begin <= currentTime && currentTime < annotations[i].end) {
- // Found a current annotation - clamp i+offset value to [0, length - 1]
- i = Math.min(annotations.length - 1, Math.max(0, i + offset));
- _this.media.setCurrentTime(annotations[i].begin);
- break;
- }
- };
-};
+ }
-/*
- * Propose an export of the widget's annotations
- *
- * Parameter: a list of annotations. If not specified, the widget's annotations will be exported.
- */
-IriSP.Widgets.Widget.prototype.exportAnnotations = function(annotations) {
- var widget = this;
- if (annotations === undefined)
- annotations = this.getWidgetAnnotations();
- var $ = IriSP.jQuery;
-
- // FIXME: this should belong to a proper serialize/deserialize component?
- var content = Mustache.to_html("[video:{{url}}]\n", {url: widget.media.url}) + annotations.map( function(a) { return Mustache.to_html("[{{ a.begin }}]{{ a.title }} {{ a.description }}[{{ a.end }}]", { a: a }); }).join("\n");
+ /**
+ * This method responsible of drawing a widget on screen.
+ */
+ draw() {
+ /* implemented by "sub-classes" */
+ }
- var el = $("<pre>")
- .addClass("exportContainer")
- .text(content)
- .dialog({
- title: "Annotation export",
- open: function( event, ui ) {
- // Select text
- var range;
- if (document.selection) {
- range = document.body.createTextRange();
- range.moveToElementText(this[0]);
- range.select();
- } else if (window.getSelection) {
- range = document.createRange();
- range.selectNode(this[0]);
- window.getSelection().addRange(range);
- }
- },
- autoOpen: true,
- width: '80%',
- minHeight: '400',
- height: 400,
- buttons: [ { text: "Close", click: function() { $( this ).dialog( "close" ); } },
- { text: "Download", click: function () {
- a = document.createElement('a');
- a.setAttribute('href', 'data:text/plain;base64,' + btoa(content));
- a.setAttribute('download', 'Annotations - ' + widget.media.title.replace(/[^ \w]/g, '') + '.txt');
- a.click();
- } } ]
- });
-};
+ //Generates uid
+ //source : http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
+ generateUid() {
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
+ /[xy]/g,
+ function (c) {
+ var r = (Math.random() * 16) | 0,
+ v = c === "x" ? r : (r & 0x3) | 0x8;
+ return v.toString(16);
+ }
+ );
+ }
+ };
-/**
- * This method responsible of drawing a widget on screen.
- */
-IriSP.Widgets.Widget.prototype.draw = function() {
- /* implemented by "sub-classes" */
-};
+ return Widgets;
+}