From 76127d2d869d6260faab448cedc484ede7f9770d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Val=C3=A9rian=20Galliat?= Date: Thu, 10 Sep 2015 17:32:56 +0200 Subject: [PATCH 1/2] Rename 'append-to' to 'render' --- lib/{append-to.js => render.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lib/{append-to.js => render.js} (100%) diff --git a/lib/append-to.js b/lib/render.js similarity index 100% rename from lib/append-to.js rename to lib/render.js From 41dc75b8e7420297043d2fb294ce334a498498df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Val=C3=A9rian=20Galliat?= Date: Thu, 10 Sep 2015 17:34:07 +0200 Subject: [PATCH 2/2] Implement 'render-to' method * Update 'handle' (previously 'append-to') to take a 'getElem' function instead of directly a root element, allowing to custimize the element injection method, and without directly manipulating the DOM. * Reimplement 'append-to' using abstract 'handle' method. * Implement a 'render-to' method to render a torrent inside an existing element. --- README.md | 4 ++++ lib/append-to.js | 35 ++++++++++++++++++++++++++++ lib/file.js | 12 ++++++++++ lib/render-to.js | 17 ++++++++++++++ lib/render.js | 60 +++++++++++++++++------------------------------- 5 files changed, 89 insertions(+), 39 deletions(-) create mode 100644 lib/append-to.js create mode 100644 lib/render-to.js diff --git a/README.md b/README.md index 9b75aa14..e5312efc 100644 --- a/README.md +++ b/README.md @@ -540,6 +540,10 @@ file.appendTo('#containerElement', function (err, elem) { }) ``` +#### `file.renderTo(elem, function callback (err, elem) {})` + +Like `file.appendTo` but renders directly into given element (or CSS selector). + #### `file.getBlobURL(function callback (err, url) {})` Get a url which can be used in the browser to refer to the file. diff --git a/lib/append-to.js b/lib/append-to.js new file mode 100644 index 00000000..672d711f --- /dev/null +++ b/lib/append-to.js @@ -0,0 +1,35 @@ +var render = require('./render') + +module.exports = function appendTo (file, rootElem, cb) { + if (rootElem && (rootElem.nodeName === 'VIDEO' || rootElem.nodeName === 'AUDIO')) { + throw new Error( + 'Invalid video/audio node argument. Argument must be root element that ' + + 'video/audio tag will be appended to.' + ) + } + + render(file, function (tagName) { + if (tagName === 'video' || tagName === 'audio') return createMedia(tagName) + else return createElem(tagName) + }, function (err, elem) { + if (err && elem) { + elem.remove() + } + + cb(err, elem) + }) + + function createMedia (tagName) { + var elem = createElem(tagName) + elem.controls = true + elem.autoplay = true // for chrome + elem.play() // for firefox + return elem + } + + function createElem (tagName) { + var elem = document.createElement(tagName) + rootElem.appendChild(elem) + return elem + } +} diff --git a/lib/file.js b/lib/file.js index 340ff37f..09d3af8e 100644 --- a/lib/file.js +++ b/lib/file.js @@ -1,6 +1,7 @@ module.exports = File var appendTo = require('./append-to') +var renderTo = require('./render-to') var eos = require('end-of-stream') var EventEmitter = require('events').EventEmitter var FileStream = require('./file-stream') @@ -130,3 +131,14 @@ File.prototype.appendTo = function (elem, cb) { if (typeof elem === 'string') elem = document.querySelector(elem) appendTo(this, elem, cb) } + +/** + * Render the file in an existing DOM element. + * @param {Element|string} elem + * @param {function} cb + */ +File.prototype.renderTo = function (elem, cb) { + if (typeof window === 'undefined') throw new Error('browser-only method') + if (typeof elem === 'string') elem = document.querySelector(elem) + renderTo(this, elem, cb) +} diff --git a/lib/render-to.js b/lib/render-to.js new file mode 100644 index 00000000..d2b47cc2 --- /dev/null +++ b/lib/render-to.js @@ -0,0 +1,17 @@ +var path = require('path') +var render = require('./render') + +module.exports = function renderTo (file, elem, cb) { + render(file, function (tagName) { + if (elem.nodeName !== tagName.toUpperCase()) { + var extname = path.extname(file.name).toLowerCase() + + throw new Error( + 'Cannot render "' + extname + '" inside a "' + + elem.nodeName.toLowerCase() + '" element, expected "' + tagName + '"' + ) + } + + return elem + }, cb) +} diff --git a/lib/render.js b/lib/render.js index c68e3f94..84c3a29e 100644 --- a/lib/render.js +++ b/lib/render.js @@ -1,4 +1,4 @@ -var debug = require('debug')('webtorrent:append-to') +var debug = require('debug')('webtorrent:render') var MediaSourceStream = require('mediasource') var path = require('path') var videostream = require('videostream') @@ -15,26 +15,19 @@ var IFRAME_EXTS = [ '.css', '.html', '.js', '.md', '.pdf', '.txt' ] var MediaSource = typeof window !== 'undefined' && window.MediaSource -module.exports = function appendTo (file, rootElem, cb) { +module.exports = function render (file, getElem, cb) { if (!cb) cb = noop var elem var extname = path.extname(file.name).toLowerCase() var currentTime = 0 - if (rootElem && (rootElem.nodeName === 'VIDEO' || rootElem.nodeName === 'AUDIO')) { - throw new Error( - 'Invalid video/audio node argument. Argument must be root element that ' + - 'video/audio tag will be appended to.' - ) - } - - if (MEDIASOURCE_EXTS.indexOf(extname) >= 0) appendToMediaSource() - else if (AUDIO_EXTS.indexOf(extname) >= 0) appendToAudio() - else if (IMAGE_EXTS.indexOf(extname) >= 0) appendToImage() - else if (IFRAME_EXTS.indexOf(extname) >= 0) appendToIframe() + if (MEDIASOURCE_EXTS.indexOf(extname) >= 0) renderMediaSource() + else if (AUDIO_EXTS.indexOf(extname) >= 0) renderAudio() + else if (IMAGE_EXTS.indexOf(extname) >= 0) renderImage() + else if (IFRAME_EXTS.indexOf(extname) >= 0) renderIframe() else nextTick(cb, new Error('Unsupported file type "' + extname + '": Cannot append to DOM')) - function appendToMediaSource () { + function renderMediaSource () { if (!MediaSource) { return nextTick(cb, new Error( 'Video/audio streaming is not supported in your browser. You can still share ' + @@ -50,7 +43,7 @@ module.exports = function appendTo (file, rootElem, cb) { function useVideostream () { debug('Use `videostream` package for ' + file.name) - createElem() + prepareElem() elem.addEventListener('error', fallbackToMediaSource) elem.addEventListener('playing', onPlaying) videostream(file, elem) @@ -58,7 +51,7 @@ module.exports = function appendTo (file, rootElem, cb) { function useMediaSource () { debug('Use MediaSource API for ' + file.name) - createElem() + prepareElem() elem.addEventListener('error', fallbackToBlobURL) elem.addEventListener('playing', onPlaying) @@ -68,7 +61,7 @@ module.exports = function appendTo (file, rootElem, cb) { function useBlobURL () { debug('Use Blob URL for ' + file.name) - createElem() + prepareElem() elem.addEventListener('error', fatalError) elem.addEventListener('playing', onPlaying) file.getBlobURL(function (err, url) { @@ -94,18 +87,13 @@ module.exports = function appendTo (file, rootElem, cb) { useBlobURL() } - function createElem (time) { + function prepareElem () { if (!elem) { - elem = document.createElement(tagName) - elem.controls = true - elem.autoplay = true // for chrome - elem.play() // for firefox + elem = getElem(tagName) elem.addEventListener('progress', function () { currentTime = elem.currentTime }) - - rootElem.appendChild(elem) } } } @@ -115,45 +103,39 @@ module.exports = function appendTo (file, rootElem, cb) { cb(null, elem) } - function appendToAudio () { - elem = document.createElement('audio') - elem.controls = true - elem.autoplay = true - rootElem.appendChild(elem) + function renderAudio () { + elem = getElem('audio') file.getBlobURL(function (err, url) { if (err) return fatalError(err) elem.addEventListener('error', fatalError) elem.addEventListener('playing', onPlaying) elem.src = url - elem.play() }) } - function appendToImage () { + function renderImage () { + elem = getElem('img') file.getBlobURL(function (err, url) { if (err) return fatalError(err) - elem = document.createElement('img') elem.src = url elem.alt = file.name - rootElem.appendChild(elem) - cb(null, elem) + cb(null) }) } - function appendToIframe () { + function renderIframe () { + elem = getElem('iframe') + file.getBlobURL(function (err, url) { if (err) return fatalError(err) - elem = document.createElement('iframe') elem.src = url if (extname !== '.pdf') elem.sandbox = 'allow-forms allow-scripts' - rootElem.appendChild(elem) cb(null, elem) }) } function fatalError (err) { - if (elem) elem.remove() - err.message = 'Error appending file "' + file.name + '" to DOM: ' + err.message + err.message = 'Error rendering file "' + file.name + '": ' + err.message debug(err.message) if (cb) cb(err) }