-
Notifications
You must be signed in to change notification settings - Fork 262
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Append chapters to VideoObject metadata where applicable (#829)
* Call method to add VideoObject markup on init * Rename method that injects video chapters metadata * Move call of addHasPartMetadata into a utility method * Update name of method * Update regex specificity * Resolve linting errors Add and update unit tests * Rename 'appendSeoMarkup' to 'appendVideoMetadata' * Rename 'isVideoEmbed' method Re-write message source validity check * Rename isVimeoEmbedWithHashParam and remove hash from regex
- Loading branch information
Showing
11 changed files
with
401 additions
and
202 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -80,6 +80,17 @@ function isInteger(value) { | |
function isVimeoUrl(url) { | ||
return /^(https?:)?\/\/((player|www)\.)?vimeo\.com(?=$|\/)/.test(url); | ||
} | ||
/** | ||
* Check to see if the URL is for a Vimeo embed. | ||
* | ||
* @param {string} url The url string. | ||
* @return {boolean} | ||
*/ | ||
|
||
function isVimeoEmbedWithHashParam(url) { | ||
var expr = /^https:\/\/player\.vimeo\.com\/video\/\d+/; | ||
return expr.test(url); | ||
} | ||
/** | ||
* Get the Vimeo URL from an element. | ||
* The element must have either a data-vimeo-id or data-vimeo-url attribute. | ||
|
@@ -127,9 +138,9 @@ function createCommonjsModule(fn, module) { | |
} | ||
|
||
/*! | ||
* weakmap-polyfill v2.0.1 - ECMAScript6 WeakMap polyfill | ||
* weakmap-polyfill v2.0.4 - ECMAScript6 WeakMap polyfill | ||
* https://github.com/polygonplanet/weakmap-polyfill | ||
* Copyright (c) 2015-2020 Polygon Planet <[email protected]> | ||
* Copyright (c) 2015-2021 polygonplanet <[email protected]> | ||
* @license MIT | ||
*/ | ||
(function (self) { | ||
|
@@ -140,8 +151,17 @@ function createCommonjsModule(fn, module) { | |
|
||
var hasOwnProperty = Object.prototype.hasOwnProperty; | ||
|
||
var hasDefine = Object.defineProperty && function () { | ||
try { | ||
// Avoid IE8's broken Object.defineProperty | ||
return Object.defineProperty({}, 'x', { | ||
value: 1 | ||
}).x === 1; | ||
} catch (e) {} | ||
}(); | ||
|
||
var defineProperty = function (object, name, value) { | ||
if (Object.defineProperty) { | ||
if (hasDefine) { | ||
Object.defineProperty(object, name, { | ||
configurable: true, | ||
writable: true, | ||
|
@@ -256,7 +276,7 @@ function createCommonjsModule(fn, module) { | |
function isObject(x) { | ||
return Object(x) === x; | ||
} | ||
})(typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : commonjsGlobal); | ||
})(typeof globalThis !== 'undefined' ? globalThis : typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : commonjsGlobal); | ||
|
||
var npo_src = createCommonjsModule(function (module) { | ||
/*! Native Promise Only | ||
|
@@ -267,7 +287,7 @@ var npo_src = createCommonjsModule(function (module) { | |
// special form of UMD for polyfilling across evironments | ||
context[name] = context[name] || definition(); | ||
|
||
if (module.exports) { | ||
if ( module.exports) { | ||
module.exports = context[name]; | ||
} | ||
})("Promise", typeof commonjsGlobal != "undefined" ? commonjsGlobal : commonjsGlobal, function DEF() { | ||
|
@@ -714,6 +734,108 @@ function swapCallbacks(oldElement, newElement) { | |
callbackMap.delete(oldElement); | ||
} | ||
|
||
/** | ||
* @module lib/postmessage | ||
*/ | ||
/** | ||
* Parse a message received from postMessage. | ||
* | ||
* @param {*} data The data received from postMessage. | ||
* @return {object} | ||
*/ | ||
|
||
function parseMessageData(data) { | ||
if (typeof data === 'string') { | ||
try { | ||
data = JSON.parse(data); | ||
} catch (error) { | ||
// If the message cannot be parsed, throw the error as a warning | ||
console.warn(error); | ||
return {}; | ||
} | ||
} | ||
|
||
return data; | ||
} | ||
/** | ||
* Post a message to the specified target. | ||
* | ||
* @param {Player} player The player object to use. | ||
* @param {string} method The API method to call. | ||
* @param {object} params The parameters to send to the player. | ||
* @return {void} | ||
*/ | ||
|
||
function postMessage(player, method, params) { | ||
if (!player.element.contentWindow || !player.element.contentWindow.postMessage) { | ||
return; | ||
} | ||
|
||
var message = { | ||
method: method | ||
}; | ||
|
||
if (params !== undefined) { | ||
message.value = params; | ||
} // IE 8 and 9 do not support passing messages, so stringify them | ||
|
||
|
||
var ieVersion = parseFloat(navigator.userAgent.toLowerCase().replace(/^.*msie (\d+).*$/, '$1')); | ||
|
||
if (ieVersion >= 8 && ieVersion < 10) { | ||
message = JSON.stringify(message); | ||
} | ||
|
||
player.element.contentWindow.postMessage(message, player.origin); | ||
} | ||
/** | ||
* Parse the data received from a message event. | ||
* | ||
* @param {Player} player The player that received the message. | ||
* @param {(Object|string)} data The message data. Strings will be parsed into JSON. | ||
* @return {void} | ||
*/ | ||
|
||
function processData(player, data) { | ||
data = parseMessageData(data); | ||
var callbacks = []; | ||
var param; | ||
|
||
if (data.event) { | ||
if (data.event === 'error') { | ||
var promises = getCallbacks(player, data.data.method); | ||
promises.forEach(function (promise) { | ||
var error = new Error(data.data.message); | ||
error.name = data.data.name; | ||
promise.reject(error); | ||
removeCallback(player, data.data.method, promise); | ||
}); | ||
} | ||
|
||
callbacks = getCallbacks(player, "event:".concat(data.event)); | ||
param = data.data; | ||
} else if (data.method) { | ||
var callback = shiftCallbacks(player, data.method); | ||
|
||
if (callback) { | ||
callbacks.push(callback); | ||
param = data.value; | ||
} | ||
} | ||
|
||
callbacks.forEach(function (callback) { | ||
try { | ||
if (typeof callback === 'function') { | ||
callback.call(player, param); | ||
return; | ||
} | ||
|
||
callback.resolve(param); | ||
} catch (e) {// empty | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* @module lib/embed | ||
*/ | ||
|
@@ -904,107 +1026,49 @@ function resizeEmbeds() { | |
|
||
window.addEventListener('message', onMessage); | ||
} | ||
|
||
/** | ||
* @module lib/postmessage | ||
*/ | ||
/** | ||
* Parse a message received from postMessage. | ||
* Add chapters to existing metadata for Google SEO | ||
* | ||
* @param {*} data The data received from postMessage. | ||
* @return {object} | ||
*/ | ||
|
||
function parseMessageData(data) { | ||
if (typeof data === 'string') { | ||
try { | ||
data = JSON.parse(data); | ||
} catch (error) { | ||
// If the message cannot be parsed, throw the error as a warning | ||
console.warn(error); | ||
return {}; | ||
} | ||
} | ||
|
||
return data; | ||
} | ||
/** | ||
* Post a message to the specified target. | ||
* | ||
* @param {Player} player The player object to use. | ||
* @param {string} method The API method to call. | ||
* @param {object} params The parameters to send to the player. | ||
* @param {HTMLElement} [parent=document] The parent element. | ||
* @return {void} | ||
*/ | ||
|
||
function postMessage(player, method, params) { | ||
if (!player.element.contentWindow || !player.element.contentWindow.postMessage) { | ||
function initAppendVideoMetadata() { | ||
var parent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document; | ||
|
||
// Prevent execution if users include the player.js script multiple times. | ||
if (window.VimeoSeoMetadataAppended) { | ||
return; | ||
} | ||
|
||
var message = { | ||
method: method | ||
}; | ||
|
||
if (params !== undefined) { | ||
message.value = params; | ||
} // IE 8 and 9 do not support passing messages, so stringify them | ||
window.VimeoSeoMetadataAppended = true; | ||
|
||
var onMessage = function onMessage(event) { | ||
var data = parseMessageData(event.data); | ||
|
||
var ieVersion = parseFloat(navigator.userAgent.toLowerCase().replace(/^.*msie (\d+).*$/, '$1')); | ||
|
||
if (ieVersion >= 8 && ieVersion < 10) { | ||
message = JSON.stringify(message); | ||
} | ||
|
||
player.element.contentWindow.postMessage(message, player.origin); | ||
} | ||
/** | ||
* Parse the data received from a message event. | ||
* | ||
* @param {Player} player The player that received the message. | ||
* @param {(Object|string)} data The message data. Strings will be parsed into JSON. | ||
* @return {void} | ||
*/ | ||
|
||
function processData(player, data) { | ||
data = parseMessageData(data); | ||
var callbacks = []; | ||
var param; | ||
if (!data || data.event !== 'ready') { | ||
return; | ||
} | ||
|
||
if (data.event) { | ||
if (data.event === 'error') { | ||
var promises = getCallbacks(player, data.data.method); | ||
promises.forEach(function (promise) { | ||
var error = new Error(data.data.message); | ||
error.name = data.data.name; | ||
promise.reject(error); | ||
removeCallback(player, data.data.method, promise); | ||
}); | ||
if (!isVimeoUrl(event.origin)) { | ||
return; | ||
} | ||
|
||
callbacks = getCallbacks(player, "event:".concat(data.event)); | ||
param = data.data; | ||
} else if (data.method) { | ||
var callback = shiftCallbacks(player, data.method); | ||
var iframes = parent.querySelectorAll('iframe'); | ||
|
||
if (callback) { | ||
callbacks.push(callback); | ||
param = data.value; | ||
} | ||
} | ||
for (var i = 0; i < iframes.length; i++) { | ||
var iframe = iframes[i]; // Initiate appendVideoMetadata if iframe is a Vimeo embed | ||
|
||
callbacks.forEach(function (callback) { | ||
try { | ||
if (typeof callback === 'function') { | ||
callback.call(player, param); | ||
return; | ||
} | ||
var isValidMessageSource = iframe.contentWindow === event.source; | ||
|
||
callback.resolve(param); | ||
} catch (e) {// empty | ||
if (isVimeoEmbedWithHashParam(iframe.src) && isValidMessageSource) { | ||
var player = new Player(iframe); | ||
player.callMethod('appendVideoMetadata', window.location.href); | ||
} | ||
} | ||
}); | ||
}; | ||
|
||
window.addEventListener('message', onMessage); | ||
} | ||
|
||
/* MIT License | ||
|
@@ -2505,6 +2569,7 @@ if (!isNode) { | |
screenfull = initializeScreenfull(); | ||
initializeEmbeds(); | ||
resizeEmbeds(); | ||
initAppendVideoMetadata(); | ||
} | ||
|
||
export default Player; |
Oops, something went wrong.