: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
} else if (binding[val] !== undefined && (val || type === 'select')) {
if (type === 'radio' || type === 'icon_radio') {
logic = _this.checked === true ? binding[val] : false;
} else if (val && binding.not_empty !== undefined) {
logic = binding.not_empty;
} else if (binding.select !== undefined && val !== binding.select.value) {
} else if (binding.checked !== undefined && _this.checked === true) {
} else if (binding.not_checked !== undefined && _this.checked === false) {
logic = binding.not_checked;
if (context === undefined || context === null || context.length === 0) {
context = _this.closest('.tb_tab,.tb_expanded_opttions') || this.getEl('tb_lightbox_container');
const hasHide = logic.hide !== undefined,
hasShow = logic.show !== undefined,
options = this._options[this.clicked].options,
getData = (opt, key) => {
if (undefined !== key && opt !== undefined) {
for (let i = opt.length - 1; i > -1; --i) {
if (opt[i].options !== undefined && Array.isArray(opt[i].options)) {
value = getData(opt[i].options, key);
if (value !== undefined) {
relatedBinding = (el, data, context) => {
const type = el.dataset.type;
_this = el.querySelector('input:checked') || el.tfTag('input')[0];
} else if ('checkbox' === type || 'toggle_switch' === type) {
_this = el.tfTag('input')[0];
} else if ('select' === type) {
_this = el.tfTag('select')[0];
this._binding(_this, data, _this.value, context);
if (hasShow === true && !Array.isArray(logic.show)) {
logic.show = [logic.show];
if (hasHide === true && !Array.isArray(logic.hide)) {
logic.hide = [logic.hide];
let items = hasShow === true ? logic.show : [];
items = items.concat(logic.hide);
for (let i = 0, len = items.length; i < len; ++i) {
if (hasHide === true && logic.hide[i] !== undefined) {
let sel = logic.hide[i].indexOf('#') === 0 ? logic.hide[i] : '.' + logic.hide[i],
hides = context.querySelectorAll(sel);
for (let j = hides.length - 1; j > -1; --j) {
hides[j].classList.add('_tb_hide_binding');
if (null !== this.component) {
let relatedBindData = getData(options, logic.hide[i]);
if (relatedBindData?.binding) {
relatedBindings.push({_el: hides[j], _args: relatedBindData});
if (hasShow === true && logic.show[i] !== undefined) {
let sel = logic.show[i].indexOf('#') === 0 ? logic.show[i] : '.' + logic.show[i],
shows = context.querySelectorAll(sel);
for (let j = shows.length - 1; j > -1; --j) {
shows[j].classList.remove('_tb_hide_binding');
if (null !== this.component) {
let relatedBindData = getData(options, logic.show[i]);
if (relatedBindData?.binding) {
relatedBindings.push({_el: shows[j], _args: relatedBindData});
for (let i = relatedBindings.length - 1; i > -1; --i) {
relatedBinding(relatedBindings[i]._el, relatedBindings[i]._args, context);
if (logic.responsive?.disabled !== undefined) {
if (!Array.isArray(logic.responsive.disabled)) {
logic.responsive.disabled = [logic.responsive.disabled];
const items_disabled = logic.responsive.disabled,
is_responsive = 'desktop' !== api.activeBreakPoint;
for (let i = items_disabled.length - 1; i > -1; --i) {
if (logic.responsive.disabled[i] !== undefined) {
let sel = logic.responsive.disabled[i].indexOf('#') === 0 ? logic.responsive.disabled[i] : '.' + logic.responsive.disabled[i],
resp = context.querySelectorAll(sel);
for (let j = resp.length - 1; j > -1; --j) {
resp[i].classList.toggle('tb_responsive_disable', is_responsive);
this[type].call(this, el, args);
const self = ThemifyConstructor,
repeater = el.closest('.tb_toggleable_fields') || el.closest('.tb_sort_fields_parent') || el.closest('.tb_row_js_wrapper'),
const opt=api.Forms.parseSettings(repeater);
self.settings[ opt.id ] = opt.v;
self.settings[ args.id ] = val;
if (args.selector !== undefined && val) {
selector = model.el.querySelectorAll(args.selector);
if (selector.length === 0) {
} else if (repeater !== null) {
const item = el.closest('.tb_repeatable_field');
let items = repeater.children,
for (let i = items.length - 1; i >-1;--i) {
if (args.rep !== undefined) {
selector = model.el.querySelectorAll(args.rep);
if (selector[index] !== undefined) {
items = selector[index].querySelectorAll(args.selector);
if (items.length === 0) {
items = index !== null && selector[index] !== undefined ? [selector[index]] : null;
if (items !== null && items !== undefined) {
for (let i = items.length - 1; i > -1; --i) {
let sw = items[i].closest('.tf_swiper-slide');
let wrapper = sw.closest('.tf_swiper-wrapper');
let swItems = wrapper.querySelectorAll('.tf_swiper-slide[data-swiper-slide-index="' + index + '"]'),
for (let j = len - 1; j > -1; --j) {
for (let found = swItems[j].querySelectorAll(args.selector), k = found.length - 1; k > -1; --k) {
if ('refresh' === args.type || self._is_ajax === true) {
model.previewReload(self.settings, selector, val);
model.previewLive(self.settings, args.name === 'wp_editor' || el.tagName === 'TEXTAREA', selector, val);
else if (self.clicked === 'setting') {
model.backendLivePreview(self.settings);
const event = args.event || 'change';
if (e.type === 'change') {
} else if ('refresh' === args.type && args.selector === undefined) {
timout = setTimeout(() => {
let value = target.value;
if ('keyup' === e.type) {
if (value === target.dataset.oldValue) {
target.dataset.oldValue = value;
if (target.nodeName === 'SELECT' && target.multiple) {
for (let selected = target.selectedOptions, i = 0; i < selected.length; ++i) {
value.push(selected[ i ].value);
this.preview(target, value, args);
const content = typeof this.getContent === 'function' ? this.getContent() : this.value;
if (api.activeModel === null || previous === content) {
if (is_widget !== false) {
const _id = this.id.split('_');
if (_id[1] && api.LightBox.el.querySelector('textarea.sync-input[name="' + _id[1] + '"]')) {
const widgetText = api.LightBox.el.querySelector('textarea.sync-input[name="' + args.id + '"]');
if (widgetText && widgetText !== this) {
widgetText.value = content;
Themify.triggerEvent(widgetText, 'change');
if (typeof tinyMCE !== 'undefined') {
tinymce.get(this.id)?.setContent(content);
that.preview(this, content, args);
that.preview(this.targetElm, content, args);
messages = api.LightBox.el.querySelectorAll('.wrap > #message');
/* change the ID on WP's #message element.
* Patches an issue with Optin due to similar IDs
for (let i = messages.length - 1; i > -1; --i) {
messages[i].id = 'wp-message';
if (typeof topWindow.QTags === 'function') {
topWindow.QTags._buttonsInit();
if (typeof tinyMCE !== 'undefined') {
if (tinymce.editors[ id ] !== undefined) { // clear the prev editor
tinyMCE.execCommand('mceRemoveEditor', true, id);
const settings = tinyMCEPreInit.mceInit.tb_lb_hidden_editor;
settings.target = ThemifyConstructor.getEl(id.replace('#', ''));
// Creates a new editor instance
const ed = new tinyMCE.Editor(id, settings, tinyMCE.EditorManager);
is_widget = el.classList.contains('wp-editor-area') ? (el.closest('#instance_widget') !== null) : false;
ed.on('change', callback);
ed.on('keyup', callback);
el.tfOn('change keyup', callback, {passive: true});
let currentTarget=e.currentTarget,
selectedLayout = e.detail.val.toString();
if (selectedLayout.indexOf('grid-') === 0) {
selectedLayout = selectedLayout.replace('grid-', 'grid');
} else if (!isNaN(selectedLayout)) {
selectedLayout = 'grid' + selectedLayout;
if (args.classSelector !== undefined && selectedLayout !== 'auto_tiles') {
el=api.liveStylingInstance.el,
apllyTo = args.classSelector !== '' ? el.querySelector(args.classSelector) : el.tfClass('module')[0],
prevLayout = ThemifyConstructor.settings[id];
ThemifyConstructor.settings[id] = selectedLayout;
apllyTo = apllyTo.classList;
prevLayout = prevLayout.toString();
prevLayout = args.prefix + prevLayout;
if (prevLayout.indexOf('grid-') === 0) {
prevLayout = prevLayout.replace('grid-', 'grid');
} else if (!isNaN(prevLayout)) {
prevLayout = 'grid' + prevLayout;
if (prevLayout === 'grid1') {
prevLayout = 'list-post';
} else if (prevLayout === 'default') {
prevLayout = 'tb_default_color';
apllyTo.remove(prevLayout);
selectedLayout = args.prefix + selectedLayout;
if (selectedLayout === 'grid1') {
selectedLayout = 'list-post';
} else if (selectedLayout === 'default') {
selectedLayout = 'tb_default_color';
apllyTo.add(selectedLayout);
api.Utils.runJs(el, 'module');
this.preview(currentTarget, selectedLayout, args);
this.preview(currentTarget, selectedLayout, args);
prev = target.closest('.tb_field').tfClass('themify_fa_toggle')[0];
if (prev !== undefined) {
prev.firstChild?.remove();
prev.appendChild(api.Helper.getIcon(v));
this.preview(target, v, args);
const current=e.currentTarget,
checkbox = current.closest('.tb_checkbox_wrap').tfClass('tb_checkbox');
for (let i = 0; i < checkbox.length; ++i) {
if (checkbox[i].checked) {
checked.push(checkbox[i].value);
this.preview(current, checked.join('|'), args);
el.tfOn('themify_builder_color_picker_change', e=>{
this.preview(e.currentTarget, e.detail.val, args);
widget_select(el, args) {
this.preview(el, api.Forms.serializeObject(el), args);
el.tfOn('queryPosts', e=> {
const current=e.currentTarget;
ThemifyConstructor.settings = api.Forms.serialize('tb_options_setting');
this.preview(current, ThemifyConstructor.settings[args.id], args);
api.activeModel?.builderContentEdit(e.currentTarget);
if (api.activeModel !== null) {
if (this.clicked === 'setting' && data.type !== 'custom_css') {
if (data.control !== false && this.component === 'module') {
const args = data.control || {};
if (args.repeat === true) {
args.id = el.dataset.inputId;
if (this.is_repeat === true) {
args.id = el.dataset.inputId;
if (args.control_type === undefined) {
if (type === undefined || type === 'text' || type === 'number' || type === 'taxonomy' || type === 'url' || type === 'autocomplete' || type === 'range' || type === 'radio' || type === 'icon_radio' || type === 'select' || type === 'gallery' || type === 'textarea' || type === 'address' || type === 'image' || type === 'file' || type === 'lottie' || type === 'date' || type === 'audio' || type === 'video' || type === 'widgetized_select' || type === 'layoutPart' || type === 'selectSearch' || type === 'hidden' || type === 'toggle_switch' || type === 'slider_range' || type === 'orderby_post') {
if (args.event === undefined && (type === 'text' || type === 'textarea')) {
type = args.control_type;
this.control.init(el, type, args);
} else if (api.isVisual && this.clicked === 'styling') {
api.liveStylingInstance.bindEvents(el, data);
if (data.binding !== undefined) {
const is_repeat = this.is_repeat === true,
callback = (_this, v) => {
const context = is_repeat ? el.closest('.tb_sort_field_dropdown,.tb_toggleable_fields_options,.tb_repeatable_field_content') : undefined;
this._binding(_this, data, v, context);
if (data.type === 'layout' || data.type === 'frame') {
el.tfOn(_CLICK_, function (e) {
const t = e.target.closest('.tfl-icon');
el.tfOn('change', function () {
callback(this, this.value);
this._bindings.push({el: el, data: data, repeat: is_repeat});
{_bindings,_radioChange,afterRun}=_this;
for (let i = 0; i < afterRun.length; ++i) {
if (_radioChange !== null) {
for (let i = 0; i < _radioChange.length; ++i) {
if (_bindings !== null) {
for (let i = _bindings.length - 1; i > -1; --i) {
if (_bindings[i].data !== undefined) {
let el = _bindings[i].el,
context = _bindings[i].repeat === true ? el.closest('.tb_sort_field_dropdown,.tb_toggleable_fields_options,.tb_repeatable_field_content') : undefined,
v = _bindings[i].data.type === 'layout' || _bindings[i].data.type === 'frame' ? el.tfClass('selected')[0].id : el.value;
_this._binding(el, _bindings[i].data, v, context);