: 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,body,topBody,bodyCl,topWindowDoc) => {
const {isFrontend,Registry,ActionBar,ToolBar}=api;
if (api.isGSPage === true) {
context.tfOn('pointerdown', e => {
if (e.button === 0 && !api.isPreview && !e.target.closest('.tb_dragger,.tb_disable_sorting,.tb_editor_on')) {
if (clicked.classList.contains('tb_grid_drag')) {
const obj=new api.columnResize();
else if(clicked.tagName.indexOf('TB-')===0){//is our shadow dom event
clicked=e.composedPath()[0];
if(clicked.closest('.tab')){
.tfOn('dragstart', function (e) {
if(api.isPreview===true){
if(!clicked || e.target.nodeType === Node.TEXT_NODE){
let target = e.target.closest('[draggable]');
if(api.activeBreakPoint !== 'desktop' && target){
target=target.closest('.module_column');
if(!target || (api.activeBreakPoint !== 'desktop' && target.classList.contains('active_module'))){
let targetCl = target.classList,
isRow = targetCl.contains('module_row'),
isColumnMove = !isRow && targetCl.contains('module_column');
if (!isRow && !isColumnMove) {
isRow = targetCl.contains('page_break_module') || targetCl.contains('predesigned_row') || targetCl.contains('tb_item_row');
e.stopImmediatePropagation();
type = isRow ? 'row' : (isColumnMove ? 'column_move' : (targetCl.contains('tb_grid') ? 'column' : 'module')),
topScroll = [ToolBar.el.getRootNode().host, topWindowDoc.tfId('tb_fixed_bottom_scroll')],
builder = api.Builder.get().el,
ghost = createElement('','tb_sortable_helper tf_box tf_overflow');
scrollReq=requestAnimationFrame(()=>{
let top=scrollStep * scrollKoef,
scrollY=scrollEl.scrollY??scrollEl.scrollTop;
if(id === 'tb_main_toolbar_root' || id === 'wpadminbar'){
dragScrollEnter=function () {
clearInterval(scrollInterval);
scrollInterval = setInterval(() => {
clearInterval(scrollInterval);
holder.style.display = 'none';
for (let items = builder.querySelectorAll('[data-pos]'), i = items.length - 1; i > -1; --i) {
items[i].removeAttribute('data-pos');
if (isScrolling === null) {
clearInterval(scrollInterval);
cancelAnimationFrame(scrollReq);
isScrolling = scrollInterval =scrollKoef=scrollReq= null;
for (let i = topScroll.length - 1; i > -1; --i) {
topScroll[i].tfOff('dragenter', dragScrollEnter, {passive: true})
.tfOff('dragleave', dragScrollLeave, {passive: true});
if (isRow && api.isVisual) {
ToolBar.zoom({item: ToolBar.el.querySelector('[data-zoom="100"]')});
topScroll = scrollStep=scrollEl= null;
scrollEl = ToolBar.el.getRootNode().host.closest('.interface-interface-skeleton__content') || doc.tfClass('edit-post-layout__content')[0];
scrollEl = api.activeBreakPoint === 'desktop' ? window : topWindow;
if (isRow && api.isVisual) {
ToolBar.zoom({item: ToolBar.el.querySelector('[data-zoom="50"]')});
for (let i = topScroll.length - 1; i > -1; --i) {
topScroll[i].tfOn('dragenter', dragScrollEnter, {passive: true})
.tfOn('dragleave', dragScrollLeave, {passive: true});
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed = 'none';
prevItem?.removeAttribute('data-pos');
holder.style.display = 'none';
e.stopImmediatePropagation();
let {target:dragged,clientY,clientX} = e;
ghostClone.style.top = (clientY - ghostCloneH) + 'px';
if (!dragged || isScrolling !== null || dragged === target || !builder.contains(dragged) || (type === 'module' && dragged.classList.contains('module_row'))) {
if (holder !== null && (dragged === holder ||dragged.classList.contains('tb_sortable_placeholder'))) {
e.dataTransfer.effectAllowed = 'move';
if (y === 0 || x === 0 || (clientY - y) > _FRAME_ || (y - clientY) > _FRAME_ || (clientX - x) > _FRAME_ || (x - clientX) > _FRAME_) {
const rect = dragged.getBoundingClientRect();
let side = (((y - rect.top) / rect.height) > .5) ? 'bottom' : 'top';
if (isColumnMove === true) {
if(cl.contains('row_inner') || cl.contains('module_subrow')){
dragged=inner.tfClass('module_column')[0];
else if (cl.contains('tb_col_side')) {
side = cl[1].replace('tb_col_side_', '');
dragged = dragged.parentNode;
inner = dragged.parentNode;
} else if (cl.contains('module_column')) {
side = (((x - rect.left) / rect.width) > .5) ? 'right' : 'left';
inner = dragged.parentNode;
let w = inner.dataset.dragW,
_area = dragged.dataset.dragArea;
const computed = getComputedStyle(inner);
const c=inner.closest('[data-cid]');
const inner_w = inner.offsetWidth;
let gutter=Registry.get(c.dataset.cid).getSizes('gutter');
gutter=gutter?ThemifyStyles.getGutterValue(gutter):'';
gutter = computed.getPropertyValue('--colg');
let gutterUnit = gutter.replace(parseFloat(gutter).toString(), '') || '%';
gutter = parseFloat(gutter);
if (gutterUnit === '%') {
w = parseFloat(parseFloat((inner_w * gutter) / 100).toFixed(2)).toString();
} else if (gutterUnit === 'em') {
w = gutter * parseFloat(computed.getPropertyValue('font-size'));
for (let cols = inner.children, i = cols.length - 1; i > -1; --i) {
if(cols[i].classList.contains('module_column')){
for (let sides = cols[i].children, j = sides.length - 1; j > -1; --j) {
if (side.classList.contains('tb_col_side')) {
st.marginLeft=st.marginRight='';
let p = side.classList.contains('tb_col_side_right') ? '50' : '-50';
st.width = w === 'none' ? '' : (w + 'px');
st.transform = w === 'none' ? 'translateX(' + p + '%)' : '';
let left=side.getBoundingClientRect().left;
else if(left>=doc.documentElement.clientWidth){
_area = computed.getPropertyValue('--area');
_area = _area.split('" "');
for (let i = _area.length - 1; i > -1; --i) {
let r = _area[i].replaceAll('"', '').split(' ');
r = Array.from(new Set(r));
_area = '"' + _area.join('" "') + '"';
inner.dataset.dragArea= _area;
cl=dragged.classList;//dragged maybe changed
if (_area !== '1' && !cl.contains('tb_drag_side_column') && !cl.contains('tb_drag_one_column')) {
const colArea = getComputedStyle(dragged).getPropertyValue('grid-area').split('/')[0].replace('"', '').trim();
if (api.activeBreakPoint!=='desktop' && !_area.includes(colArea + ' ') && !_area.includes(' ' + colArea)) {
cl.add('tb_drag_one_column');
cl.add('tb_drag_side_column');
if (cl.contains('tb_drag_one_column')) {
side = (((y - rect.top) / rect.height) > .5) ? 'right' : 'left';
if (dragged !== topScroll[0] && dragged !== topScroll[1]) {
if (!ghostClone && isColumnMove === false) {
const cl=dragged.classList;
if(cl.contains('tb_active_builder')){
dragged=side==='top'?dragged.firstElementChild:dragged.lastElementChild.previousElementSibling;
if (cl.contains('module_column')) {
dragged = dragged.tfClass('tb_holder')[0];
else if (cl.contains('tb_dragger')) {
dragged = dragged.parentNode;
if (dragged.classList.contains('tb_holder') && dragged.childElementCount > 0) {
dragged = side === 'top' && dragged.firstChild !== target ? dragged.firstChild : dragged.lastChild;
if (dragged === target) {
if (prevItem && prevItem !== dragged) {
if (isColumnMove === false) {
const sibling = side === 'top' ? dragged.previousSibling : dragged.nextElementSibling;
if (sibling === prevItem) {
const prevPos = sibling.dataset.pos;
if ((side === 'top' && prevPos === 'bottom') || (side === 'bottom' && prevPos === 'top')) {
prevItem.removeAttribute('data-pos');
if (dragged.dataset.pos !== side) {
dragged.dataset.pos=side;
holder.style.display = '';
if (dragged.classList.contains('tb_holder')) {
dragged.appendChild(holder);
side === 'top' ? dragged.before(holder) : dragged.after(holder);
onDragStart = function (e) {
Themify.trigger('disableInline');
e.stopImmediatePropagation();
classItems.push(api.MainPanel.el,ToolBar.el.getRootNode().host);
for(let i=classItems.length-1;i>-1;--i){
classItems[i].classList.add('tb_start_animate', 'tb_drag_start', 'tb_drag_' + cl[0]);
classItems[i].classList.add(cl[1]);
this.classList.add('tb_draggable_item');
if (isColumnMove === true) {
this.parentNode.classList.add('tb_column_drag_inner');
const innsers = builder.querySelectorAll('.row_inner,.module_subrow');
for (let i = innsers.length - 1; i > -1; --i) {
let childs = innsers[i].children,
w = innsers[i].getBoundingClientRect().width - 5;
for (let j = childs.length - 1; j > -1; --j) {
if (childs[j].classList.contains('module_column') && (childs[j].offsetWidth + childs[j].offsetLeft) < w) {
childs[j].classList.add('tb_hide_drag_col_right');
ghostClone.style.top = e.clientY + 'px';
e.stopImmediatePropagation();
e.stopImmediatePropagation();
let dropped = e.target || e;
if (dropped.classList.contains('module_column') || dropped.classList.contains('tb_col_side')) {
dropped = isColumnMove ? dropped.closest('.module_column') : dropped.querySelector('[data-pos]');
for (let items = doc.tfClass('tb_column_drag_inner'), i = items.length - 1; i > -1; --i) {
items[i].classList.remove('tb_column_drag_inner');
else if(dropped.classList.contains('tb_active_builder')){
const row=dropped.firstElementChild;
dropped=row.dataset.pos?row:dropped.lastElementChild.previousElementSibling;
else if (dropped.classList.contains('tb_dragger')) {
dropped = dropped.closest('[draggable]');
if (dropped === holder || dropped.classList.contains('tb_sortable_placeholder')) {
dropped = dropped?.closest('.tb_active_builder')?.querySelector('[data-pos]');
if (dropped?.classList.contains('tb_sortable_placeholder')) {
dropped = dropped.closest('.tb_holder');
if (!dropped || (type === 'module' && dropped.classList.contains('module_row'))) {
target.classList.remove('tb_draggable_item');
let draggedRow=target.closest('.module_row'),
isSort= draggedRow!==null,
dragged = isSort?target:target.cloneNode(true),
side = dropped.dataset.pos;
target.classList.remove('tb_draggable_item');
api.undoManager.start('move');
target.classList.remove('tb_draggable_item');//don't change position,should be after undomanager start,need for undo
const builderEditSlug=api.isVisual?undefined:window.TB_BuilderContentLightbox?.getActiveEl()?.manager.get('mod_name');
dragged.style.display='none';
else if(dragged.classList.contains('active_subrow')){
const parent=dragged.parentNode,
parentCl=parent.classList;
if(parent.childElementCount===1 && (parentCl.contains('tab-content') || parentCl.contains('accordion-content'))){
const dummy=createElement();
api.Drop.row(dummy,'grid',1,false);
if (!dropped.classList.contains('tb_holder')) {
const parentCl=dropped.parentNode.classList;
if(type==='module' && (parentCl.contains('tab-content') || parentCl.contains('accordion-content')|| ( (builderEditSlug==='accordion' || builderEditSlug==='tab') && !dragged.classList.contains('active_subrow') && !dropped.closest('.module_subrow')))){
const subrow=new api.Subrow({cols:[{}]});
subrow.el.tfClass('tb_holder')[0].appendChild(dragged);
side === 'top' ?dropped.before(subrow.el):dropped.after(subrow.el);
side === 'top' ?dropped.before(dragged):dropped.after(dragged);
dropped.appendChild(dragged);
if(isColumnMove || isSort){
await api.Drop.column(dragged, dropped, side);
Themify.trigger('tb_' + type + '_sort', [dragged]);
api.Utils.onResize(true);
api.undoManager.end('move');
else{//new element: dragged element will be replaced
let dropType=targetCl.contains('tb_grid')?'grid':(targetCl.contains('page_break_module')?'pagebreak':'predesign'),
slug=target.dataset.slug,
dropHandler=dropType==='grid'?'row':type;
dropType=target.dataset.type;
if(dropHandler==='row' && targetCl.contains('library_item')){
await api.Drop[dropHandler](dragged,dropType,slug);
Themify.trigger('tb_' + type + '_sort', [dragged]);
if(dropHandler==='module' && dropType !== 'part' && dropType !== 'module'){
api.undoManager.clear('move');
api.undoManager.end('move');
api.undoManager.clear('move');
if (targetCl.contains('active_subrow')) {
cl.push('tb_drag_subrow');
bodyCl.add('tb_drag_row');
ghostClone = ghost.cloneNode();
const b = target.getBoundingClientRect();
ghostClone.style.width = b.width + 'px';
ghostClone.style.left = b.left + 'px';
ghostClone.innerHTML = 'Row';
body.appendChild(ghostClone);
ghostCloneH = ghostClone.offsetHeight / 2;
else if (type === 'module' || isColumnMove) {
if (isColumnMove || targetCl.contains('active_subrow')) {