Skip to content

Allow intercept of videoparser by widget and pass attributes #8892

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 48 additions & 40 deletions core/modules/parsers/videoparser.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,48 @@
/*\
title: $:/core/modules/parsers/videoparser.js
type: application/javascript
module-type: parser

The video parser parses a video tiddler into an embeddable HTML element

\*/
(function(){

/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";

var VideoParser = function(type,text,options) {
var element = {
type: "element",
tag: "video",
attributes: {
controls: {type: "string", value: "controls"},
style: {type: "string", value: "width: 100%; object-fit: contain"}
}
},
src;
if(options._canonical_uri) {
element.attributes.src = {type: "string", value: options._canonical_uri};
} else if(text) {
element.attributes.src = {type: "string", value: "data:" + type + ";base64," + text};
}
this.tree = [element];
this.source = text;
this.type = type;
};

exports["video/ogg"] = VideoParser;
exports["video/webm"] = VideoParser;
exports["video/mp4"] = VideoParser;
exports["video/quicktime"] = VideoParser;

})();
/*\
title: $:/core/modules/parsers/videoparser.js
type: application/javascript
module-type: parser

The video parser parses a video tiddler into an embeddable HTML element

\*/
(function () {

/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";

var VideoParser = function (type, text, options) {
var element = {
type: "element",
tag: "$video", // Changed to $video to enable widget interception
attributes: {
controls: { type: "string", value: "controls" },
style: { type: "string", value: "width: 100%; object-fit: contain" }
}
};

// Pass through source information
if (options._canonical_uri) {
element.attributes.src = { type: "string", value: options._canonical_uri };
element.attributes.type = { type: "string", value: type };
} else if (text) {
element.attributes.src = { type: "string", value: "data:" + type + ";base64," + text };
element.attributes.type = { type: "string", value: type };
}

// Pass through tiddler title if available
if (options.title) {
element.attributes.tiddler = { type: "string", value: options.title };
}

this.tree = [element];
this.type = type;
};

exports["video/ogg"] = VideoParser;
exports["video/webm"] = VideoParser;
exports["video/mp4"] = VideoParser;
exports["video/quicktime"] = VideoParser;

})();
104 changes: 104 additions & 0 deletions core/modules/widgets/video.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*\
title: $:/core/modules/widgets/video.js
type: application/javascript
module-type: widget

Basic Video widget for displaying video files.
This is a simple implementation that can be overridden by plugins
for more advanced functionality.

\*/
(function(){

/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";

var Widget = require("$:/core/modules/widgets/widget.js").widget;

var VideoWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};

/*
Inherit from the base widget class
*/
VideoWidget.prototype = new Widget();

/*
Render this widget into the DOM
*/
VideoWidget.prototype.render = function(parent,nextSibling) {
this.parentDomNode = parent;
this.computeAttributes();
this.execute();

// Create video element
var videoElement = this.document.createElement("video");
videoElement.setAttribute("controls", this.getAttribute("controls", "controls"));
videoElement.setAttribute("style", this.getAttribute("style", "width: 100%; object-fit: contain"));
videoElement.className = "tw-video-element";

// Set source
if(this.videoSource) {
if (this.videoSource.indexOf("data:") === 0) {
videoElement.setAttribute("src", this.videoSource);
} else {
var sourceElement = this.document.createElement("source");
sourceElement.setAttribute("src", this.videoSource);
if(this.videoType) {
sourceElement.setAttribute("type", this.videoType);
}
videoElement.appendChild(sourceElement);
}
}

// Insert the video into the DOM
parent.insertBefore(videoElement, nextSibling);
this.domNodes.push(videoElement);
};

/*
Compute the internal state of the widget
*/
VideoWidget.prototype.execute = function() {
// Get the video source and type
this.videoSource = this.getAttribute("src");
this.videoType = this.getAttribute("type");
this.videoControls = this.getAttribute("controls", "controls");

// Try to get from tiddler attribute
if(!this.videoSource && this.getAttribute("tiddler")) {
var tiddlerTitle = this.getAttribute("tiddler");
var tiddler = this.wiki.getTiddler(tiddlerTitle);
if(tiddler) {
if(tiddler.fields._canonical_uri) {
this.videoSource = tiddler.fields._canonical_uri;
this.videoType = tiddler.fields.type;
} else if(tiddler.fields.text) {
this.videoSource = "data:" + tiddler.fields.type + ";base64," + tiddler.fields.text;
this.videoType = tiddler.fields.type;
}
}
}

// Make sure we have a tiddler for saving timestamps
this.tiddlerTitle = this.getAttribute("tiddler");
};

/*
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
*/
VideoWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes.src || changedAttributes.type || changedAttributes.controls || changedAttributes.tiddler) {
this.refreshSelf();
return true;
} else {
return false;
}
};

exports["video"] = VideoWidget;

})();