: 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
((api,_CLICK_,ThemifyConstructor) => {
const gsTpl=doc.tfId('tb_global_styles_root').content;
_this._selectedContainer=el.tfClass('selected_wrap')[0];
_this._list = el.tfClass('list')[0];
el.classList.remove('empty');
for (let i = vals.length - 1; i > -1; --i) {
if (api.GS.styles[vals[i]] !== undefined) {
_this._createSelected(vals[i]);
el.tfClass('actions')[0].tfOn(_CLICK_,e=>{
const action = e.target.dataset.action;
else if(action==='save'){
_this._selectedContainer.tfOn(_CLICK_,e=>{
const id=e.target.closest('.selected')?.dataset.id;
if(e.target.closest('.delete')){
else if(e.target.closest('.edit')){
_this._list.tfOn(_CLICK_,e=>{
const item=e.target.closest('.item');
_this._insert(item.dataset.id);
el.querySelector('#search').tfOn('input', e=> {
const filter = e.target.value.toUpperCase().trim(),
items = e.target.closest('.form').tfClass('item'),
let found=items.length===0;
for (let i = items.length - 1; i > -1; --i) {
let title = items[i].tfClass('title')[0];
let display=filter==='' || title.innerHTML.toUpperCase().includes(filter)? '' : 'none';
if(found===false && display===''){
items[i].style.display =display;
_this._hideShowNoGsText(found);
if (filter!=='' && searchCache[filter]===undefined && !api.GS._allLoaded) {
el.tfClass('clear_search')[0].tfOn(_CLICK_, e=> {
const search=el.querySelector('#search');
Themify.triggerEvent(search,'input');
el.parentNode.querySelector('.overlay').tfOn(_CLICK_, function(e) {
const f = createDocumentFragment(),
st = _this._field.value.split(' ');
for (let i = 0; i < items.length; ++i) {
if(!_this._list.querySelector('[data-id="'+item+'"]')){
let post = api.GS.styles[item],
title=createElement('','title'),
container = createElement('',{'data-id':item,class:'item'+(st.includes(item)? ' selected' : '')});
title.innerHTML=post.title;
container.append(title,createElement('','type',post.type));
f.appendChild(container);
_this._list.appendChild(f);
// Crete selected GS HTML
post = api.GS.styles[id],
selectedItem = createElement('',{class:'selected','data-id':id}),
edit = createElement('span','edit'),
title=createElement('span','tf_overflow');
title.innerHTML=post.title;
edit.appendChild(api.Helper.getIcon('ti-pencil'));
selectedItem.append(edit,title,createElement('span','delete tf_close'));
_this._list.querySelector('[data-id="' + id + '"]')?.classList.add('selected');
_this._selectedContainer.appendChild(selectedItem);
// Insert new global style
if(!_this._selectedContainer.querySelector('[data-id="' + id + '"]')){
// Add selected global style HTML and hide it in drop down
_this._createSelected(id);
// Add CSS class to global style field
let st = _this._field.value + ' ' + id;
_this._field.value = st = st.trim();
_this._selectedContainer.closest('#container').classList.remove('empty');
await api.GS.setGsStyle(st.split(' '));
// Delete Global Style from module
_this._list.querySelector('[data-id="' + id + '"]')?.classList.remove('selected');
_this._selectedContainer.querySelector('[data-id="' + id + '"]')?.remove();
// Add CSS class to global style field
let st = _this._field.value.trim().split(' ');
st.splice(st.indexOf(id), 1);
_this._selectedContainer.closest('#container').classList.add('empty');
await api.GS.setGsStyle(st.split(' '), true);
form=_this.el.querySelector('.form');
const items = Object.keys(api.GS.styles);
if (api.GS._allLoaded !== true) {
_this._reLoad=_this._list.tfOn('scroll',e=>{
_this._reLoad.tfOn(_CLICK_,e=>{
this._hideShowNoGsText();
const cl=this.el.classList,
if(cl.contains('loading')){
if(searchCache[s]!==undefined) {
return Promise.resolve();
for (let i in api.GS.styles) {
if (api.GS.styles[i].id !== undefined) {
loaded.push(api.GS.styles[i].id);
action: 'tb_get_gs_posts',
xhr = new AbortController();
return api.LocalFetch(ajaxData,'json',{signal: xhr.signal}).then(res=>{
this._hideShowNoGsText(true);
const keys = Object.keys(res);
api.GS._allLoaded= keys.length < 10;
// Save as global style event
const data=await api.LiteLightBox.prompt('enterGlobalStyleName');
TF_Notification.showHide('error','enterGlobalStyleName');
ThemifyConstructor.setStylingValues(api.activeBreakPoint);
const styles = api.Helper.cloneObject(api.Base.builderSave(ThemifyConstructor.values,'empty'));
delete styles[api.GS.key];
action:'tb_save_as_new_global_style',
type: api.activeModel.get('mod_name')
api.Spinner.showLoader();
let res=await api.LocalFetch(ajaxData);
api.Spinner.showLoader('hide');
if ('success' === res.status) {
const sucessMsg = res.msg;
await api.Utils.saveCss(api.Base.builderSave(res.data,'empty'), '', res.id);
await TF_Notification.showHide('done', sucessMsg);
api.GS.styles[res.class] = res;
const answer = await api.LiteLightBox.confirm({
await ThemifyConstructor.resetStyling(api.activeModel);
this._addItem([res.class]);
api.LiteLightBox.alert(res.msg);
api.Spinner.showLoader('error');
if (api.GS._allLoaded=== false) {
distToBottom = Math.max(target.scrollHeight - (target.scrollTop + target.offsetHeight), 0);
if (distToBottom > 0 && distToBottom <= 200) {
this._loadMore().catch(e=>{});
_hideShowNoGsText(check){
check??=this._list.tfClass('item')[0]!==undefined;
this._list.tfClass('no_gs')[0].classList.toggle('tf_hide',check);
this._reLoad?.classList.toggle('tf_hide',this._list.scrollHeight > this._list.clientHeight);
class GSShadow extends HTMLElement {
const tpl = gsTpl.cloneNode(true),
input = ThemifyConstructor.hidden.render({
value: ThemifyConstructor.values[api.GS.key],
this.el=new GS(tpl.querySelector('#container'),input);
this.attachShadow({ mode:'open'}).appendChild(tpl);
customElements.define('tb-gs', GSShadow);
Themify.on('tb_toolbar_loaded', () => {
const fr=createDocumentFragment();
fr.appendChild(api.ToolBar.getBaseCss());
gsTpl.prepend(fr.cloneNode(true));
}, true,api.ToolBar?.isLoaded===true);
if (api.isGSPage === true) {
Themify.on('themify_builder_ready',()=>{
api.Registry.off(api.Builder.get(),'tb_init',callback);
if(api.is_builder_ready){
api.Registry.on(api.Builder.get(),'tb_init',callback);
},true,api.is_builder_ready);
else if (themifyBuilder.globalStyles) {
this.extend(themifyBuilder.globalStyles);
themifyBuilder.globalStyles = null;
if (this.styles[key]===undefined && gs[key] !== undefined){
this.styles[key] = gs[key];
// Open Styling Panel in GS edit post
let type = themifyBuilder.globalStyleData.type,
selector = 'module_' + type;
selector = 'active_subrow';
selector = 'active_module';
api.Registry.get(api.Builder.get().el.tfClass(selector)[0].dataset.cid).edit('styling');
api.ToolBar.previewBuilder({item: api.ToolBar.el.tfClass('preview')[0]});
setCss(data, type, isGlobal) {
api.liveStylingInstance.setCss(data, type, isGlobal);
async createCss(data, type,bid, saving) {
bid||=api.Builder.get().id;
const css = await ThemifyStyles.createCss(bid, data, type, saving, this.styles, undefined, saving);
if (saving === true && Object.keys(this.styles).length > 0 && css.gs) {
for (let i in this.styles) {
css.gs.used += '' === css.gs.used ? '' : ', ';
css.gs.used += this.styles[i].title;
// Find used items in builder data
data = JSON.stringify(data);
let pattern = /"global_styles":"(.*?)"/mg,
while ((match = pattern.exec(data)) !== null) {
used += ' ' + match[1].trim();
used = [...new Set(used.split(' '))];
for (let i = used.length - 1; i > -1; --i) {
if (this.styles[used[i]] !== undefined) {
// Build require HTML for Global Style fields and controllers to add it in Styling Tab
return api.isGSPage === true || this.activeGS !== null?false:createElement('tb-gs');
// Trigger required functions on add/delete a GS
updated(css, res, values,model) {
if (api.isGSPage === false && api.isVisual && model.type !== 'module') {
this.extraStyle(css, res, values,model);
async setImport(usedGS, data, ignore) {
if (this.styles[i] !== undefined) {
if (Object.keys(usedGS).length > 0) {
action:'tb_import_gs_posts_ajax',
data: JSON.stringify(usedGS),
return api.LocalFetch(ajaxData).then(res => {
async setGsStyle(values, isRemove,model) {
if (api.isGSPage === true || !api.isVisual) {
let elType = model.get('mod_name'),
styling: ThemifyStyles.generateGSstyles(values, elType, this.styles),
ThemifyStyles.disableNestedSel = true;
if (this._liveInstance === null) {
this._liveInstance = api.createStyleInstance();
this._liveInstance.init(true, true,model);
const css = await this.createCss([res], elType),
live = this._liveInstance,
oldBreakpoint = api.activeBreakPoint,