: 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
groups['cf' === extGroups[g] ? 0 : cfEmpty ? 1 : 2].appendChild(fr);
_this._controlChange(sel, preview, pw, self);
wrapper.tfOn('focusin tf_init', focusIn, {once: true, passive: true})
.append(self._initControl(select, data), preview);
self.afterRun.push(() => {
const weight = self.create([{type: 'select', options: {}, label: 'f_w', selector: data.selector, class: 'font-weight-select', id: data.id + '_w', prop: 'font-weight'}]),
weightParent = weight.querySelector('.tb_field');
wrapper.closest('.tb_field').after(weight);
_this.updateFontVariant(v, weightParent.tfClass('font-weight-select')[0], self);
const select_wrap = createElement('','tf_inline_b tf_vmiddle tf_rel'),
select = createElement('select',{class:'tb_lb_option tf_scrollbar',id:data.id}),
v = self.values[data.id],
select.appendChild(createElement('option'));
let group = createElement('optgroup',{label:i18n[k] || k});
for (let i = 0, anim = options[k]; i < anim.length; ++i) {
let opt = createElement('option',{value:anim[i]},i18n[anim[i]] || anim[i]);
select.appendChild(group);
select_wrap.appendChild(select);
const unstickOption = {},
selectedUID = api.activeModel.id,
_data = api.Helper.cloneObject(data),
for (let cid of Registry.items.keys()) {
let el = Registry.get(cid);
if (type === el?.type && el.id !== selectedUID) {
if ('row' === type && st && (st.custom_css_id || st.row_anchor)) {
uidText = st.custom_css_id ? '#' + st.custom_css_id : '#' + st.row_anchor;
} else if ('module' === type && st && st.custom_css_id) {
uidText = '#' + st.custom_css_id;
uidText = 'row' === type ? 'Row #' + el.id : el.get('mod_name') + ' #' + el.id;
unstickOption[el.id] = uidText;
_data.options = unstickOption;
return self.select.render(_data, self);
update(val, search, options) {
const f = createDocumentFragment();
search.removeAttribute('data-value');
if (options !== undefined) {
let item = createElement('',{class:'tb_search_item','data-value':k},options[k]);
item.className += ' selected';
search.dataset.value = k;
search.value = options[k];
if (search.value === '' && first !== null) {
search.value = options[first];
search.dataset.value = first;
_events(search, container) {
search.tfOn('keyup', function () {
const items = container.tfClass('tb_search_item'),
r = new RegExp(val, 'i');
for (let i = 0, len = items.length; i < len; ++i) {
items[i].style.display = (val === '' || r.test(items[i].textContent)) ? 'block' : 'none';
container.tfOn('pointerdown', function (e) {
if (e.button === 0 && e.target.classList.contains('tb_search_item')) {
const all_items = this.tfClass('tb_search_item'),
for (let i = all_items.length - 1; i > -1; --i) {
all_items[i].classList.remove('selected');
_this.classList.add('selected');
const v = _this.dataset.value;
search.value = _this.textContent;
search.dataset.value = v;
search.previousElementSibling.blur();
Themify.triggerEvent(search, 'selectElement', {val: v});
const container = createElement('','tb_search_wrapper'),
arrow = createElement('',{class:'tb_search_arrow',tabindex:-1}),
label=data.placeholder?? data.label,
search = createElement('input',{type:'text',class:'tb_search_input',autocomplete:'off',placeholder:(i18n[label] || label) + '...'}),
search_container = createElement('',{class:'tb_search_container tf_scrollbar',tabindex:-1});
if (self.is_repeat === true) {
search.className += self.is_sort === true ? ' tb_lb_sort_child' : ' tb_lb_option_child';
search.dataset.inputId = data.id;
search.className += ' tb_lb_option';
if (data.class !== undefined) {
search.className += ' ' + data.class;
search_container.appendChild(this.update(self.values[data.id], search, data.options, self));
arrow.appendChild(createElement('span','tf_loader'));
container.append(arrow, self._initControl(search, data), search_container);
if (data.after !== undefined) {
container.appendChild(self.after(data));
if (data.description !== undefined) {
container.appendChild(self.description(data.description));
if (data.tooltip !== undefined) {
container.appendChild(self.hint(data.tooltip));
this._events(search, search_container);
const el = createElement(),
el.replaceWith(self.create([this.cache[0], this.cache[1]]));
self.afterRun.push(setAfter);
if (this.cache === null) {
el.className = 'tf_loader';
api.Spinner.showLoader();
api.LocalFetch({action: 'tb_optin_get_settings'}).then(res => {
api.Spinner.showLoader('spinhide');
api.Spinner.showLoader('error');
if (!themifyBuilder[data.map + '_api']) {
html: '<span>' + themifyBuilder[data.map + '_api_err'] + '</span>',
wrap_class: 'tb_group_element_' + data.map
return self.separator.render(errData, self);
return createDocumentFragment();
let tmp_el=createElement('',{id:data.id || data.term_id}),
formatData = options => {
result[k] = options[k].name;
update = (item, val, options) => {
item.nextElementSibling?.replaceChildren(self.selectSearch.update(val, item, options, self));
get = (wr, val, type, s) => {
wr.classList.add('tb_search_wait');
controller = new AbortController();
action: 'tb_get_post_types',
}, false, {signal: controller.signal})
wr.classList.remove('tb_search_wait');
_data = api.Helper.cloneObject(data),
self.afterRun.push(() => {
let opt = ['id', 'tax_id', 'term_id', 'tag_id'],
fr = createDocumentFragment(),
getTerms = async (search, val, s, isType) => {
const cache_key = s ? val + '_' + s : val;
let res = _this._cacheTerms.get(cache_key);
res = await get(search.parentNode, val, 'terms', s);
_this._cacheTerms.set(cache_key, res);
if (data.term_id === undefined && data.tag_id === undefined) {
const wrap = search.closest('.' + data.id),
is_all = wrap.querySelector('#' + data.id).value === 'All',
els = wrap.querySelectorAll('.' + data.tax_id + ',.' + data.term_id + ',.' + data.tag_id);
for (let k = els.length - 1; k > -1; --k) {
els[k].classList.toggle('tf_hide', is_all);
const term_id = data.tag_id || data.term_id.replace('#tmp_id#', val),
parent = search.closest('.tb_input');
if (isInit === null && values[term_id] !== undefined) {
term_val = values[term_id].split('|')[0];
update(search, term_val, res);
const multiply = createElement('input',{type:'text',class:'query_category_multiple'}),
wr = createElement('', 'tb_query_multiple_wrap');
wr.append(createElement('span','',i18n.or), multiply);
parent.insertBefore(wr, parent.nextSibling);
if (after !== undefined) {
parent.appendChild(self.after(after));
if (desc !== undefined) {
parent.appendChild(self.description(desc));
if (data.slug_id !== undefined) {
const referenceNode = parent.parentNode,
query_by = self.create([{
default: values.term_type === undefined && values[data.tax_id] === 'post_slug' ? 'post_slug' : 'category', //backward compatibility
{value: 'all', name: 'all_posts'},
{value: 'category', name: 'query_term_id'},
{value: 'post_slug', name: 'slug_label'}
wrap_class: 'tb_group_element_post_slug',
referenceNode.before(query_by);
referenceNode.parentNode.appendChild(slug);
if (data.sticky_id !== undefined) {
const sticky = self.create([{
wrap_class: 'tb_group_element_all'
parent.parentNode.parentNode.appendChild(sticky);
multiply.tfOn('change', () => {
Themify.triggerEvent(search, 'queryPosts', {val: term_val});
timeout = setTimeout(() => {
parent.tfClass('query_category_multiple')[0].value = term_val;
if (isInit === true || self.is_new) {
Themify.triggerEvent(search, 'queryPosts', {val: term_val});
ThemifyConstructor.settings = api.Forms.serialize('tb_options_setting');
for (let i = 0, len = opt.length; i < len; ++i) {
_data.id = _data[opt[i]];
_data.label = 'query_' + opt[i];
_data.type = 'selectSearch';
if (opt[i] === 'term_id') {
_data.wrap_class = 'tb_search_term_wrap tb_group_element_category';
_data.class = 'query_category_single';
_data.help = 'query_desc';
_data.control = {control_type: 'queryPosts'};
else if ((opt[i] === 'tax_id' || opt[i] === 'tag_id') && _data.term_id === undefined) {
_data.control = {control_type: 'queryPosts'};
delete _data.description;
let res = self.create([_data]);
if (true === data.just_current) {
let is_post = opt[i] === 'id',
is_term = opt[i] === 'term_id' || opt[i] === 'tag_id',
v = is_term ? '' : values[_data.id],
search = res.querySelector('.tb_search_input');
search.tfOn('selectElement', function (e) {
nextsearch = this.closest('.tb_field');
nextsearch = nextsearch.nextElementSibling;
if (nextsearch !== null) {
if (!is_post && isInit === true && data.slug_id !== undefined) {
nextsearch = nextsearch.nextElementSibling;
if (nextsearch !== null) {
nextsearch = nextsearch.tfClass('tb_search_input')[0];
if (_this._cacheTypes[val] !== undefined) {
if (true === data.just_current && 'tag' === values[data.tax_id]) {
values[data.tax_id] = 'post_tag';
update(nextsearch, values[data.tax_id], formatData(_this._cacheTypes[val].options));
Themify.triggerEvent(nextsearch, 'selectElement', {val: nextsearch.dataset.value});