Upload folder via GUI - assets

This commit is contained in:
Git Manager GUI
2026-04-13 18:52:44 +02:00
parent b6394e5495
commit 9c47501712
4 changed files with 806 additions and 0 deletions

215
assets/js/admin.js Normal file
View File

@@ -0,0 +1,215 @@
/* WP Multi Formular - Admin JS v2.0 */
(function($){
'use strict';
var fields=[],activeIndex=null,multiStep=false,stepCount=1;
$(document).ready(function(){
var $cv=$('#wmf-canvas'); if(!$cv.length) return;
var raw=$cv.data('fields'); if(raw&&Array.isArray(raw)&&raw.length) fields=raw;
multiStep=$('#wmf-multistep-toggle').is(':checked');
stepCount=calcSteps();
renderCanvas(); initSortable(); initPalette(); initTabs();
initFormSubmit(); initPreview(); initShortcodeCopy();
initPaletteSearch(); initSettingsClose(); initMultiStepToggle();
});
function renderCanvas(){
var $l=$('#wmf-field-list'),$e=$('#wmf-canvas-empty');
$l.empty();
if(!fields.length){ $e.removeClass('wmf-hidden'); }
else { $e.addClass('wmf-hidden'); $.each(fields,function(i,f){ $l.append(buildRow(f,i)); }); }
updateHighlight(); updateStepLabels();
}
function buildRow(field,index){
var def=getDef(field.type)||{icon:'dashicons-edit'};
var lbl=field.label||WMF.i18n.no_label;
var req=(field.required==='1')?'<span class="wmf-field-req-mark">*</span>':'';
var cond=(field.conditional_logic==='1')?'<span title="Bedingte Logik" style="color:#2271b1;font-size:12px;">&#9889;</span>':'';
var step=multiStep?'<select class="wmf-step-select" data-index="'+index+'" title="Schritt">'+stepOpts(field.step||0)+'</select>':'';
return $('<div>').addClass('wmf-canvas-field').attr('data-index',index).html(
'<span class="wmf-drag-handle dashicons dashicons-menu"></span>'+
'<span class="wmf-field-type-icon dashicons '+esc(def.icon)+'"></span>'+
'<span class="wmf-field-label">'+esc(lbl)+req+'</span>'+
cond+step+
'<span class="wmf-field-type-badge">'+esc(field.type)+'</span>'+
'<button type="button" class="wmf-field-del">&#10005;</button>'
).on('click',function(e){
if($(e.target).is('.wmf-field-del,.wmf-step-select')) return;
selectField(index);
});
}
function stepOpts(cur){ var h=''; for(var i=0;i<stepCount;i++) h+='<option value="'+i+'" '+(cur===i?'selected':'')+'>S'+(i+1)+'</option>'; return h; }
function calcSteps(){ var m=0; $.each(fields,function(i,f){ if((f.step||0)>m) m=f.step||0; }); return m+1; }
function selectField(index){
activeIndex=index; updateHighlight();
loadSettings(index);
$('#wmf-form-settings-panel').hide(); $('#wmf-field-settings-panel').show();
}
function updateHighlight(){
$('.wmf-canvas-field').removeClass('wmf-active');
if(activeIndex!==null) $('.wmf-canvas-field[data-index="'+activeIndex+'"]').addClass('wmf-active');
}
function deselectField(){
activeIndex=null; $('.wmf-canvas-field').removeClass('wmf-active');
$('#wmf-field-settings-panel').hide(); $('#wmf-form-settings-panel').show();
}
function loadSettings(index){
var field=fields[index];
$('#wmf-field-settings-title').text((field.label||field.type)+' Einstellungen');
$('#wmf-field-settings-body').html('<p class="wmf-loading-msg">'+WMF.i18n.loading+'</p>');
$.post(WMF.ajax_url,{action:'wmf_get_field_settings',nonce:WMF.nonce,field_type:field.type,field_data:JSON.stringify(field)},function(res){
if(!res.success){ $('#wmf-field-settings-body').html('<p style="color:red">Fehler beim Laden.</p>'); return; }
$('#wmf-field-settings-body').html(res.data.html);
bindSettings(index); initOptsEditor(index); initCondUI(index);
}).fail(function(){ $('#wmf-field-settings-body').html('<p style="color:red">AJAX-Fehler.</p>'); });
}
function bindSettings(index){
$('#wmf-field-settings-body').find('[data-setting]').off('input change').on('input change',function(){
var k=$(this).data('setting'),v=$(this).is(':checkbox')?($(this).is(':checked')?'1':'0'):$(this).val();
fields[index][k]=v;
$('.wmf-canvas-field[data-index="'+index+'"]').replaceWith(buildRow(fields[index],index));
updateHighlight();
});
$(document).off('change.ct').on('change.ct','[data-setting="conditional_logic"]',function(){
$(this).closest('.wmf-field-setting').nextAll('.wmf-conditional-rules').first().toggle($(this).val()==='1');
});
}
function initOptsEditor(index){
var field=fields[index];
if(['select','checkbox','radio'].indexOf(field.type)===-1) return;
var $body=$('#wmf-field-settings-body');
var $w=$('<div class="wmf-field-setting"><label>Optionen</label><div class="wmf-opts-list"></div><button type="button" class="button wmf-add-opt">+ Option</button></div>');
$body.append($w);
function render(){
var $l=$w.find('.wmf-opts-list').empty();
$.each(field.options||[],function(i,opt){
var $r=$('<div class="wmf-opt-row"><input type="text" class="ol" placeholder="Bezeichnung" value="'+esc(opt.label)+'"><input type="text" class="ov" placeholder="Wert" value="'+esc(opt.value)+'"><button type="button" class="wmf-opt-del">x</button></div>');
$r.find('.ol').on('input',function(){ field.options[i].label=$(this).val(); fields[index]=field; });
$r.find('.ov').on('input',function(){ field.options[i].value=$(this).val(); fields[index]=field; });
$r.find('.wmf-opt-del').on('click',function(){ field.options.splice(i,1); fields[index]=field; render(); });
$l.append($r);
});
}
render();
$w.find('.wmf-add-opt').on('click',function(){
if(!field.options) field.options=[];
var n=field.options.length+1; field.options.push({label:'Option '+n,value:'option_'+n});
fields[index]=field; render();
});
}
function initCondUI(index){
var $rl=$('.wmf-conditional-rule-list'); if(!$rl.length) return;
var opts='<option value="">Feld auswaehlen</option>';
$.each(fields,function(i,f){ if(i!==index) opts+='<option value="'+esc(f.id)+'">'+esc(f.label||f.id)+'</option>'; });
$rl.find('.wmf-rule-field').each(function(){ var v=$(this).val(); $(this).html(opts); if(v) $(this).val(v); });
function sync(){
var r=[];
$rl.find('.wmf-rule-row').each(function(){
r.push({field:$(this).find('.wmf-rule-field').val(),operator:$(this).find('.wmf-rule-op').val(),value:$(this).find('.wmf-rule-value').val()});
});
fields[index].conditional_rules=r;
}
$(document).off('click.ar').on('click.ar','.wmf-add-rule',function(){
var $r=$('<div class="wmf-rule-row"><select class="wmf-rule-field">'+opts+'</select><select class="wmf-rule-op"><option value="=">ist</option><option value="!=">ist nicht</option><option value="contains">enthaelt</option><option value="not_empty">ist ausgefuellt</option></select><input type="text" class="wmf-rule-value" placeholder="Wert"><button type="button" class="wmf-rule-remove">x</button></div>');
$rl.append($r); sync();
});
$(document).off('click.rr').on('click.rr','.wmf-rule-remove',function(){ $(this).closest('.wmf-rule-row').remove(); sync(); });
$(document).off('change.sr input.sr').on('change.sr input.sr','.wmf-rule-field,.wmf-rule-op,.wmf-rule-value',sync);
}
$(document).on('click','.wmf-field-del',function(e){
e.stopPropagation();
if(!confirm(WMF.i18n.confirm_delete)) return;
var idx=parseInt($(this).closest('.wmf-canvas-field').data('index'));
fields.splice(idx,1);
if(activeIndex===idx){ activeIndex=null; deselectField(); } else if(activeIndex>idx) activeIndex--;
renderCanvas(); initSortable();
});
function initSettingsClose(){
$('#wmf-field-settings-close').on('click',deselectField);
$('#wmf-delete-field-btn').on('click',function(){
if(activeIndex===null) return;
if(!confirm(WMF.i18n.confirm_delete)) return;
fields.splice(activeIndex,1); activeIndex=null; deselectField(); renderCanvas(); initSortable();
});
}
function initPalette(){
$(document).on('click','.wmf-palette-item',function(){ addField($(this).data('type')); });
$(document).on('dragstart','.wmf-palette-item',function(e){ e.originalEvent.dataTransfer.setData('text/plain',$(this).data('type')); });
var $cv=$('#wmf-canvas');
$cv.on('dragover',function(e){ e.preventDefault(); $cv.addClass('drag-over'); });
$cv.on('dragleave drop',function(){ $cv.removeClass('drag-over'); });
$cv.on('drop',function(e){ e.preventDefault(); var t=e.originalEvent.dataTransfer.getData('text/plain'); if(t) addField(t); });
}
function addField(type){
var def=getDef(type); if(!def) return;
var f=$.extend(true,{},def.defaults);
f.id='field_'+Math.random().toString(36).substr(2,8); f.name=f.id; f.label=def.label; f.step=0;
fields.push(f); activeIndex=fields.length-1;
renderCanvas(); initSortable(); selectField(activeIndex);
}
function initSortable(){
$('#wmf-field-list').sortable({
handle:'.wmf-drag-handle',placeholder:'wmf-canvas-field ui-sortable-placeholder',tolerance:'pointer',
update:function(){
var r=[];
$('#wmf-field-list .wmf-canvas-field').each(function(){ r.push(fields[parseInt($(this).data('index'))]); });
fields=r; activeIndex=null; renderCanvas(); deselectField();
}
});
}
$(document).on('change','.wmf-step-select',function(){
fields[parseInt($(this).data('index'))].step=parseInt($(this).val());
stepCount=calcSteps(); updateStepLabels();
});
function updateStepLabels(){
stepCount=calcSteps(); var $sl=$('#wmf-step-labels'); if(!$sl.length) return;
while($sl.find('input').length<stepCount){
var n=$sl.find('input').length+1;
$sl.append('<div class="wmf-sg"><label>Schritt '+n+'</label><input type="text" name="step_labels[]" placeholder="Schritt '+n+'" class="widefat"></div>');
}
}
function initMultiStepToggle(){
$('#wmf-multistep-toggle').on('change',function(){ multiStep=$(this).is(':checked'); renderCanvas(); });
$('#wmf-add-step-label').on('click',function(){ stepCount++; updateStepLabels(); });
}
function initTabs(){
$(document).on('click','.wmf-tab',function(){
var t=$(this).data('tab'),$p=$(this).closest('.wmf-panel,.wmf-panel-body');
$p.find('.wmf-tab').removeClass('active'); $p.find('.wmf-tab-pane').removeClass('active');
$(this).addClass('active'); $p.find('.wmf-tab-pane[data-tab="'+t+'"]').addClass('active');
});
}
function initFormSubmit(){
$('#wmf-builder-form').on('submit',function(){ $('#wmf-form-fields-json').val(JSON.stringify(fields)); });
}
function initPreview(){
$('#wmf-preview-btn').on('click',function(){
var $o=$('#wmf-preview-overlay'),$c=$('#wmf-preview-content');
$o.show(); $c.html('<p style="text-align:center;padding:30px;color:#999">Lade Vorschau...</p>');
$.post(WMF.ajax_url,{action:'wmf_preview_form',nonce:WMF.nonce,form_id:$('input[name=form_id]').val()||0,fields:JSON.stringify(fields)},function(res){
$c.html(res.success?res.data.html:'<p style="color:red">Vorschau-Fehler.</p>');
});
});
$('#wmf-preview-overlay').on('click',function(e){ if($(e.target).is(this)) $(this).hide(); });
$(document).on('click','#wmf-preview-close',function(){ $('#wmf-preview-overlay').hide(); });
}
function initShortcodeCopy(){
$(document).on('click','.wmf-sc-copy,.wmf-sc-badge',function(){
var t=$(this).text().trim();
if(navigator.clipboard) navigator.clipboard.writeText(t).then(function(){ toast('Shortcode kopiert!'); });
});
}
function initPaletteSearch(){
$('#wmf-palette-search').on('input',function(){
var term=$(this).val().toLowerCase();
$('.wmf-palette-item').each(function(){ $(this).toggleClass('wmf-hidden',term!==''&&$(this).data('label').toLowerCase().indexOf(term)===-1); });
});
}
function getDef(type){ return WMF.fields.find(function(f){ return f.type===type; })||null; }
function esc(s){ return String(s||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;'); }
function toast(msg){
var $t=$('<div style="position:fixed;bottom:24px;right:24px;background:#2271b1;color:#fff;padding:10px 20px;border-radius:4px;z-index:99999;font-size:14px;opacity:0;transition:opacity .3s;">'+msg+'</div>').appendTo('body');
setTimeout(function(){$t.css('opacity',1);},10);
setTimeout(function(){$t.css('opacity',0);setTimeout(function(){$t.remove();},400);},2200);
}
})(jQuery);

259
assets/js/frontend.js Normal file
View File

@@ -0,0 +1,259 @@
/* WP Multi Formular Frontend JS v2.0 */
(function($){
'use strict';
$(document).ready(function(){
$('.wmf-form').each(function(){ WMF_Form.init($(this)); });
});
var WMF_Form = {
init: function($form){
this.initConditional($form);
this.initMultiStep($form);
this.initRating($form);
this.initSignature($form);
this.initRange($form);
this.initCharCount($form);
this.initLiveValidation($form);
this.initSubmit($form);
},
/* BEDINGTE LOGIK */
initConditional: function($form){
var self = this;
var $fields = $form.find('[data-condition="1"]');
if(!$fields.length) return;
function evalAll(){
$fields.each(function(){
var $field = $(this);
var action = $field.data('condition-action') || 'show';
var match = $field.data('condition-match') || 'all';
var rules = $field.data('condition-rules');
if(typeof rules === 'string'){ try{ rules=JSON.parse(rules); }catch(e){ rules=[]; } }
if(!rules||!rules.length) return;
var results = $.map(rules, function(rule){
if(!rule.field) return true;
var $t = $form.find('[name="wmf_fields['+rule.field+']"],[name="wmf_fields['+rule.field+'][]"]');
var val = '';
if($t.is('[type=checkbox]')){ var c=[]; $t.filter(':checked').each(function(){ c.push($(this).val()); }); val=c; }
else if($t.is('[type=radio]')){ val=$t.filter(':checked').val()||''; }
else { val=$t.val()||''; }
switch(rule.operator){
case '=': return Array.isArray(val)?val.indexOf(rule.value)!==-1:val===rule.value;
case '!=': return Array.isArray(val)?val.indexOf(rule.value)===-1:val!==rule.value;
case 'contains': return (Array.isArray(val)?val.join(','):val).indexOf(rule.value)!==-1;
case 'not_empty':return Array.isArray(val)?val.length>0:val.trim()!=='';
default: return true;
}
});
var passed = (match==='all') ? results.every(Boolean) : results.some(Boolean);
var $wrap = $field.closest('.wmf-field-wrap');
var hide = (action==='show') ? !passed : passed;
$wrap.toggleClass('wmf-cond-hidden', hide);
$wrap.find('input,select,textarea').prop('disabled', hide);
});
}
$form.on('change input','input,select,textarea', evalAll);
evalAll();
},
/* MULTI STEP */
initMultiStep: function($form){
var ms = $form.data('multi-step');
if(ms!==1&&ms!=='1') return;
var self = this;
var $steps = $form.find('.wmf-step');
var total = $steps.length;
var current = 0;
var $prog = $form.closest('.wmf-form-wrap').find('.wmf-progress-bar');
function show(idx){
$steps.hide().eq(idx).show();
current = idx;
$prog.find('.wmf-step-indicator').each(function(i){
$(this).toggleClass('active',i===idx).toggleClass('done',i<idx);
});
$('html,body').animate({scrollTop:$form.closest('.wmf-form-wrap').offset().top-60},300);
}
$form.on('click','.wmf-next-step',function(){
if(!self.validateStep($form.find('.wmf-step').eq(current))) return;
show(current+1);
});
$form.on('click','.wmf-prev-step',function(){ show(current-1); });
show(0);
},
validateStep: function($step){
var valid=true, $first=null;
$step.find('.wmf-field-wrap:not(.wmf-cond-hidden)').each(function(){
var $w=$( this);
var $i=$w.find('input:not([type=hidden]),select,textarea').first();
if(!$i.length) return;
var r=WMF_Validate.field($i,$w);
if(r!==true){
$w.addClass('wmf-has-error');
$w.find('.wmf-field-error-msg').text(r).show();
if(!$first) $first=$i;
valid=false;
}
});
if($first) $first.focus();
return valid;
},
/* LIVE VALIDIERUNG */
initLiveValidation: function($form){
$form.on('blur','input:not([type=hidden]),select,textarea',function(){
var $w=$(this).closest('.wmf-field-wrap');
if(!$w.length) return;
var r=WMF_Validate.field($(this),$w);
if(r===true){ $w.removeClass('wmf-has-error'); $w.find('.wmf-field-error-msg').hide(); }
else { $w.addClass('wmf-has-error'); $w.find('.wmf-field-error-msg').text(r).show(); }
});
$form.on('input change','input:not([type=hidden]),select,textarea',function(){
var $w=$(this).closest('.wmf-field-wrap');
if($w.hasClass('wmf-has-error')){
if(WMF_Validate.field($(this),$w)===true){ $w.removeClass('wmf-has-error'); $w.find('.wmf-field-error-msg').hide(); }
}
});
},
/* SUBMIT */
initSubmit: function($form){
$form.on('submit',function(e){
var valid=true,$first=null;
$form.find('.wmf-field-wrap:not(.wmf-cond-hidden)').each(function(){
var $w=$(this),$i=$w.find('input:not([type=hidden]),select,textarea').first();
if(!$i.length) return;
var r=WMF_Validate.field($i,$w);
if(r!==true){
$w.addClass('wmf-has-error');
$w.find('.wmf-field-error-msg').text(r).show();
if(!$first) $first=$i;
valid=false;
}
});
if(!valid){
e.preventDefault();
if($first) $('html,body').animate({scrollTop:$first.closest('.wmf-field-wrap').offset().top-80},300);
return;
}
// Unterschrift
$form.find('.wmf-signature-canvas').each(function(){
var $c=$(this);
if($c.data('drawn')) $c.closest('.wmf-signature-wrap').find('.wmf-signature-data').val(this.toDataURL('image/png'));
});
$form.addClass('wmf-loading');
$form.find('.wmf-submit-button').prop('disabled',true);
});
},
/* STERNE */
initRating: function($form){
$form.on('mouseenter','.wmf-star',function(){
var v=parseInt($(this).data('value'));
$(this).closest('.wmf-rating').find('.wmf-star').each(function(){ $(this).toggleClass('hover',parseInt($(this).data('value'))<=v); });
});
$form.on('mouseleave','.wmf-rating',function(){ $(this).find('.wmf-star').removeClass('hover'); });
$form.on('click','.wmf-star',function(){
var v=$(this).data('value');
var $r=$(this).closest('.wmf-rating');
$r.find('.wmf-rating-value').val(v).trigger('change');
$r.find('.wmf-star').each(function(){ $(this).toggleClass('active',parseInt($(this).data('value'))<=parseInt(v)); });
});
},
/* UNTERSCHRIFT */
initSignature: function($form){
$form.find('.wmf-signature-canvas').each(function(){
var canvas=this, ctx=canvas.getContext('2d'), drawing=false;
var dpr=window.devicePixelRatio||1;
var rect=canvas.getBoundingClientRect();
canvas.width=rect.width*dpr; canvas.height=rect.height*dpr;
ctx.scale(dpr,dpr);
ctx.strokeStyle='#1d2327'; ctx.lineWidth=2; ctx.lineCap='round'; ctx.lineJoin='round';
function pos(e){ var r=canvas.getBoundingClientRect(),s=e.touches?e.touches[0]:e; return{x:s.clientX-r.left,y:s.clientY-r.top}; }
function start(e){ e.preventDefault(); drawing=true; var p=pos(e); ctx.beginPath(); ctx.moveTo(p.x,p.y); }
function move(e){ e.preventDefault(); if(!drawing)return; var p=pos(e); ctx.lineTo(p.x,p.y); ctx.stroke(); $(canvas).data('drawn',true); }
function stop(){ drawing=false; }
canvas.addEventListener('mousedown',start);
canvas.addEventListener('mousemove',move);
canvas.addEventListener('mouseup',stop);
canvas.addEventListener('mouseleave',stop);
canvas.addEventListener('touchstart',start,{passive:false});
canvas.addEventListener('touchmove',move,{passive:false});
canvas.addEventListener('touchend',stop);
$(canvas).closest('.wmf-signature-wrap').find('.wmf-sig-clear').on('click',function(){
ctx.clearRect(0,0,canvas.width,canvas.height);
$(canvas).data('drawn',false);
$(canvas).closest('.wmf-signature-wrap').find('.wmf-signature-data').val('');
});
});
},
/* SCHIEBEREGLER */
initRange: function($form){
$form.on('input','.wmf-range-input',function(){
$(this).closest('.wmf-range-wrap').find('.wmf-range-value').text($(this).val());
});
},
/* ZEICHENZÄHLER */
initCharCount: function($form){
$form.find('textarea[maxlength]').each(function(){
var $ta=$(this), max=parseInt($ta.attr('maxlength'));
var $c=$ta.closest('.wmf-field').find('.wmf-char-count .wmf-chars-used');
$ta.on('input',function(){ var l=$(this).val().length; $c.text(l); $c.closest('.wmf-char-count').toggleClass('wmf-over-limit',l>=max); });
});
}
};
/* VALIDIERUNG */
var WMF_Validate = {
field: function($i,$w){
var req=$i.prop('required'), type=$i.attr('type')||$i.prop('tagName').toLowerCase(), val=$i.val();
var i18n=(typeof WMF_Frontend!=='undefined'&&WMF_Frontend.i18n)||{};
if(type==='checkbox'){
var $boxes=$w.find('input[type=checkbox]');
if($boxes.first().prop('required')&&!$boxes.filter(':checked').length) return i18n.required||'Pflichtfeld.';
return true;
}
if(type==='radio'){
var $radios=$w.find('input[type=radio]');
if($radios.first().prop('required')&&!$radios.filter(':checked').length) return i18n.required||'Pflichtfeld.';
return true;
}
if($i.is('select[multiple]')){
if(req&&(!val||!val.length)) return i18n.required||'Pflichtfeld.';
return true;
}
if(req&&(!val||val.trim()==='')) return i18n.required||'Pflichtfeld.';
if(!val||val.trim()==='') return true;
if(type==='email'&&!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val)) return i18n.email||'Ungültige E-Mail.';
if(type==='url'){ try{ new URL(val); }catch(e){ return i18n.url||'Ungültige URL.'; } }
return true;
}
};
/* SHORTCODE KOPIEREN */
$(document).on('click','.wmf-sc-copy',function(){
var t=$(this).text().trim();
if(navigator.clipboard) navigator.clipboard.writeText(t).then(function(){ WMF_Form.toast && WMF_Form.toast('Shortcode kopiert!'); });
});
WMF_Form.toast = function(msg){
var $t=$('<div class="wmf-toast">'+msg+'</div>').appendTo('body');
setTimeout(function(){$t.addClass('show');},10);
setTimeout(function(){$t.removeClass('show');setTimeout(function(){$t.remove();},400);},2500);
};
})(jQuery);