: 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
const item = self.getEl(id);
} else if (item[0] !== undefined) {
wrap_class: 'tb_multi_columns_wrap',
wrap_class: 'tb_multi_columns_wrap',
id: id + '_divider_color',
prop: 'column-rule-color',
id: id + '_divider_width',
class: 'tb_multi_columns_width',
prop: 'column-rule-width',
id: id + '_divider_style',
options: self.getOptions('border'),
prop: 'column-rule-style',
for (let i = 0; i < 7; ++i) {
opt[i] = i === 0 ? '' : i;
hide: 'tb_multi_columns_wrap'
show: 'tb_multi_columns_wrap'
const ndata = api.Helper.cloneObject(data);
const wrap = self.select.render(ndata, self),
select = wrap.querySelector('select');
self.afterRun.push(() => {
const field = select.closest('.tb_field');
field.parentNode.insertBefore(self.create(columnOptions), field.nextElementSibling);
const wrap = createElement('fieldset', 'tb_expand_wrap'),
expand = createElement('','tb_expanded_opttions'),
toggle = createElement('','tb_style_toggle tb_closed');
toggle.append(createTextNode(i18n[data.label] ?? data.label), api.Helper.getIcon('ti-angle-up'));
toggle.tfOn(_CLICK_, function (e) {
e.stopImmediatePropagation();
if (this.dataset.done === undefined) {
this.dataset.done = true;
expand.appendChild(self.create(data.options));
Themify.trigger('tb_options_expand', expand);
this.classList.toggle('tb_closed');
wrap.append(toggle, expand);
self.afterRun.push(() => {
Themify.trigger('tb_options_expand', expand);
const tmp = shortcode.replace(/[\r\n]/gm, '').replace(/ +/g, ' ').match(/ids.*?=.(.+?)["']/gi);
return tmp?.[0]?.replace('ids', '').replace('=', '').replaceAll(' ', '').replace(/["']/g, '').trim().split(',') || null;
replaceShortcode(oldV, newV) {
return oldV.replace(/[\r\n]/gm, '').replace(/ +/g, ' ').replace(/ids.*?=.(.+?)["']/ig, 'ids="' + newV + '"');
for(let i=0;i<ids.length;++i){
let item=this.cache.get(ids[i].toString());
for(let i=res.length-1;i>-1;--i){
this.cache.set(res[i].id.toString(), res[i]);
getSelectedImages(collections){
for(let i=0;i<collections.length;++i){
let attr=collections[i].attributes,
item[k]=k==='thumbnail'?s.url:[s.url,s.width,s.height];
async getImages(shortcode){
let ids=this.parseIds(shortcode),
const tmp = shortcode.replace(/[\r\n]/gm, '').replace(/ +/g, ' ').match(/path.*?=.(.+?)["']/gi),
images= tmp?.[0]?.replace('path', '').replace('=', '').replaceAll(' ', '').replace(/["']/g, '').trim().split(',');
for(let i=0;i<images.length;++i){
let prmsK='pr_'+ids.join(','),
prms=this.cache.get(prmsK);
action: 'tb_get_ajax_data',
dataset: 'gallery_shortcode',
this.cache.set(prmsK,prms);
api.Spinner.showLoader('error');
const clone = wp.media.gallery.shortcode,
isInLine=!api.LightBox.el.contains(btn),
openMediaLibrary = e => {
if (this.file_frame === null) {
// Create the media frame.
this.file_frame = wp.media.frames.file_frame = wp.media({
state: 'gallery-library',
title: wp.media.view.l10n.editGalleryTitle,
this.file_frame.el.classList.add('themify_gallery_settings');
this.file_frame.options.selection.reset();
wp.media.gallery.shortcode = attachments => {
const props = attachments.props.toJSON(),
attrs.order = props.order;
attrs.orderby = props.orderby;
if (attachments.gallery) {
Object.assign(attrs,attachments.gallery.toJSON());
attrs.ids = attachments.pluck('id');
// Copy the `uploadedTo` post ID.
attrs.id = props.uploadedTo;
// Check if the gallery is randomly ordered.
if ( attrs._orderbyrandom || attrs._orderbyRandom ) {
delete attrs._orderbyrandom;
delete attrs._orderbyRandom;
// If the `ids` attribute is set and `orderby` attribute
// is the default value, clear it for cleaner output.
else if (attrs.ids && 'post__in' === attrs.orderby) {
// Remove default attributes from the shortcode.
for (let key in wp.media.gallery.defaults) {
if (wp.media.gallery.defaults[key] === attrs[key]) {
delete attrs._orderByField;
delete attrs._orderbyfield;
const shortcode = new topWindow.wp.shortcode({
wp.media.gallery.shortcode = clone;
const v = input.value.trim(),
setShortcode = selection => {
const v = wp.media.gallery.shortcode(selection).string().slice(1, -1);
input.value = '[' + v + ']';
Themify.triggerEvent(input, 'change',{images:this.getSelectedImages(selection.models),models:selection.models});
this.file_frame = wp.media.gallery.edit(v);
this.file_frame.state('gallery-edit');
this.file_frame.state('gallery-library');
this.file_frame.$el.find('.media-menu .media-menu-item').last().trigger('click');
this.file_frame.off('update', setShortcode).on('update', setShortcode);
val = input.value.trim(),
const el =e.target?.closest('.tf_close[data-id]');
const textarea = e.currentTarget.parentNode.tfTag('textarea')[0],
ids = this.parseIds(value),
index = ids?.indexOf(el.dataset.id) ?? -1;
textarea.value = ids.length > 0 ? this.replaceShortcode(value, ids.join(',')) : '';
timer = setTimeout(() => {
Themify.triggerEvent(textarea, 'change',{remove:1});
const el = e.target && !e.target.classList.contains('tf_close') ? e.target.closest('.tb_gal_item') : null;
e.stopImmediatePropagation();
ownerDocument = el.ownerDocument,
e.stopImmediatePropagation();
ownerDocument.body.classList.add('tb_start_animate', 'tb_sort_start');
const _this = e.currentTarget,
b = _this.getBoundingClientRect(),
parentNode = _this.parentNode;
clone = el.cloneNode(true);
clone.classList.add('tb_gal_clone');
_this.classList.add('tb_sort_handler');
box = parentNode.getBoundingClientRect();
holderHeight = (b.height / 2) - parentNode.offsetTop;
holderWidth = (b.width / 2) - parentNode.offsetLeft;
e.stopImmediatePropagation();
} else if (x > box.right) {
} else if (y > box.bottom) {
const moveTo = ownerDocument.elementFromPoint(x, y),
clientX = x - holderWidth - box.left,
clientY = y - holderHeight - box.top;
e.currentTarget.style.transform = 'translate(' + clientX + 'px,' + clientY + 'px)';
if (moveTo && moveTo !== e.currentTarget && moveTo.classList.contains('tb_gal_item')) {
const side = y > prevY || x > prevX ? 'bottom' : 'top';
if (dir !== side || theLast !== moveTo) {
side === 'bottom' ? moveTo.after(clone) : moveTo.before(clone);
e.stopImmediatePropagation();
cancelAnimationFrame(timer);
this.tfOff('pointermove', _startDrag, {passive: true, once: true})
.tfOff('pointermove', _move, {passive: true})
.tfOff('lostpointercapture pointerup', _up, {passive: true, once: true});
ownerDocument.body.classList.remove('tb_start_animate', 'tb_sort_start');
const wr = this.closest('.tb_shortcode_preview'),
items = wr.tfClass('tf_close'),
textarea = wr.parentNode.tfTag('textarea')[0],
clone.classList.remove('tb_gal_clone');
for (let i = 0; i < items.length; ++i) {
shortcode.push(items[i].dataset.id);
textarea.value = self.replaceShortcode(textarea.value, shortcode.join(','));
Themify.triggerEvent(textarea, 'change',{sort:1});
timer = clone = prevY = prevX = dir = theLast = holderWidth = holderHeight = self=ownerDocument=box = null;
el.tfOn('lostpointercapture pointerup', _up, {passive: true, once: true})
.tfOn('pointermove', _startDrag, {passive: true, once: true})
.tfOn('pointermove', _move, {passive: true})
.setPointerCapture(e.pointerId);
let ids = this.parseIds(shortcode) || [],
fr = createDocumentFragment(),
prewiew_wrap = input.parentNode.tfClass('tb_shortcode_preview')[0];
for (let i = 0; i < images.length; ++i) {
let img = isNaN(image) ? new Image(w, h) : null,
wr = createElement('','tb_gal_item tf_loader tf_w tf_h tf_box tf_rel'),
remove = createElement('button',{type:'button',class:'tf_close','data-id':image.id || ''});
img.src = image.thumbnail || image.large?.[0] || image.full?.[0];
wr.classList.remove('tf_loader', 'tf_w', 'tf_h');
if (prewiew_wrap === undefined) {
prewiew_wrap = createElement();
prewiew_wrap.tfOn(_CLICK_, removeItem, {passive: true})
.tfOn('pointerdown', sort, {passive: true})
.className = 'tb_shortcode_preview tf_scrollbar';
input.after(prewiew_wrap);
prewiew_wrap.replaceChildren();
prewiew_wrap.appendChild(fr);
this.getImages(shortcode).then(res=>{
if (!this.getCache(ids)) {
btn.tfOn(_CLICK_, openMediaLibrary, {passive: true});
if(!e?.detail?.sort && !e?.detail?.remove){
preview(e.currentTarget.value);
const d = createDocumentFragment(),
btn = createElement('button',{type:'button',class:'builder_button tb_text_button tb_btn_arrow'});
btn.innerHTML = i18n.add_gallery;
data.class = 'tb_shortcode_input '+(data.class || '');
d.append(self.textarea.render(data, self), btn);
self.afterRun.push(() => {
this.init(btn, btn.previousElementSibling);
const f = createDocumentFragment(),
area = createElement('textarea'),
v = self.getStyleVal(data.id),
ev = data.control && data.control.event ? data.control.event : 'keyup';
if (self.is_repeat === true) {
area.className = self.is_sort === true ? 'tb_lb_sort_child' : 'tb_lb_option_child';
area.dataset.inputId = data.id;
area.className = 'tb_lb_option';
if (data.class !== undefined) {