: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
self.each(nodes, function eachNodeInSerializer (node) {
if (node.firstChild == node.lastChild) {
if (node.firstChild && 'value' in node.firstChild && (node.firstChild.value === ' ' || !node.firstChild.value.trim().length)) {
//@todo:isthiseachreallynecessary?
// Add event to reconfigure wrappers every time the content is loaded
tinymce.each(tinymce.editors, function onEachEditor (editor) {
self.addEvent('loadContent', editor, function onInitEditor (ed) {
self.configureWrappers(editor);
// @todo: This is needed only for JCE, to fix the img placeholder. Try to find out a better approach to avoid the placeholder blink
function afterTimeoutOnFindEditor () {
* This is required because after load/refresh the page, the
* onLoadContent is not being triggered automatically, so
// If in JCE the user see the placeholder (img) instead of the iframe after load/refresh the pagr, this time is too short
// Let's make sure the inner doc has been fully loaded first.
var checkTimesLimit = 100;
var statusCheckerInterval = setInterval(function () {
if (checkIndex === checkTimesLimit) {
clearInterval(statusCheckerInterval);
alert('For some reason TinyMCE was not fully loaded yet. Please, refresh the page and try again.');
var doc = editorInstance.getDoc();
clearInterval(statusCheckerInterval);
self.fixIframeSize = function (iframe) {
if ($(iframe).width() > maxWidth && !$(iframe).data('size-fixed')) {
var ratio = $(iframe).height() / $(iframe).width();
$(iframe).width(maxWidth);
$(iframe).height(maxWidth * ratio);
$(iframe).css('max-width', maxWidth);
$(iframe).attr('max-width', maxWidth);
$(iframe).data('size-fixed', true);
* Function triggered on mouse enter the wrapper
* @param object e The event
self.onMouseEnter = function (e, editorInstance) {
self.displayPreviewControllerPanel($(e.currentTarget), editorInstance);
* Function triggered on mouse get out of the wrapper
* @param object e The event
self.onMouseOut = function (e) {
// Check if the destiny is not a child element
if (self.isDefined(e.toElement)) {
if (e.toElement.parentElement == e.fromElement
|| $(e.toElement).hasClass('embedpress_ignore_mouseout')
if (self.isDefined(e.relatedTarget)) {
if ($(e.relatedTarget).hasClass('embedpress_ignore_mouseout')) {
self.hidePreviewControllerPanel();
* Callback triggered by paste events. This should be hooked by TinyMCE's paste_preprocess
* setting. A normal bind to the onPaste event doesn't work correctly all the times
* (specially when you copy and paste content from the same editor).
self.onPaste = function (plugin, args) {
var urlPatternRegex = new RegExp(/(https?):\/\/([w]{3}\.)?.+?(?:\s|$)/i);
var urlPatternsList = self.getProvidersURLPatterns();
// Split the pasted content into separated lines.
var contentLines = args.content.split(/\n/g) || [];
contentLines = contentLines.map(function (line, itemIndex) {
// Check if there's a url into `line`.
if (line.match(urlPatternRegex)) {
// Split the current line across its space-characters to isolate the url.
let termsList = line.trim().split(/\s+/);
termsList = termsList.map(function (term, termIndex) {
// Check if the term into the current line is a url.
var match = term.match(urlPatternRegex);
for (var urlPatternIndex = 0; urlPatternIndex < urlPatternsList.length; urlPatternIndex++) {
// Isolates that url from the rest of the content if the service is supported.
var urlPattern = new RegExp(urlPatternsList[urlPatternIndex]);
if (urlPattern.test(term)) {
return '</p><p>' + match[0] + '</p><p>';
termsList[termsList.length - 1] = termsList[termsList.length - 1] + '<br>';
line = termsList.join(' ');
// Check if the text was transformed or not. If it was, add wrappers
var content = contentLines.join('');
if (content.replace(/<br>$/, '') !== args.content) {
args.content = '<p>' + args.content + '</p>';
* Method trigered on every node change, to detect new lines. It will
* try to fix a default behavior for some editors of clone the parent
* element when adding a line break. This will clone the embed wrapper
* if we set the cursor after a preview wrapper and hit enter.
* @param object e The event
self.onNodeChange = function (e) {
// Fix the clone parent on break lines issue
// Check if a line break was added
if (e.element.tagName === 'BR') {
// Check one of the parent elements is a clonned embed wrapper
if (e.parents.length > 0) {
$.each(e.parents, function (index, parent) {
if ($(parent).hasClass('embedpress_wrapper')) {
// Remove the cloned wrapper and replace with a 'br' tag
$(parent).replaceWith($('<br>'));
} else if (e.element.tagName === 'IFRAME') {
if (e.parents.length > 0) {
$.each(e.parents, function (index, parent) {
if (parent.hasClass('embedpress_wrapper')) {
var wrapper = $('.embedpress-wrapper', parent);
if (wrapper.length > 1) {
self.onKeyDown = function (e, editorInstance) {
var node = editorInstance.selection.getNode();
if (e.keyCode == 8 || e.keyCode == 46) {
if (node.nodeName.toLowerCase() === 'p') {
var children = $(node).children();
if (children.length > 0) {
$.each(children, function () {
// On delete, make sure to remove the wrapper and children, not only the wrapper
if ($(this).hasClass('embedpress_wrapper') || $(this).hasClass('embedpress_ignore_mouseout')) {
// Ignore the arrows keys
var arrowsKeyCodes = [37, 38, 39, 40];
if (arrowsKeyCodes.indexOf(e.keyCode) == -1) {
// Check if we are inside a preview wrapper
if ($(node).hasClass('embedpress_wrapper') || $(node).hasClass('embedpress_ignore_mouseout')) {
// Avoid delete the wrapper or block line break if we are inside the wrapper
wrapper = $(self.getWrapperFromChild(node));
if (wrapper.length > 0) {
// Creates a temporary element which will be inserted after the wrapper
var tmpId = '__embedpress__tmp_' + self.makeId();
wrapper.after($('<span id="' + tmpId + '"></span>'));
// Get and select the temporary element
var span = editorInstance.dom.select('span#' + tmpId)[0];
editorInstance.selection.select(span);
// Remove the temporary element
// If we are inside the embed preview, ignore any key to avoid edition
return self.cancelEvent(e, editorInstance);
self.getWrapperFromChild = function (element) {
if ($(element).hasClass('embedpress_wrapper')) {
var $parent = $(element).parent();
if ($parent.length > 0) {
return self.getWrapperFromChild($parent[0]);
self.onUndo = function (e, editorInstance) {
// Force re-render everything
self.cancelEvent = function (e, editorInstance) {
editorInstance.dom.events.cancel();
* Method executed when the edit button is clicked. It will display
* a field with the current url, to update the current embed's source
* @param Object e The event
self.onClickEditButton = function (e, editorInstance) {
// Prevent edition of the panel
self.cancelEvent(e, editorInstance);
self.activeWrapperForModal = self.activeWrapper;
var $wrapper = self.activeWrapperForModal;
var wrapperUid = $wrapper.prop('id').replace('embedpress_wrapper_', '');
var customAttributes = {};
var $embedInnerWrapper = $('.embedpress-wrapper', $wrapper);
var embedItem = $('iframe', $wrapper);
if ($embedInnerWrapper.length > 1){
$.each($embedInnerWrapper[0].attributes, function () {
if (this.name !== 'class') {
customAttributes[this.name.replace('data-', '').toLowerCase()] = this.value;
var embedWidth = (((embedItem && embedItem.width()) || $embedInnerWrapper.data('width')) || $embedInnerWrapper.width()) || '';
var embedHeight = (((embedItem && embedItem.height()) || $embedInnerWrapper.data('height')) || $embedInnerWrapper.height()) || '';
embedItem = $embedInnerWrapper = null;
$('<div class="loader-indicator"><i class="embedpress-icon-reload"></i></div>').appendTo($wrapper);
url: self.params.baseUrl + 'wp-admin/admin-ajax.php',
action: 'embedpress_get_embed_url_info',
url: self.decodeEmbedURLSpecialChars($wrapper.data('url'), false)
beforeSend: function (request, requestSettings) {
$('.loader-indicator', $wrapper).addClass('is-loading');
success: function (response) {
bootbox.alert('Unable to get a valid response from the server.');
if (response.canBeResponsive) {
var embedShouldBeResponsive = true;
if ('width' in customAttributes || 'height' in customAttributes) {
embedShouldBeResponsive = false;
} else if ('responsive' in customAttributes && customAttributes['responsive'].isFalse()) {
embedShouldBeResponsive = false;
className: 'embedpress-modal',
title: 'Editing Embed properties',
message: '<form id="form-' + wrapperUid + '" embedpress>' +
'<div class="col-md-12">' +
'<div class="form-group">' +
'<label for="input-url-' + wrapperUid + '">Url</label>' +
'<input class="form-control" type="url" id="input-url-' + wrapperUid + '" value="' + self.decodeEmbedURLSpecialChars($wrapper.data('url'), false) + '">' +
(response.canBeResponsive ?
'<div class="col-md-12">' +
'<label>Responsive</label>' +
'<div class="form-group">' +
'<label class="radio-inline">' +
'<input type="radio" name="input-responsive-' + wrapperUid + '" id="input-responsive-1-' + wrapperUid + '" value="1"' + (embedShouldBeResponsive ? ' checked="checked"' : '') + '> Yes' +
'<label class="radio-inline">' +
'<input type="radio" name="input-responsive-' + wrapperUid + '" id="input-responsive-0-' + wrapperUid + '" value="0"' + (!embedShouldBeResponsive ? ' checked="checked"' : '') + '> No' +
'<div class="col-md-6">' +
'<div class="form-group">' +
'<label for="input-width-' + wrapperUid + '">Width</label>' +
'<input class="form-control" type="integer" id="input-width-' + wrapperUid + '" value="' + embedWidth + '"' + (embedShouldBeResponsive ? ' disabled' : '') + '>' +
'<div class="col-md-6">' +
'<div class="form-group">' +
'<label for="input-height-' + wrapperUid + '">Height</label>' +
'<input class="form-control" type="integer" id="input-height-' + wrapperUid + '" value="' + embedHeight + '"' + (embedShouldBeResponsive ? ' disabled' : '') + '>' +
className: 'btn-default',
self.activeWrapperForModal = null;
className: 'btn-primary',
var $wrapper = self.activeWrapperForModal;
// Select the current wrapper as a base for the new element
editorInstance.selection.select($wrapper[0]);
$wrapper.children().remove();
if (response.canBeResponsive) {
if ($('#form-' + wrapperUid + ' input[name="input-responsive-' + wrapperUid + '"]:checked').val().isFalse()) {
var embedCustomWidth = $('#input-width-' + wrapperUid).val();
if (parseInt(embedCustomWidth) > 0) {
customAttributes['width'] = embedCustomWidth;
var embedCustomHeight = $('#input-height-' + wrapperUid).val();
if (parseInt(embedCustomHeight) > 0) {
customAttributes['height'] = embedCustomHeight;
customAttributes['responsive'] = 'false';
delete customAttributes['width'];
delete customAttributes['height'];
customAttributes['responsive'] = 'true';
var embedCustomWidth = $('#input-width-' + wrapperUid).val();
if (parseInt(embedCustomWidth) > 0) {
customAttributes['width'] = embedCustomWidth;
var embedCustomHeight = $('#input-height-' + wrapperUid).val();
if (parseInt(embedCustomHeight) > 0) {
customAttributes['height'] = embedCustomHeight;
var customAttributesList = [];
if (!!Object.keys(customAttributes).length) {
for (var attrName in customAttributes) {
customAttributesList.push(attrName + '="' + customAttributes[attrName] + '"');
var shortcode = '[' + $data.EMBEDPRESS_SHORTCODE + (customAttributesList.length > 0 ? ' ' + customAttributesList.join(' ') : '') + ']' + $('#input-url-' + wrapperUid).val() + '[/' + $data.EMBEDPRESS_SHORTCODE + ']';
// We do not directly replace the node because it was causing a bug on a second edit attempt
editorInstance.execCommand('mceInsertContent', false, shortcode);
self.configureWrappers(editorInstance);
$('form[embedpress]').on('change', 'input[type="radio"]', function (e) {
var form = self.parents('form[embedpress]');
$('input[type="integer"]', form).prop('disabled', self.val().isTrue());
complete: function (request, textStatus) {
$('.loader-indicator', $wrapper).removeClass('is-loading');
$('.loader-indicator', $wrapper).remove();
* Method executed when the remove button is clicked. It will remove
* the preview and embed code, adding a mark to ignore the url
* @param Object e The event
self.onClickRemoveButton = function (e, editorInstance) {
// Prevent edition of the panel
self.cancelEvent(e, editorInstance);
var $wrapper = self.activeWrapper;
$wrapper.children().remove();
self.recursivelyAddClass = function (element, className) {
$(element).children().each(function (index, child) {
$(child).addClass(className);
var grandChild = $(child).children();
if (grandChild.length > 0) {
self.recursivelyAddClass(child, className);