: 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
ghost.innerHTML = isColumnMove ? 'Column' : 'Subrow';
const slug = target.dataset.slug || Registry.get(target.dataset.cid).get('mod_name'),
m=themifyBuilder.modules[slug];
name = createElement('span','tf_vmiddle',m.name);
ghost.appendChild(api.Helper.getIcon('ti-' + icon));
else if (type === 'column') {
ghost.className+=' '+target.className;
ghost.innerHTML=target.innerHTML;
else if (type === 'row' && (targetCl.contains('page_break_module') || targetCl.contains('predesigned_row'))) {
const tmpCl = targetCl.contains('page_break_module') ? 'page_break_title' : 'predesigned_title';
ghost.textContent = target.tfClass(tmpCl)[0].textContent;
holder = createElement('','tb_sortable_placeholder tf_rel tf_w');
ghost.style.top='-1000px';
ghost.tfClass('add_module_btn')[0]?.remove();
e.dataTransfer.effectAllowed='move';
e.dataTransfer.setData('Text', 'id');//required for touch dnd
e.dataTransfer.setDragImage(ghost, (ghost.offsetWidth / 2) + 2, (ghost.offsetHeight / 2));
target.tfOn('dragend', function (e) {
e.stopImmediatePropagation();
body.tfOff('dragover', onDragOver);
builder.tfOff(['dragenter', 'dragleave','pointermove','pointerover','pointerout','pointerenter','pointerleave','mousemove','mouseover','mouseout','mouseenter','mouseleave'], mouseEvent, {
this.tfOff('drag', onDragStart, {
const dropped = builder.querySelector('[data-pos]');
for (let items = doc.querySelectorAll('[data-drag-w],[data-drag-area],[data-pos]'), i = items.length - 1; i > -1; --i) {
items[i].removeAttribute('data-pos');
items[i].removeAttribute('data-drag-w');
items[i].removeAttribute('data-drag-area');
for (let items = doc.querySelectorAll('.tb_hide_drag_col_right,.tb_drag_one_column,.tb_drag_side_column,.tb_column_drag_inner'), i = items.length - 1; i > -1; --i) {
items[i].classList.remove('tb_hide_drag_col_right', 'tb_drag_one_column', 'tb_drag_side_column', 'tb_column_drag_inner');
this.classList.remove('tb_draggable_item', 'tb_drag_one_column', 'tb_drag_side_column');
for(let drops=doc.tfClass('is-drop-target'),i=drops.length-1;i>-1;--i){
drops[i].classList.remove('is-drop-target');
for(let i=classItems.length-1;i>-1;--i){
classItems[i].classList.remove('tb_start_animate', 'tb_drag_start','tb_drag_start_'+cl[0], 'tb_drag_' + cl[0]);
classItems[i].classList.remove(cl[1]);
holder = isDropped = clicked = target = targetCl = prevItem = ghost = ghostClone = ghostCloneH = builder = x = y = cl = type = isColumnMove = classItems = null;
for(let i=classItems.length-1;i>-1;--i){
classItems[i].classList.add('tb_drag_start_'+cl[0]);
classItems[i].classList.add(cl[1]);
target.tfOn('drag', onDragStart, {
body.tfOn('dragover', onDragOver);
builder.tfOn('dragenter dragleave', mouseEvent, {
builder.tfOn(['pointermove','pointerover','pointerout','pointerenter','pointerleave','mousemove','mouseover','mouseout','mouseenter','mouseleave'], mouseEvent, {
row_inner = el.parentNode,
computed = getComputedStyle(row_inner),
childs=api.Utils.getColumns(row_inner),
childCount = childs.length,
row_w = row_inner.offsetWidth,
dir = target.classList.contains('tb_drag_right') ? 'w' : 'e',
rtlDir=Themify.isRTL?(dir==='w'?'e':'w'):dir,
tooltip1 = createElement('', 'tb_grid_drag_tooltip'),
tooltip2 = tooltip1.cloneNode(false),
dragColName = getComputedStyle(el).getPropertyValue('grid-area').split('/')[0].replace('"', '').trim(),
area = dragColName && dragColName !== 'auto' && dragColName !== 'initial' && dragColName !== 'none'? computed.getPropertyValue('--area').replace(/[\r\n]/gm, '').replace(/ +/g, ' ').trim().split('" "') : '',
gutterVal = computed.getPropertyValue('column-gap'),
gutter = parseFloat(gutterVal) || 0,
cols = computed.getPropertyValue('--col').replace(/\s\s+/g, ' ').trim(),
Themify.trigger('disableInline');
else if (cols.includes('repeat')) {
if (!cols.includes('auto-fit') && !cols.includes('auto-fill')) {
repeat = cols.replace(/\s\,\s|\s\,|\,\s/g, ',').replace(/\s\(\s|\s\(|\(\s/g, '(').replaceAll(' )', ')').trim().split(' ');
for (let i = 0; i < repeat.length; ++i) {
if (repeat[i].includes('repeat')) {
let item = repeat[i].split('(')[1].replace(')', '').split(','),
tmp += ' ' + (' ' + unit).repeat(count);
for (let i = area.length - 1; i > -1; --i) {
if (area[i].includes(dragColName)) {
let arr = area[i].replace(/\s\s+/g, ' ').replaceAll('"', '').trim().split(' ');
for (let j = arr.length - 1; j > -1; --j) {
if (arr[j] === dragColName) {
if (dragIndexes.length > 0) {
if (dragIndexes.length > 0) {
const dragNextAreaIndex = rtlDir === 'w'? Math.max.apply(null, dragIndexes) + 1 : Math.min.apply(null, dragIndexes) - 1,
dragNextColName = area[row].replace(/\s\s+/g, ' ').replaceAll('"', '').trim().split(' ')[dragNextAreaIndex]?.trim();
for (let i = area.length - 1; i > -1; --i) {
if (area[i].includes(dragNextColName)) {
let arr = area[i].replace(/\s\s+/g, ' ').replaceAll('"', '').trim().split(' ');
for (let j = arr.length - 1; j > -1; --j) {
if (arr[j] === dragNextColName) {
if (dragNextIndexes.length > 0) {
for (let i = childs.length - 1; i > -1; --i) {
if (el !== childs[i] && dragNextColName === getComputedStyle(childs[i]).getPropertyValue('grid-area').split('/')[0].replace('"', '').trim()) {
const areaLength = area[0].trim().split(' ').length;
cols = ('1fr '.repeat(areaLength)).trim();
const diffLength = areaLength - cols.split(' ').length;
cols += ' 1fr'.repeat(diffLength);
cell = el.previousElementSibling || el.nextElementSibling;
cell = el.nextElementSibling || el.previousElementSibling;
for (let i = 0; i < childs.length; ++i) {
gridWidth.push(childs[i].getBoundingClientRect().width);
const min = Math.min.apply(null, gridWidth).toFixed(2);
for (let i = gridWidth.length - 1; i > -1; --i) {
gridWidth[i] = min === gridWidth[i].toFixed(2)? '1fr' : ((gridWidth[i] / min).toFixed(2) + 'fr');
cols = gridWidth.join(' ');
const _childs = Themify.convert(childs);
dragIndexes.push(_childs.indexOf(el));
dragNextIndexes.push(_childs.indexOf(cell));
if (!cols[dragIndexes[0]]) {
dragIndexes[0]%= cols.length;
if (!cols[dragNextIndexes[0]]) {
dragNextIndexes[0]%=cols.length;
let colsLen = cols.length,
if (gutterVal && !gutterVal.includes('%')) {
if (gutterVal.includes('px')) {
gutterPX=parseInt(gutter);
summPx =(colsLen - 1) * gutterPX;
else if (gutterVal.includes('em')) {
summEM = (colsLen - 1) * gutter;
gutterPX=computed.getPropertyValue('font-size')*gutter;
percent -= (colsLen - 1) * gutter;
gutterPX=row_w*(gutter/100);
for (let i = colsLen - 1; i > -1; --i) {
} else if (v.includes('%')) {
percent -= parseFloat(v);
} else if (v.includes('em')) {
} else if (v.includes('px')) {
summEM = parseFloat(computed.getPropertyValue('font-size')) * summEM;
target.classList.add('tb_drag_grid_current');
el.classList.add('tb_current_module');
tooltip1.className += ' tb_grid_drag_right_tooltip';
tooltip2.className += ' tb_grid_drag_left_tooltip';
tooltip1.className += ' tb_grid_drag_left_tooltip';
tooltip2.className += ' tb_grid_drag_right_tooltip';
el.style.willChange='width';
cell.style.willChange='width';
tooltip1.style.willChange=tooltip2.style.willChange='contents';
_this.dragIndexes=dragIndexes;
_this.dragNextIndexes=dragNextIndexes;
_this.fr1 = parseFloat((parseFloat((row_w * percent) / 100) - summPx - summEM) / summFr);
_this.row_inner=row_inner;
_this.isSame=Registry.get(row_inner.closest('[data-cid]').dataset.cid).isLightboxOpen();
_this.elComputed=getComputedStyle(el);
_this.cellComputed=getComputedStyle(cell);
e.stopImmediatePropagation();
target.tfOn('lostpointercapture', e=> {
e.stopImmediatePropagation();
target.tfOff('pointermove', onDrag, {
.tfOn('pointermove', onDrag, {
.setPointerCapture(e.pointerId);
this.timer = requestAnimationFrame(() => {
let diff = ~~clientX - this.startX;
if (_this.isDragged !== true) {
//if(!_this.isSame || 1){
api.undoManager.start('style');
_this.target.append(_this.tooltip1,_this.tooltip2);
bodyCl.add('tb_start_animate', 'tb_drag_grid_start');
let fr = parseFloat(value / _this.fr1);
const {cols,dragIndexes,dragNextIndexes}=_this,
dragLen=dragIndexes.length,
dragNextLen = dragNextIndexes.length;
fr = parseFloat(fr / (dragLen + dragNextLen));
let v1 = parseFloat(cols[dragIndexes[0]]) + fr,
v2 = parseFloat(cols[dragNextIndexes[0]]) - fr;
if (v1 > .001 && v2 > .001) {
let floatV1=v1.toFixed(3),
for (let i = dragLen - 1; i > -1; --i) {
cols[dragIndexes[i]] = v1;
for (let i = dragNextLen - 1; i > -1; --i) {
cols[dragNextIndexes[i]] = v2;
_this.row_inner.style.setProperty('--col', cols.join(' '));
_this.tooltip1.textContent = floatV1 + 'fr / ' + parseInt(_this.elComputed.getPropertyValue('width')) + 'px';//parseInt(this.fr1*floatV1+this.gutterPX*(dragLen-1));
_this.tooltip2.textContent = floatV2 + 'fr / ' + parseInt(_this.cellComputed.getPropertyValue('width')) + 'px';//parseInt(this.fr1*floatV2+this.gutterPX*(dragNextLen-1));
cancelAnimationFrame(_this.timer);
requestAnimationFrame(()=> {
el.classList.remove('tb_current_module');
_this.target.classList.remove('tb_drag_grid_current');
cell.style.willChange='';
bodyCl.remove('tb_start_animate', 'tb_drag_grid_start');
const {row_inner,cols}=_this,
row = row_inner.closest('[data-cid]');
for (let i = cols.length - 1; i > -1; --i) {
cols[i] = parseFloat(parseFloat(cols[i]).toFixed(3).replace('0.', '.')).toString() + 'fr';
Registry.get(row.dataset.cid).setCols({size:cols.join(' ')});
row_inner.style.setProperty('--col', '');
api.Utils.setColumnsCount([el, cell]);
Themify.trigger('tb_grid_changed',row);
api.Utils.onResize(true);
// if(!_this.isSame|| 1){
api.undoManager.end('style');
})(tb_app,body,topBody,bodyCl,topWindowDoc);