: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* @author EmbedPress <help@embedpress.com>
* @copyright Copyright (C) 2018 EmbedPress. All rights reserved.
* @license GPLv2 or later
(function ($, String, $data, undefined) {
$(window.document).ready(function () {
String.prototype.capitalizeFirstLetter = function () {
return this.charAt(0).toUpperCase() + this.slice(1);
String.prototype.isValidUrl = function () {
var rule = /^(https?|embedpresss?):\/\//i;
return rule.test(this.toString());
String.prototype.hasShortcode = function (shortcode) {
var shortcodeRule = new RegExp('\\[' + shortcode + '(?:\\]|.+?\\])', 'ig');
return !!this.toString().match(shortcodeRule);
String.prototype.stripShortcode = function (shortcode) {
var stripRule = new RegExp('(\\[' + shortcode + '(?:\\]|.+?\\])|\\[\\/' + shortcode + '\\])', 'ig');
return this.toString().replace(stripRule, '');
String.prototype.setShortcodeAttribute = function (attr, value, shortcode, replaceInsteadOfMerge) {
replaceInsteadOfMerge = typeof replaceInsteadOfMerge === 'undefined' ? false : replaceInsteadOfMerge;
var subject = this.toString();
if (subject.hasShortcode(shortcode)) {
var attributes = subject.getShortcodeAttributes(shortcode);
if (attributes.hasOwnProperty(attr)) {
if (replaceInsteadOfMerge) {
attributes[attr] = value;
attributes[attr] += ' ' + value;
attributes[attr] = value;
if (!!Object.keys(attributes).length) {
var parsedAttributes = [];
for (var ats in attributes) {
parsedAttributes.push(ats + '="' + attributes[ats] + '"');
subject = '[' + shortcode + ' ' + parsedAttributes.join(' ') + ']' + subject.stripShortcode(shortcode) + '[/' + shortcode + ']';
subject = '[' + shortcode + ']' + subject.stripShortcode(shortcode) + '[/' + shortcode + ']';
String.prototype.getShortcodeAttributes = function (shortcode) {
var subject = this.toString();
if (subject.hasShortcode(shortcode)) {
var propertiesString = (new RegExp(/\[embed\s*(.*?)\]/ig)).exec(subject)[1]; // Separate all shortcode attributes from the rest of the string
if (propertiesString.length > 0) {
var extractAttributesRule = new RegExp(/(\!?\w+-?\w*)(?:="(.+?)")?/ig); // Extract attributes and their values
while (match = extractAttributesRule.exec(propertiesString)) {
if (match[2] === undefined) {
// Prevent `class` property being empty an treated as a boolean param
if (attrName.toLowerCase() !== 'class') {
if (attrName.indexOf('!') === 0) {
attrName = attrName.replace('!', '');
attributes[attrName] = attrValue;
if (attrValue.isBoolean()) {
attrValue = attrValue.isFalse() ? 'false' : 'true';
attributes[attrName] = attrValue;
match = extractAttributesRule = null;
String.prototype.isBoolean = function () {
var subject = this.toString().trim().toLowerCase();
return subject.isTrue(false) || subject.isFalse();
String.prototype.isTrue = function (defaultValue) {
var subject = this.toString().trim().toLowerCase();
defaultValue = typeof defaultValue === undefined ? true : defaultValue;
return !defaultValue.isFalse();
String.prototype.isFalse = function () {
var subject = this.toString().trim().toLowerCase();
var SHORTCODE_REGEXP = new RegExp('\\[\/?' + $data.EMBEDPRESS_SHORTCODE + '\\]', 'gi');
var EmbedPress = function () {
var PLG_SYSTEM_ASSETS_CSS_PATH = $data.EMBEDPRESS_URL_ASSETS + 'css';
var PLG_CONTENT_ASSETS_CSS_PATH = PLG_SYSTEM_ASSETS_CSS_PATH;
* True, if user agent is iOS
* @type Boolean True, if is iOS
self.iOS = /iPad|iPod|iPhone/.test(window.navigator.userAgent);
* The active wrapper, activated by the mouse enter event
self.activeWrapper = null;
self.activeWrapperForModal = null;
* The active controller panel
self.activeControllerPanel = null;
* A list containing all loaded editor instances on the page
* @param object params Override the plugin's params
self.init = function (params) {
$.extend(self.params, params);
// Fix iOS doesn't firing click events on 'standard' elements
$(window.document.body).css('cursor', 'pointer');
self.addEvent = function (event, element, callback) {
if (typeof element.on !== 'undefined') {
element.on(event, callback);
if (element['on' + event.capitalizeFirstLetter()]) {
element['on' + event.capitalizeFirstLetter()].add(callback);
self.isEmpty = function (list) {
return list.length === 0;
self.isDefined = function (attribute) {
return (typeof attribute !== 'undefined') && (attribute !== null);
self.makeId = function () {
var possible = 'abcdefghijklmnopqrstuvwxyz0123456789';
for (var i = 0; i < 5; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length));
self.loadAsyncDynamicJsCodeFromElement = function (subject, wrapper, editorInstance) {
if (subject.prop('tagName') && subject.prop('tagName').toLowerCase() === 'script') {
var scriptSrc = subject.attr('src') || null;
self.addScriptDeclaration(wrapper, subject.html(), editorInstance);
self.addScript(scriptSrc, null, wrapper, editorInstance);
var innerScriptsList = $('script', subject);
if (innerScriptsList.length > 0) {
$.each(innerScriptsList, function (innerScriptIndex, innerScript) {
self.loadAsyncDynamicJsCodeFromElement(innerScript, wrapper, editorInstance);
* Method executed on the document ready event
self.onReady = function () {
var findEditors = function () {
// Wait until the editor is available
var interval = window.setInterval(
var editorsFound = self.getEditors();
if (editorsFound.length) {
self.loadedEditors = editorsFound;
for (var editorIndex = 0; editorIndex < self.loadedEditors.length; editorIndex++) {
self.onFindEditor(self.loadedEditors[editorIndex]);
window.clearInterval(interval);
return self.loadedEditors;
if (self.tinymceIsAvailable()) {
// Add support for the Beaver Builder.
if (typeof FLLightbox !== 'undefined') {
$.each(FLLightbox._instances, function (index) {
FLLightbox._instances[index].on('open', function () {
FLLightbox._instances[index].on('didHideLightbox', function () {
* Detects if tinymce object is available
* @return Boolean True, if available
self.tinymceIsAvailable = function () {
return typeof window.tinymce === 'object' || typeof window.tinyMCE === 'object';
* Returns true if the controller panel is active
* @return Boolean True, if the controller panel is active
self.controllerPanelIsActive = function () {
return typeof self.activeControllerPanel !== 'undefined' && self.activeControllerPanel !== null;
* @return Object The editor
self.getEditors = function () {
if (!window.tinymce || !window.tinymce.editors || window.tinymce.editors.length === 0) {
return window.tinymce.editors || [];
* Parses the content, sending it to the component which will
* look for urls to be parsed into embed codes
* @param string content The content
* @param function onsuccess The callback called on success
self.getParsedContent = function (content, onsuccess) {
// Get the parsed content
url: self.params.baseUrl + 'wp-admin/admin-ajax.php',
action: 'embedpress_do_ajax_request',
self.addStylesheet = function (url, editorInstance) {
var head = editorInstance.getDoc().getElementsByTagName('head')[0];
var $style = $('<link rel="stylesheet" type="text/css" href="' + url + '">');
self.convertURLSchemeToPattern = function (scheme) {
var prefix = '(.*)((?:http|embedpress)s?:\\/\\/(?:www\\.)?',
scheme = scheme.replace(/\*/g, '[a-zA-Z0-9=&_\\-\\?\\.\\/!\\+%:@,#]+');
scheme = scheme.replace(/\./g, '\\.');
scheme = scheme.replace(/\//g, '\\/');
return prefix + scheme + suffix;
self.getProvidersURLPatterns = function () {
// @todo: Add option to disable/enable the providers
self.each($data.urlSchemes, function convertEachURLSchemesToPattern (scheme) {
patterns.push(self.convertURLSchemeToPattern(scheme));
self.addScript = function (source, callback, wrapper, editorInstance) {
var doc = editorInstance.getDoc();
if (typeof wrapper === 'undefined' || !wrapper) {
wrapper = $(doc.getElementsByTagName('head')[0]);
var $script = $(doc.createElement('script'));
$script.attr('async', 1);
if (typeof callback === 'function') {
$script.attr('src', source);
self.addScriptDeclaration = function (wrapper, declaration, editorInstance) {
var doc = editorInstance.getDoc(),
$script = $(doc.createElement('script'));
$(wrapper).append($script);
$script.text(declaration);
self.addURLsPlaceholder = function (node, url, editorInstance) {
var wrapperClasses = ['embedpress_wrapper', 'embedpress_placeholder', 'wpview', 'wpview-wrap'];
var shortcodeAttributes = node.value.getShortcodeAttributes($data.EMBEDPRESS_SHORTCODE);
var customAttributes = shortcodeAttributes;
if (!!Object.keys(shortcodeAttributes).length) {
var specialAttributes = ['class', 'href', 'data-href'];
// Iterates over each attribute of shortcodeAttributes to add the prefix "data-" if missing
var dataPrefix = 'data-';
var prefixedShortcodeAttributes = [];
for (var attr in shortcodeAttributes) {
if (specialAttributes.indexOf(attr) === -1) {
if (attr.indexOf(dataPrefix) !== 0) {
prefixedShortcodeAttributes[dataPrefix + attr] = shortcodeAttributes[attr];
prefixedShortcodeAttributes[attr] = shortcodeAttributes[attr];
attr = attr.replace(dataPrefix, '');
wrapperClasses.push(shortcodeAttributes[attr]);
shortcodeAttributes = prefixedShortcodeAttributes;
prefixedShortcodeAttributes = dataPrefix = null;
if (('data-width' in shortcodeAttributes || 'data-height' in shortcodeAttributes) && 'data-responsive' in shortcodeAttributes) {
shortcodeAttributes['data-responsive'] = 'false';
var wrapper = new self.Node('div', 1);
'class': Array.from(new Set(wrapperClasses)).join(' '),
'id': 'embedpress_wrapper_' + uid,
'data-loading-text': 'Loading your embed...'
wrapperSettings = $.extend({}, wrapperSettings, shortcodeAttributes);
if (wrapperSettings.class.indexOf('is-loading') === -1) {
wrapperSettings.class += ' is-loading';
wrapper.attr(wrapperSettings);
var panel = new self.Node('div', 1);
'id': 'embedpress_controller_panel_' + uid,
'class': 'embedpress_controller_panel embedpress_ignore_mouseout hidden'
function createGhostNode (htmlTag, content) {
htmlTag = htmlTag || 'span';
content = content || ' ';
var ghostNode = new self.Node(htmlTag, 1);
var ghostText = new self.Node('#text', 3);
ghostText.value = content;
ghostNode.append(ghostText);
var editButton = new self.Node('div', 1);
'id': 'embedpress_button_edit_' + uid,
'class': 'embedpress_ignore_mouseout embedpress_controller_button'
var editButtonIcon = new self.Node('div', 1);
'class': 'embedpress-icon-pencil embedpress_ignore_mouseout'