"),S("#csf-codemirror-css").after(e),e.attr({rel:"stylesheet",id:"csf-codemirror-"+s.theme+"-css",href:s.cdnURL+"/theme/"+s.theme+".min.css",type:"text/css",media:"all"}),j.vars.code_themes.push(s.theme)),CodeMirror.modeURL=s.cdnURL+"/mode/%N/%N.min.js",CodeMirror.autoLoadMode(n,s.mode),n.on("change",function(e,t){i.val(n.getValue()).trigger("change")}),clearInterval(c))}))})},S.fn.csf_field_date=function(){return this.each(function(){var e=S(this),n=e.find("input"),i=e.find(".csf-date-settings").data("settings"),i=S.extend({},i,{showAnim:"",beforeShow:function(e,t){S(t.dpDiv).addClass("csf-datepicker-wrapper")},onClose:function(e,t){S(t.dpDiv).removeClass("csf-datepicker-wrapper")}});2===n.length&&(i=S.extend({},i,{onSelect:function(e){S(this),n.first();var t=n.first().attr("id")===S(this).attr("id")?"minDate":"maxDate",e=S.datepicker.parseDate(i.dateFormat,e);n.not(this).datepicker("option",t,e)}})),n.each(function(){var e=S(this);e.hasClass("hasDatepicker")&&e.removeAttr("id").removeClass("hasDatepicker"),e.datepicker(i)})})},S.fn.csf_field_datetime=function(){return this.each(function(){var e=S(this),i=e.find("input"),t=e.find(".csf-datetime-settings").data("settings"),t=S.extend({},t,{onReady:function(e,t,n){S(n.calendarContainer).addClass("csf-flatpickr")}});2===i.length&&(t=S.extend({},t,{onChange:function(e,t,n){"from"===S(n.element).data("type")?i.last().get(0)._flatpickr.set("minDate",e[0]):i.first().get(0)._flatpickr.set("maxDate",e[0])}})),i.each(function(){S(this).flatpickr(t)})})},S.fn.csf_field_fieldset=function(){return this.each(function(){S(this).find(".csf-fieldset-content").csf_reload_script()})},S.fn.csf_field_gallery=function(){return this.each(function(){var s,e=S(this),c=e.find(".csf-edit-gallery"),a=e.find(".csf-clear-gallery"),r=e.find("ul"),o=e.find("input");e.find("img");e.on("click",".csf-button, .csf-edit-gallery",function(e){var t=S(this),n=o.val(),t=t.hasClass("csf-edit-gallery")?"edit":"add",i="add"!=t||n.length?"gallery-edit":"gallery";e.preventDefault(),void 0!==_.wp&&_.wp.media&&_.wp.media.gallery&&("gallery"==i?(s=_.wp.media({library:{type:"image"},frame:"post",state:"gallery",multiple:!0})).open():(s=_.wp.media.gallery.edit('[gallery ids="'+n+'"]'),"add"==t&&s.setState("gallery-library")),s.on("update",function(e){r.empty();e=e.models.map(function(e){var e=e.toJSON(),t=(e.sizes&&e.sizes.thumbnail&&e.sizes.thumbnail.url?e.sizes.thumbnail:e).url;return r.append(' '),e.id});o.val(e.join(",")).trigger("change"),a.removeClass("hidden"),c.removeClass("hidden")}))}),a.on("click",function(e){e.preventDefault(),r.empty(),o.val("").trigger("change"),a.addClass("hidden"),c.addClass("hidden")})})},S.fn.csf_field_group=function(){return this.each(function(){function e(e){e.preventDefault();var t,n,i,s,e=c.children(".csf-cloneable-item").length;r.hide(),h&&h ')).append(t),s.append(n),s.append(i),c.children().eq(e.index()).after(s),j.helper.name_nested_replace(c.children(".csf-cloneable-item"),l),c.accordion("refresh"),c.csf_customizer_refresh(),c.csf_customizer_listen({closest:!0}),d&&u(c))}function t(e){e.preventDefault(),e=c.children(".csf-cloneable-item").length,a.hide(),r.hide(),p&&e-1 .csf-cloneable-item > .csf-cloneable-title",collapsible:!0,active:!1,animate:!1,heightStyle:"content",icons:{header:"csf-cloneable-header-icon fas fa-angle-right",activeHeader:"csf-cloneable-header-icon fas fa-angle-down"},activate:function(e,t){var i,s,n=t.newPanel,t=t.newHeader;n.length&&!n.data("opened")?(i=t.find(".csf-cloneable-value"),s=[],S.each(o,function(e,t){s.push(n.find('[data-depend-id="'+t+'"]'))}),S.each(s,function(e,t){t.on("change keyup csf.keyup",function(){var n=[];S.each(s,function(e,t){t=t.val();t&&n.push(t)}),n.length&&i.text(n.join(f))}).trigger("csf.keyup")}),n.csf_reload_script(),n.data("opened",!0),n.data("retry",!1)):n.data("retry")&&(n.csf_reload_script_retry(),n.data("retry",!1))}}),c.sortable({axis:"y",handle:".csf-cloneable-title,.csf-cloneable-sort",helper:"original",cursor:"move",placeholder:"widget-placeholder",start:function(e,t){c.accordion({active:!1}),c.sortable("refreshPositions"),t.item.children(".csf-cloneable-content").data("retry",!0)},update:function(e,t){j.helper.name_nested_replace(c.children(".csf-cloneable-item"),l),c.csf_customizer_refresh(),d&&u(c)}}),i.children(".csf-cloneable-add").on("click",function(e){e.preventDefault();var t=c.children(".csf-cloneable-item").length;r.hide(),h&&hOpenStreetMap contributors'}).addTo(a),r=L.marker(c.center,{draggable:!0}).addTo(a),o=function(e){n.val(e.lat),i.val(e.lng),s.val(a.getZoom())},a.on("click",function(e){r.setLatLng(e.latlng),o(e.latlng)}),a.on("zoom",function(){o(r.getLatLng())}),r.on("drag",function(){o(r.getLatLng())}),t.length||(t=S('[data-depend-id="'+e.find(".csf--address-field").data("address-field")+'"]')),f={},t.autocomplete({source:function(e,t){var n=e.term;n in f?t(f[n]):S.get("https://nominatim.openstreetmap.org/search",{format:"json",q:n},function(e){e=e.length?e.map(function(e){return{value:e.display_name,label:e.display_name,lat:e.lat,lon:e.lon}},"json"):[{value:"no-data",label:"No Results."}];f[n]=e,t(e)})},select:function(e,t){if("no-data"===t.item.value)return!1;t=L.latLng(t.item.lat,t.item.lon);a.panTo(t),r.setLatLng(t),o(t)},create:function(e,t){S(this).autocomplete("widget").addClass("csf-map-ui-autocomplate")}}),n.on("change",l=function(){var e=L.latLng(n.val(),i.val());a.panTo(e),r.setLatLng(e)}),i.on("change",l))})},S.fn.csf_field_link=function(){return this.each(function(){var i=S(this),e=i.find(".csf--link"),s=i.find(".csf--add"),c=i.find(".csf--edit"),a=i.find(".csf--remove"),r=i.find(".csf--result"),t=j.helper.uid("csf-wplink-textarea-");s.on("click",function(e){e.preventDefault(),_.wpLink.open(t)}),c.on("click",function(e){e.preventDefault(),s.trigger("click"),S("#wp-link-url").val(i.find(".csf--url").val()),S("#wp-link-text").val(i.find(".csf--text").val()),S("#wp-link-target").prop("checked","_blank"===i.find(".csf--target").val())}),a.on("click",function(e){e.preventDefault(),i.find(".csf--url").val("").trigger("change"),i.find(".csf--text").val(""),i.find(".csf--target").val(""),s.removeClass("hidden"),c.addClass("hidden"),a.addClass("hidden"),r.parent().addClass("hidden")}),e.attr("id",t).on("change",function(){var e=_.wpLink.getAttrs(),t=e.href,n=S("#wp-link-text").val(),e=e.target||"";i.find(".csf--url").val(t).trigger("change"),i.find(".csf--text").val(n),i.find(".csf--target").val(e),r.html('{url:"'+t+'", text:"'+n+'", target:"'+e+'"}'),s.addClass("hidden"),c.removeClass("hidden"),a.removeClass("hidden"),r.parent().removeClass("hidden")})})},S.fn.csf_field_media=function(){return this.each(function(){var n,i=S(this),s=i.find(".csf--button"),c=i.find(".csf--remove"),a=s.data("library")&&s.data("library").split(",")||"",r=!!i.hasClass("csf-assign-field-background")&&i.closest(".csf-field-background").find(".csf--auto-attributes");s.on("click",function(e){e.preventDefault(),void 0!==_.wp&&_.wp.media&&_.wp.media.gallery&&(n||(n=_.wp.media({library:{type:a}})).on("select",function(){var e=n.state().get("selection").first().attributes,t=s.data("preview-size")||"thumbnail";a.length&&-1===a.indexOf(e.subtype)&&-1===a.indexOf(e.type)||(i.find(".csf--id").val(e.id),i.find(".csf--width").val(e.width),i.find(".csf--height").val(e.height),i.find(".csf--alt").val(e.alt),i.find(".csf--title").val(e.title),i.find(".csf--description").val(e.description),t=void 0!==e.sizes&&void 0!==e.sizes.thumbnail&&"thumbnail"===t?e.sizes.thumbnail.url:void 0!==e.sizes&&void 0!==e.sizes.full?e.sizes.full.url:"image"===e.type?e.url:e.icon,r&&r.removeClass("csf--attributes-hidden"),c.removeClass("hidden"),i.find(".csf--preview").removeClass("hidden"),i.find(".csf--src").attr("src",t),i.find(".csf--thumbnail").val(t),i.find(".csf--url").val(e.url).trigger("change"))}),n.open())}),c.on("click",function(e){e.preventDefault(),r&&r.addClass("csf--attributes-hidden"),c.addClass("hidden"),i.find("input").val(""),i.find(".csf--preview").addClass("hidden"),i.find(".csf--url").trigger("change")})})},S.fn.csf_field_repeater=function(){return this.each(function(){function e(e){e.preventDefault();var t,n,i,e=s.children(".csf-repeater-item").length;r.hide(),f&&f ')).append(t),i.append(n),s.children().eq(e.index()).after(i),i.children(".csf-repeater-content").csf_reload_script(),j.helper.name_nested_replace(s.children(".csf-repeater-item"),o),s.csf_customizer_refresh(),s.csf_customizer_listen({closest:!0}))}function t(e){e.preventDefault(),e=s.children(".csf-repeater-item").length,a.hide(),r.hide(),l&&e-1'+i.unit+"")},spin:function(e,t){n.val(t.value).trigger("change")}})})},S.fn.csf_field_switcher=function(){return this.each(function(){var n=S(this).find(".csf--switcher");n.on("click",function(){var e=0,t=n.find("input");n.hasClass("csf--active")?n.removeClass("csf--active"):(e=1,n.addClass("csf--active")),t.val(e).trigger("change")})})},S.fn.csf_field_tabbed=function(){return this.each(function(){var e=S(this),t=e.find(".csf-tabbed-nav a"),n=e.find(".csf-tabbed-content");n.eq(0).csf_reload_script(),t.on("click",function(e){e.preventDefault();var e=S(this),t=e.index(),t=n.eq(t);e.addClass("csf-tabbed-active").siblings().removeClass("csf-tabbed-active"),t.csf_reload_script(),t.removeClass("hidden").siblings().addClass("hidden")})})},S.fn.csf_field_typography=function(){return this.each(function(){var x=this,z=S(this),i=[],D=csf_typography_json.webfonts,t=csf_typography_json.googlestyles,O=csf_typography_json.defaultstyles;x.sanitize_subset=function(e){return e=(e=e.replace("-ext"," Extended")).charAt(0).toUpperCase()+e.slice(1)},x.sanitize_style=function(e){return t[e]||e},x.load_google_font=function(e,t,n){e&&"object"==typeof WebFont&&(t=t?t.replace("normal",""):"",n=n?n.replace("normal",""):"",-1===i.indexOf(e=t||n?e+":"+t+n:e)&&WebFont.load({google:{families:[e]}}),i.push(e))},x.append_select_options=function(e,t,s,c,a){e.find("option").not(":first").remove();var r="";S.each(t,function(e,t){var n=t,i=a?s&&-1!==s.indexOf(t)?" selected":"":s&&s===t?" selected":"";"subset"===c?n=x.sanitize_subset(t):"style"===c&&(n=x.sanitize_style(t)),r+='"+n+" "}),e.append(r).trigger("csf.change").trigger("chosen:updated")},x.init=function(){var c,a,r,o,f,l,d,h,g,p=[],e=z.find(".csf--typography"),u=z.find(".csf--type"),v=z.find(".csf--block-font-style"),m=e.data("unit"),_=e.data("line-height-unit"),t=e.data("exclude")?e.data("exclude").split(","):[],b=(z.find(".csf--chosen").length&&z.find("select").each(function(){var e=S(this),t=e.parent().find(".chosen-container");t.length&&t.remove(),e.chosen({allow_single_deselect:!0,disable_search_threshold:15,width:"100%"})}),z.find(".csf--font-family")),i=b.val(),s=(b.find("option").not(":first-child").remove(),""),y=(S.each(D,function(n,e){t&&-1!==t.indexOf(n)||(s+='',S.each(e.fonts,function(e,t){s+='"+t+" "}),s+=" ")}),b.append(s).trigger("chosen:updated"),z.find(".csf--block-font-style")),w=(y.length&&(c=z.find(".csf--font-style-select"),a=c.val()?c.val().replace(/normal/g,""):"",c.on("change csf.change",function(e){var t=c.val(),n=(t=!t&&p&&-1===p.indexOf("normal")?p[0]:t)&&"italic"!==t&&"normal"===t?"normal":"",n=t&&"italic"!==t&&"normal"!==t?t.replace("italic",""):n,t=t&&"italic"===t.substr(-6)?"italic":"";z.find(".csf--font-weight").val(n),z.find(".csf--font-style").val(t)}),(r=z.find(".csf--block-extra-styles")).length&&(o=z.find(".csf--extra-styles"),f=o.val())),z.find(".csf--block-subset")),C=(w.length&&(l=z.find(".csf--subset"),d=l.val(),h=l.data("multiple")||!1),z.find(".csf--block-backup-font-family")),k=(b.on("change csf.change",function(e){w.length&&w.addClass("hidden"),r.length&&r.addClass("hidden"),C.length&&C.addClass("hidden");var t,n,i=b.find(":selected"),s=i.val(),i=i.data("type");i&&s?("google"!==i&&"custom"!==i||!C.length||C.removeClass("hidden"),y.length&&(n=O,"google"===i&&D[i].fonts[s][0]?n=D[i].fonts[s][0]:"custom"===i&&D[i].fonts[s]&&(n=D[i].fonts[s]),t=-1!==(p=n).indexOf("normal")?"normal":n[0],t=a&&-1!==n.indexOf(a)?a:t,x.append_select_options(c,n,t,"style"),a=!1,y.removeClass("hidden"),"google"===i&&r.length&&1!',S.each(e.errors,function(e,t){var e=S('[data-depend-id="'+e+'"]'),n=S('a[href="#tab='+e.closest(".csf-section").data("section-id")+'"]'),i=n.closest(".csf-tab-item");e.closest(".csf-fieldset").append(''+t+"
"),n.find(".csf-error").length||n.append(s),i.find(".csf-arrow .csf-error").length||i.find(".csf-arrow").append(s)})),a.removeClass("csf-saving"),c.prop("disabled",!1).attr("value",n),r=!1,j.vars.form_modified=!1,j.vars.$form_warning.hide(),clearTimeout(i);var s,t=S(".csf-form-success");t.empty().append(e.notice).fadeIn("fast",function(){i=setTimeout(function(){t.fadeOut("fast")},1e3)})}).fail(function(e){alert(e.error)})):j.vars.form_modified=!1),r=!0})})},S.fn.csf_options=function(){return this.each(function(){var e=S(this),t=e.find(".csf-content"),n=e.find(".csf-form-success"),i=e.find(".csf-form-warning"),s=e.find(".csf-header .csf-save");(j.vars.$form_warning=i).length&&(_.onbeforeunload=function(){return!!j.vars.form_modified||y},t.on("change keypress",":input",function(){j.vars.form_modified||(n.hide(),i.fadeIn("fast"),j.vars.form_modified=!0)})),n.hasClass("csf-form-show")&&setTimeout(function(){n.fadeOut("fast")},1e3),S(b).keydown(function(e){if((e.ctrlKey||e.metaKey)&&83===e.which)return s.trigger("click"),e.preventDefault(),!1})})},S.fn.csf_taxonomy=function(){return this.each(function(){var e,t,n=S(this),i=n.parents("form");"addtag"===i.attr("id")&&(e=i.find("#submit"),t=n.children(".csf-field").csf_clone(),e.on("click",function(){i.find(".form-required").hasClass("form-invalid")||(n.data("inited",!1),n.empty(),n.html(t),t=t.csf_clone(),n.csf_reload_script())}))})},S.fn.csf_shortcode=function(){var m=this;return m.shortcode_parse=function(e,n){var i="";return S.each(e,function(e,t){i+="["+(n=n||e),S.each(t,function(e,t){"content"===e?i=(i+="]")+t+"[/"+n:i+=m.shortcode_tags(e,t)}),i+="]"}),i},m.shortcode_tags=function(e,t){var n="";return""!==t&&("object"!=typeof t||S.isArray(t)?n+=" "+e+'="'+t.toString()+'"':S.each(t,function(e,t){""!==(t="background-image"===e?t.url||"":t)&&(n+=" "+e+'="'+t.toString()+'"')})),n},m.insertAtChars=function(e,t){e=void 0!==e[0].name?e[0]:e;return e.value.length&&void 0!==e.selectionStart?(e.focus(),e.value.substring(0,e.selectionStart)+t+e.value.substring(e.selectionEnd,e.value.length)):(e.focus(),t)},m.send_to_editor=function(e,t){var n;(n="undefined"!=typeof tinymce?tinymce.get(t):n)&&!n.isHidden()?n.execCommand("mceInsertContent",!1,e):(n=S("#"+t)).val(m.insertAtChars(n,e)).trigger("change")},this.each(function(){var s,c,a,n,r,o,f,i,l,d=S(this),h=d.find(".csf-modal-load"),p=(d.find(".csf-modal-content"),d.find(".csf-modal-insert")),u=d.find(".csf-modal-loading"),t=d.find("select"),g=d.data("modal-id"),v=d.data("nonce");S(b).on("click",'.csf-shortcode-button[data-modal-id="'+g+'"]',function(e){e.preventDefault(),l=S(this),s=l.data("editor-id")||!1,c=l.data("target-id")||!1,a=l.data("gutenberg-id")||!1,d.removeClass("hidden"),d.hasClass("csf-shortcode-single")&&r===y&&t.trigger("change")}),t.on("change",function(){var e=S(this),t=e.find(":selected");n=e.val(),r=t.data("shortcode"),o=t.data("view")||"normal",f=t.data("group")||r,h.empty(),n?(u.show(),_.wp.ajax.post("csf-get-shortcode-"+g,{shortcode_key:n,nonce:v}).done(function(e){u.hide();e=S(e.content).appendTo(h);p.parent().removeClass("hidden"),i=e.find(".csf--repeat-shortcode").csf_clone(),e.csf_reload_script(),e.find(".csf-fields").csf_reload_script()})):p.parent().addClass("hidden")}),p.on("click",function(e){if(e.preventDefault(),!p.prop("disabled")&&!p.attr("disabled")){var n="",t=d.find(".csf-field:not(.csf-depend-on)").find(":input:not(.ignore)").serializeObjectCSF();switch(o){case"contents":var i=r?t[r]:t;S.each(i,function(e,t){e=r||e;n+="["+e+"]"+t+"[/"+e+"]"});break;case"group":n+="["+r,S.each(t[r],function(e,t){n+=m.shortcode_tags(e,t)}),n=(n=(n+="]")+m.shortcode_parse(t[f],f))+("[/"+r+"]");break;case"repeater":n+=m.shortcode_parse(t[f],f);break;default:n+=m.shortcode_parse(t)}n=""===n?"["+r+"]":n,a?(e=_.csf_gutenberg_props.attributes.hasOwnProperty("shortcode")?_.csf_gutenberg_props.attributes.shortcode:"",_.csf_gutenberg_props.setAttributes({shortcode:e+n})):s?m.send_to_editor(n,s):(e=c?S(c):l.parent().find("textarea")).val(m.insertAtChars(e,n)).trigger("change"),d.addClass("hidden")}}),d.on("click",".csf--repeat-button",function(e){e.preventDefault();var e=d.find(".csf--repeatable"),t=i.csf_clone(),n=t.find(".csf-repeat-remove");t.appendTo(e);t.find(".csf-fields").csf_reload_script(),j.helper.name_nested_replace(d.find(".csf--repeat-shortcode"),f),n.on("click",function(){t.remove(),j.helper.name_nested_replace(d.find(".csf--repeat-shortcode"),f)})}),d.on("click",".csf-modal-close, .csf-modal-overlay",function(){d.addClass("hidden")})})},"function"==typeof Color&&(Color.prototype.toString=function(){if(this._alpha<1)return this.toCSS("rgba",this._alpha).replace(/\s+/g,"");var e=parseInt(this._color,10).toString(16);if(this.error)return"";if(e.length<6)for(var t=6-e.length-1;0<=t;t--)e="0"+e;return"#"+e}),j.funcs.parse_color=function(e){var e=e.replace(/\s+/g,""),t=-1!==e.indexOf("rgba")?parseFloat(100*e.replace(/^.*,(.+)\)/,"$1")):100;return{value:e,transparent:t,rgba:t<100}},S.fn.csf_color=function(){return this.each(function(){var a,r=S(this),n=j.funcs.parse_color(r.val()),e=!_.csf_vars.color_palette.length||_.csf_vars.color_palette;r.hasClass("wp-color-picker")&&r.closest(".wp-picker-container").after(r).remove(),r.wpColorPicker({palettes:e,change:function(e,t){t=t.color.toString();a.removeClass("csf--transparent-active"),a.find(".csf--transparent-offset").css("background-color",t),r.val(t).trigger("change")},create:function(){a=r.closest(".wp-picker-container");var i=r.data("a8cIris"),e=S('').appendTo(a.find(".wp-picker-holder")),s=e.find(".csf--transparent-slider"),c=e.find(".csf--transparent-text"),t=e.find(".csf--transparent-offset"),e=e.find(".csf--transparent-button");"transparent"===r.val()&&a.addClass("csf--transparent-active"),e.on("click",function(){"transparent"!==r.val()?(r.val("transparent").trigger("change").removeClass("iris-error"),a.addClass("csf--transparent-active")):(r.val(i._color.toString()).trigger("change"),a.removeClass("csf--transparent-active"))}),s.slider({value:n.transparent,step:1,min:0,max:100,slide:function(e,t){t=parseFloat(t.value/100);i._color._alpha=t,r.wpColorPicker("color",i._color.toString()),c.text(1===t||0===t?"":t)},create:function(){var e=parseFloat(n.transparent/100);c.text(e<1?e:""),t.css("background-color",n.value),a.on("click",".wp-picker-clear",function(){i._color._alpha=1,c.text(""),s.slider("option","value",100),a.removeClass("csf--transparent-active"),r.trigger("change")}),a.on("click",".wp-picker-default",function(){var e=j.funcs.parse_color(r.data("default-color")),t=parseFloat(e.transparent/100),n=t<1?t:"";i._color._alpha=t,c.text(n),s.slider("option","value",e.transparent),"transparent"===e.value&&(r.removeClass("iris-error"),a.addClass("csf--transparent-active"))})}})}})})},S.fn.csf_chosen=function(){return this.each(function(){var n,c,a=S(this),e=a.parent().find(".chosen-container"),t=a.hasClass("csf-chosen-sortable")||!1,i=a.hasClass("csf-chosen-ajax")||!1,s=a.attr("multiple")||!1,r=S.extend({allow_single_deselect:!0,disable_search_threshold:10,width:s?"100%":"auto",no_results_text:_.csf_vars.i18n.no_results_text},a.data("chosen-settings"));e.length&&e.remove(),i?(e=S.extend({data:{type:"post",nonce:""},allow_single_deselect:!0,disable_search_threshold:-1,width:"100%",min_length:3,type_delay:500,typing_text:_.csf_vars.i18n.typing_text,searching_text:_.csf_vars.i18n.searching_text,no_results_text:_.csf_vars.i18n.no_results_text},a.data("chosen-settings")),a.CSFAjaxChosen(e)):a.chosen(r),s&&(i=(n=a.parent().find(".csf-hide-select")).val()||[],a.on("change",function(e,t){t&&t.selected?n.append(''+t.selected+" "):t&&t.deselected&&n.find('option[value="'+t.deselected+'"]').remove(),_.wp.customize!==y&&0===n.children().length&&n.data("customize-setting-link")&&_.wp.customize.control(n.data("customize-setting-link")).setting.set(""),n.trigger("change")}),a.CSFChosenOrder(i,!0)),t&&((c=a.parent().find(".chosen-container").find(".chosen-choices")).bind("mousedown",function(e){S(e.target).is("span")&&e.stopPropagation()}),c.sortable({items:"li:not(.search-field)",helper:"orginal",cursor:"move",placeholder:"search-choice-placeholder",start:function(e,t){t.placeholder.width(t.item.innerWidth()),t.placeholder.height(t.item.innerHeight())},update:function(e,t){var i="",s=a.data("chosen"),n=a.parent().find(".csf-hide-select");c.find(".search-choice-close").each(function(){var n=S(this).data("option-array-index");S.each(s.results_data,function(e,t){t.array_index===n&&(i+=''+t.value+" ")})}),n.children().remove(),n.append(i),n.trigger("change")}}))})},S.fn.csf_checkbox=function(){return this.each(function(){var e=S(this),t=e.find(".csf--input"),n=e.find(".csf--checkbox");n.on("click",function(){t.val(Number(n.prop("checked"))).trigger("change")})})},S.fn.csf_checkbox_all=function(){return this.each(function(){var n=S(this);n.on("click",function(){var e=n.closest(".csf-field-checkbox").find(":input"),t=!1;e.each(function(){S(this).prop("checked")||(t=!0)}),t?(e.prop("checked","checked"),e.attr("checked","checked")):(e.prop("checked",""),e.removeAttr("checked")),e.first().trigger("change")})})},S.fn.csf_siblings=function(){return this.each(function(){var t=S(this),e=t.find(".csf--sibling"),n=t.data("multiple")||!1;e.on("click",function(){var e=S(this);n?e.hasClass("csf--active")?(e.removeClass("csf--active"),e.find("input").prop("checked",!1).trigger("change")):(e.addClass("csf--active"),e.find("input").prop("checked",!0).trigger("change")):(t.find("input").prop("checked",!1),e.find("input").prop("checked",!0).trigger("change"),e.addClass("csf--active").siblings().removeClass("csf--active"))})})},S.fn.csf_help=function(){return this.each(function(){var e,t,n=S(this);n.on({mouseenter:function(){e=S('
').html(n.find(".csf-help-text").html()).appendTo("body"),t=j.vars.is_rtl?n.offset().left+24:n.offset().left-e.outerWidth(),e.css({top:n.offset().top-(e.outerHeight()/2-14),left:t})},mouseleave:function(){e!==y&&e.remove()}})})},S.fn.csf_customizer_refresh=function(){return this.each(function(){var e=S(this),t=e.closest(".csf-customize-complex");if(t.length){var n=t.data("unique-id");if(n===y)return;var i=t.find(":input"),t=t.data("option-id"),i=i.serializeObjectCSF(),i=!S.isEmptyObject(i)&&i[n]&&i[n][t]?i[n][t]:"",n=_.wp.customize.control(n+"["+t+"]");n.setting._value=null,n.setting.set(i)}else e.find(":input").first().trigger("change");S(b).trigger("csf-customizer-refresh",e)})},S.fn.csf_customizer_listen=function(e){var s=S.extend({closest:!1},e);return this.each(function(){var t,e,n,i;_.wp.customize!==y&&(e=(t=s.closest?S(this).closest(".csf-customize-complex"):S(this)).find(":input"),n=t.data("unique-id"),i=t.data("option-id"),n!==y&&e.on("change keyup csf.change",function(){var e=t.find(":input").serializeObjectCSF(),e=!S.isEmptyObject(e)&&e[n]&&e[n][i]?e[n][i]:"";_.wp.customize.control(n+"["+i+"]").setting.set(e)}))})},S(b).on("expanded",".control-section",function(){var e,t,n=S(this);n.hasClass("open")&&!n.data("inited")&&(e=n.find(".csf-customize-field"),t=n.find(".csf-customize-complex"),e.length&&(n.csf_dependency(),e.csf_reload_script({dependency:!1}),t.csf_customizer_listen()),n.data("inited",!0))}),j.vars.$window.on("resize csf.resize",j.helper.debounce(function(e){(-1 ',
redo: ' ',
bold: ' ',
italic: ' ',
strikethrough: ' ',
link: ' ',
alignNone: ' ',
alignWide: ' ',
alignFull: ' ',
alignLeft: ' ',
alignCenter: ' ',
alignRight: ' ',
textAlignLeft: ' ',
textAlignCenter: ' ',
textAlignRight: ' ',
orderedList: ' ',
unorderedList: ' ',
indent: ' ',
outdent: ' ',
textAlignmentDropdown: ' ',
replaceMedia: 'Replace ',
};
/**
* Create one runtime toolbar button definition.
*
* @param {Object} config Button configuration.
* @returns {Object} Runtime toolbar button definition.
*/
function createToolbarButton(config = {}) {
return {
icon: config.icon || '',
title: config.title || '',
action: typeof config.action === 'function' ? config.action : () => {},
className: config.className || '',
formatKey: config.formatKey || '',
formatType: config.formatType || '',
value: Object.prototype.hasOwnProperty.call(config, 'value') ? config.value : undefined,
tag: config.tag || '',
activeTags: Array.isArray(config.activeTags) ? config.activeTags : [],
};
}
/**
* Create one runtime toolbar dropdown definition.
*
* @param {Object} config Dropdown configuration.
* @returns {Object} Runtime toolbar dropdown definition.
*/
function createToolbarDropdown(config = {}) {
return {
type: 'dropdown',
title: config.title || '',
defaultIcon: config.defaultIcon || '',
options: Array.isArray(config.options) ? config.options.filter(Boolean) : [],
formatKey: config.formatKey || '',
};
}
/**
* Execute one schema block-attribute operation from a toolbar action.
*
* @param {Object|null} editor Editor host.
* @param {string} operationId Schema operation id.
* @param {*} value Requested operation value.
* @returns {void}
*/
function executeSchemaBlockAttributeOperation(editor, operationId, value) {
const operationExecutor = SFE.SchemaOperationExecutor || null;
if (!operationExecutor || typeof operationExecutor.executeBlockAttributeOperation !== 'function') {
return;
}
operationExecutor.executeBlockAttributeOperation({
editorHost: editor,
operationId,
value,
saveHistory: true,
});
}
/**
* Execute one schema list operation from a toolbar action.
*
* @param {Object|null} editor Editor host.
* @param {string} operationId Schema or primitive operation id.
* @returns {void}
*/
function executeSchemaListOperation(editor, operationId) {
if (typeof editor?.executeListStructureOperation !== 'function') {
return;
}
editor.executeListStructureOperation({
kind: operationId,
});
}
/**
* Execute one list type switch from a toolbar action.
*
* @param {Object|null} editor Editor host.
* @param {string} listType List type token.
* @returns {void}
*/
function executeListTypeOperation(editor, listType) {
const createTag = listType === 'ordered' ? 'ol' : 'ul';
const oppositeTag = listType === 'ordered' ? 'UL' : 'OL';
const operationExecutor = SFE.SchemaOperationExecutor || null;
if (editor?._linkUIActive && typeof editor.closeLinkUI === 'function') {
editor.closeLinkUI();
}
const selection = window.getSelection();
if (selection?.rangeCount > 0) {
const range = selection.getRangeAt(0);
let startLi = range.startContainer;
let endLi = range.endContainer;
while (startLi && startLi !== editor?.element && startLi.tagName !== 'LI') {
startLi = startLi.parentNode;
}
while (endLi && endLi !== editor?.element && endLi.tagName !== 'LI') {
endLi = endLi.parentNode;
}
if (startLi && endLi && startLi !== endLi) {
return;
}
}
if (
(editor?.element?.tagName === 'UL' || editor?.element?.tagName === 'OL') &&
operationExecutor &&
typeof operationExecutor.executeCurrentListTypeChange === 'function'
) {
const result = operationExecutor.executeCurrentListTypeChange({
editorHost: editor,
value: listType,
});
if (result) {
return;
}
}
const listItem = typeof editor?.getCurrentListItem === 'function'
? editor.getCurrentListItem()
: null;
if (!listItem) {
if (typeof editor?.insertListManual === 'function') {
editor.insertListManual(createTag);
setTimeout(() => {
const list = typeof editor?.getParentList === 'function'
? editor.getParentList()
: null;
if (list) {
list.classList.add('wp-block-list');
}
}, 10);
}
return;
}
const currentList = listItem.parentNode;
if (
currentList &&
currentList.tagName === oppositeTag &&
typeof editor?.changeListType === 'function'
) {
editor.changeListType(currentList, createTag);
}
}
/**
* Build one toolbar button for a schema token that toggles inline formatting.
*
* @param {string} token Token name.
* @param {string} title Button title.
* @param {string} icon Icon markup.
* @param {string} tagName Inline tag name.
* @param {string[]} activeTags Active-tag list for toolbar state.
* @returns {Object} Runtime toolbar button definition.
*/
function createInlineFormatButton(token, title, icon, tagName, activeTags) {
return createToolbarButton({
formatKey: token,
title,
icon,
activeTags,
action: (editor) => {
if (typeof editor?.toggleInlineFormat !== 'function') {
return;
}
editor.executeAction(() => {
editor.toggleInlineFormat(tagName);
}, { saveHistory: false });
},
});
}
/**
* Build one toolbar button for a schema token that opens link editing.
*
* @param {string} token Token name.
* @param {string} title Button title.
* @returns {Object} Runtime toolbar button definition.
*/
function createLinkButton(token, title) {
return createToolbarButton({
formatKey: token,
title,
icon: TOOLBAR_FORMAT_ICONS.link,
action: (editor) => {
if (typeof editor?.showLinkUI !== 'function') {
return;
}
const usesElementScopedLinkEditing = typeof editor.supportsElementLinkEditing === 'function'
? editor.supportsElementLinkEditing()
: false;
const existingLink = typeof editor.getParentElement === 'function'
? editor.getParentElement('a')
: null;
editor.showLinkUI(usesElementScopedLinkEditing ? null : existingLink);
},
});
}
/**
* Determine whether schema declares element-scoped link editing for the
* active text component.
*
* @param {HTMLElement|null} element Active editable element.
* @param {Object} editorOptions Normalized component editor options.
* @returns {boolean} True when the component edits its root anchor directly.
*/
function supportsElementScopedLinkToken(element, editorOptions = {}) {
if (!element || element.tagName !== 'A') {
return false;
}
const inlineFormatCapabilities = (
editorOptions?.inlineFormatCapabilities &&
typeof editorOptions.inlineFormatCapabilities === 'object'
)
? editorOptions.inlineFormatCapabilities
: null;
const attributeCapabilities = (
editorOptions?.attributeCapabilities &&
typeof editorOptions.attributeCapabilities === 'object'
)
? editorOptions.attributeCapabilities
: null;
const buttonLinkCapability = inlineFormatCapabilities?.buttonLink;
const buttonLinkTag = typeof buttonLinkCapability?.tag === 'string'
? buttonLinkCapability.tag.trim().toLowerCase()
: '';
if (buttonLinkTag !== 'a') {
return false;
}
const attributes = Array.isArray(attributeCapabilities?.buttonLink?.attributes)
? attributeCapabilities.buttonLink.attributes
.map(value => (typeof value === 'string' ? value.trim() : ''))
.filter(Boolean)
: [];
return attributes.includes('url');
}
/**
* Build one toolbar button for a schema list indentation action.
*
* @param {string} token Token name.
* @param {string} title Button title.
* @param {string} icon Icon markup.
* @param {string} operationId Schema list operation id.
* @returns {Object} Runtime toolbar button definition.
*/
function createListIndentButton(token, title, icon, operationId) {
return createToolbarButton({
formatKey: token,
title,
icon,
action: (editor) => {
executeSchemaListOperation(editor, operationId);
},
});
}
/**
* Build one toolbar option for schema-backed block alignment.
*
* @param {string} optionKey Icon/format lookup key.
* @param {string} title Option title.
* @param {string} value Alignment value.
* @returns {Object} Runtime toolbar option definition.
*/
function createBlockAlignOption(optionKey, title, value) {
return createToolbarButton({
formatKey: optionKey,
formatType: 'blockAlign',
title,
icon: TOOLBAR_FORMAT_ICONS[optionKey],
value,
action: (editor) => {
executeSchemaBlockAttributeOperation(editor, 'set_align', value);
},
});
}
/**
* Build one toolbar option for schema-backed text alignment.
*
* @param {string} optionKey Icon/format lookup key.
* @param {string} title Option title.
* @param {string} value Alignment value.
* @returns {Object} Runtime toolbar option definition.
*/
function createTextAlignmentOption(optionKey, title, value) {
return createToolbarButton({
formatKey: optionKey,
formatType: 'textAlignment',
title,
icon: TOOLBAR_FORMAT_ICONS[optionKey],
value,
action: (editor) => {
executeSchemaBlockAttributeOperation(editor, 'set_text_align', value);
},
});
}
/**
* Build one toolbar option for schema-backed heading level changes.
*
* @param {string|number} level Heading level or element-tag value.
* @returns {Object} Runtime toolbar option definition.
*/
function createHeadingLevelOption(level) {
const value = typeof level === 'string' ? level.trim().toLowerCase() : level;
const tag = typeof value === 'number' ? `h${value}` : value;
const levelNumber = Number.parseInt(String(tag).replace(/^h/i, ''), 10);
const title = tag === 'p' ? 'Paragraph' : tag === 'div' ? 'Div' : `Heading ${levelNumber}`;
return createToolbarButton({
formatKey: String(tag),
title,
icon: title,
tag,
value,
action: (editor) => {
executeSchemaBlockAttributeOperation(editor, 'set_heading_level', value);
},
});
}
/**
* Return the canonical built-in block-align toolbar option map.
*
* @returns {Map} Built-in block-align options keyed by value.
*/
function getBlockAlignOptionMap() {
return new Map([
['none', createBlockAlignOption('alignNone', 'None', 'none')],
['wide', createBlockAlignOption('alignWide', 'Wide Width', 'wide')],
['full', createBlockAlignOption('alignFull', 'Full Width', 'full')],
['left', createBlockAlignOption('alignLeft', 'Align Left', 'left')],
['center', createBlockAlignOption('alignCenter', 'Align Center', 'center')],
['right', createBlockAlignOption('alignRight', 'Align Right', 'right')],
]);
}
/**
* Create the schema-backed text-alignment dropdown.
*
* @returns {Object} Runtime toolbar dropdown definition.
*/
function createTextAlignmentDropdown() {
return createToolbarDropdown({
formatKey: 'textAlignment',
title: 'Text Alignment',
defaultIcon: TOOLBAR_FORMAT_ICONS.textAlignmentDropdown,
options: [
createTextAlignmentOption('textAlignLeft', 'Align Text Left', 'left'),
createTextAlignmentOption('textAlignCenter', 'Align Text Center', 'center'),
createTextAlignmentOption('textAlignRight', 'Align Text Right', 'right'),
],
});
}
function getSchemaBlockAlignValues(editorOptions = {}) {
const operations = Array.isArray(editorOptions?.operations)
? editorOptions.operations
: [];
const operation = operations.find(candidate => (
String(candidate?.id || '').trim() === 'set_align' &&
String(candidate?.kind || '').trim() === 'block_attribute_change'
)) || null;
const operationValues = Array.isArray(operation?.values)
? operation.values
: null;
const capabilityValues = Array.isArray(editorOptions?.attributeCapabilities?.align?.values)
? editorOptions.attributeCapabilities.align.values
: null;
const values = operationValues && operationValues.length
? operationValues
: capabilityValues;
return Array.isArray(values)
? values.map(value => String(value || '').trim().toLowerCase()).filter(Boolean)
: [];
}
function createBlockAlignDropdown(editorOptions = {}) {
const allowedValues = getSchemaBlockAlignValues(editorOptions);
const optionMap = getBlockAlignOptionMap();
const options = allowedValues.map(value => optionMap.get(value)).filter(Boolean);
if (!options.length) {
return null;
}
return createToolbarDropdown({
formatKey: 'align',
title: 'Align',
defaultIcon: options[0].icon,
options
});
}
/**
* Create the schema-backed heading-level dropdown.
*
* @returns {Object} Runtime toolbar dropdown definition.
*/
function createHeadingDropdown(editorOptions = {}) {
const operation = (editorOptions.operations || []).find(candidate => (
String(candidate?.id || '').trim() === 'set_heading_level'
)) || null;
const values = Array.isArray(operation?.values)
? operation.values
: (editorOptions.attributeCapabilities?.headingLevels?.values || []);
return createToolbarDropdown({
formatKey: 'headingLevels',
title: 'Heading Level',
defaultIcon: 'H',
options: values.map(createHeadingLevelOption),
});
}
/**
* Create the shared media-replace toolbar button.
*
* @returns {Object} Runtime toolbar button definition.
*/
function createReplaceMediaButton() {
return createToolbarButton({
formatKey: 'replaceMedia',
icon: TOOLBAR_FORMAT_ICONS.replaceMedia,
title: 'Replace Media',
className: 'mwp-sfe-editor-btn-text',
action: (editor) => {
if (typeof editor?.showMediaReplaceUI === 'function') {
editor.showMediaReplaceUI();
}
}
});
}
/**
* Resolve one built-in schema toolbar token to a runtime format definition.
*
* @param {string} token Built-in schema toolbar token.
* @param {HTMLElement|null} element Active editable element.
* @param {Object} editorOptions Normalized editor options.
* @returns {Object|null} Runtime toolbar definition or null.
*/
function resolveSchemaFormatToken(token, element, editorOptions = {}) {
const normalizedToken = typeof token === 'string' ? token.trim() : '';
if (!normalizedToken) return null;
switch (normalizedToken) {
case 'undo':
return createToolbarButton({
formatKey: 'undo',
title: 'Undo',
icon: TOOLBAR_FORMAT_ICONS.undo,
action: (editor) => editor?.undo?.(),
});
case 'redo':
return createToolbarButton({
formatKey: 'redo',
title: 'Redo',
icon: TOOLBAR_FORMAT_ICONS.redo,
action: (editor) => editor?.redo?.(),
});
case 'bold':
return createInlineFormatButton('bold', 'Bold', TOOLBAR_FORMAT_ICONS.bold, 'strong', ['strong', 'b']);
case 'italic':
return createInlineFormatButton('italic', 'Italic', TOOLBAR_FORMAT_ICONS.italic, 'em', ['em', 'i']);
case 'strikethrough':
return createInlineFormatButton('strikethrough', 'Strikethrough', TOOLBAR_FORMAT_ICONS.strikethrough, 's', ['s', 'strike']);
case 'link':
return createLinkButton('link', 'Link');
case 'buttonLink':
return !supportsElementScopedLinkToken(element, editorOptions)
? null
: createLinkButton('buttonLink', 'Button Link');
case 'textAlignment':
return createTextAlignmentDropdown();
case 'align':
return createBlockAlignDropdown(editorOptions);
case 'headingLevels':
return createHeadingDropdown(editorOptions);
case 'orderedList':
return createToolbarButton({
formatKey: 'orderedList',
title: 'Ordered List',
icon: TOOLBAR_FORMAT_ICONS.orderedList,
action: (editor) => executeListTypeOperation(editor, 'ordered'),
});
case 'unorderedList':
return createToolbarButton({
formatKey: 'unorderedList',
title: 'Unordered List',
icon: TOOLBAR_FORMAT_ICONS.unorderedList,
action: (editor) => executeListTypeOperation(editor, 'unordered'),
});
case 'indent':
return createListIndentButton('indent', 'Indent', TOOLBAR_FORMAT_ICONS.indent, 'indent_list_item');
case 'outdent':
return createListIndentButton('outdent', 'Outdent', TOOLBAR_FORMAT_ICONS.outdent, 'outdent_list_item');
case 'replaceMedia':
return createReplaceMediaButton();
default:
return null;
}
}
/**
* Convert one nested schema format token spec into concrete toolbar configs.
*
* @param {Array} formatsSpec Nested schema token spec.
* @param {HTMLElement|null} element Active editable element.
* @param {Object} editorOptions Normalized editor options.
* @param {number} depth Current recursion depth.
* @returns {Array|null} Concrete toolbar config tree.
*/
function buildFormatsFromSchemaSpec(formatsSpec, element, editorOptions = {}, depth = 0) {
if (depth > 3 || !Array.isArray(formatsSpec)) return null;
const resolved = [];
formatsSpec.forEach(item => {
if (typeof item === 'string') {
const format = resolveSchemaFormatToken(item, element, editorOptions);
if (format) {
resolved.push(format);
}
return;
}
if (Array.isArray(item)) {
const group = buildFormatsFromSchemaSpec(item, element, editorOptions, depth + 1);
if (Array.isArray(group) && group.length) {
resolved.push(group);
}
}
});
return resolved.length ? resolved : null;
}
/**
* Flatten one nested toolbar definition tree into a single format list.
*
* @param {Array} items Nested toolbar definition tree.
* @returns {Object[]} Flat format list.
*/
function flattenFormats(items = []) {
const flattened = [];
(items || []).forEach((item) => {
if (Array.isArray(item)) {
flattened.push(...flattenFormats(item));
return;
}
if (!item || typeof item !== 'object') {
return;
}
flattened.push(item);
if (item.type === 'dropdown' && Array.isArray(item.options)) {
flattened.push(...flattenFormats(item.options));
}
});
return flattened;
}
class ToolbarManager {
constructor(host, options = {}) {
this.host = host || null;
this.options = options || {};
this.toolbar = null;
this._toolbarPointerdownHandler = null;
this._activeToolbarDropdownWrapper = null;
if (this.host && typeof this.host.attachToolbarManager === 'function') {
this.host.attachToolbarManager(this);
}
}
getFormats() {
return Array.isArray(this.host?.formats)
? this.host.formats
: [];
}
/**
* Return one flat runtime toolbar format list.
*
* @returns {Object[]} Flat toolbar format list.
*/
getFlatFormats() {
return flattenFormats(this.getFormats());
}
createToolbar() {
if (this.toolbar && this.toolbar.parentNode) this.toolbar.remove();
this.toolbar = document.createElement('div');
this.toolbar.className = 'mwp-sfe-editor-toolbar';
const selectorSvg = ' ';
const createButton = (format) => {
const btn = document.createElement('button');
btn.type = 'button';
btn.className = ['mwp-sfe-editor-btn', format.className || ''].filter(Boolean).join(' ');
btn.innerHTML = format.icon;
btn.title = format.title;
btn.dataset.format = format.title;
if (format.title === 'Undo') btn.dataset.action = 'undo';
if (format.title === 'Redo') btn.dataset.action = 'redo';
btn.addEventListener('mousedown', (event) => event.preventDefault());
btn.addEventListener('click', (event) => {
event.preventDefault();
format.action(this.host);
});
return btn;
};
const buildItems = (items, container) => {
items.forEach(item => {
if (Array.isArray(item)) {
const group = document.createElement('div');
group.className = 'mwp-sfe-btn-group';
buildItems(item, group);
container.appendChild(group);
} else if (item.type === 'dropdown') {
const wrapper = document.createElement('div');
wrapper.className = 'mwp-sfe-dropdown';
const toggle = document.createElement('button');
toggle.className = 'mwp-sfe-editor-btn mwp-sfe-dropdown-toggle';
toggle.title = item.title;
if (item.formatKey === 'headingLevels') {
wrapper.classList.add('mwp-sfe-dropdown-heading-level');
toggle.innerHTML = `${item.defaultIcon} ${selectorSvg} `;
} else {
toggle.innerHTML = `${item.defaultIcon}`;
}
const content = document.createElement('div');
content.className = 'mwp-sfe-dropdown-content';
item.options.forEach(opt => {
const optBtn = createButton(opt);
optBtn.addEventListener('click', () => {
if (item.formatKey === 'headingLevels') {
toggle.innerHTML = `${opt.icon} ${selectorSvg}`;
} else {
toggle.innerHTML = `${opt.icon}`;
}
content.classList.remove('mwp-sfe-show');
});
content.appendChild(optBtn);
});
toggle.addEventListener('mousedown', (event) => event.preventDefault());
toggle.addEventListener('click', (event) => {
event.preventDefault();
this.toolbar.querySelectorAll('.mwp-sfe-dropdown-content.mwp-sfe-show').forEach(el => {
if (el !== content) el.classList.remove('mwp-sfe-show');
});
content.classList.toggle('mwp-sfe-show');
this._activeToolbarDropdownWrapper = content.classList.contains('mwp-sfe-show')
? wrapper
: null;
});
wrapper.appendChild(toggle);
wrapper.appendChild(content);
if (container.className !== 'mwp-sfe-btn-group') {
const group = document.createElement('div');
group.className = 'mwp-sfe-btn-group';
group.appendChild(wrapper);
container.appendChild(group);
} else {
container.appendChild(wrapper);
}
} else {
const btn = createButton(item);
if (container.className !== 'mwp-sfe-btn-group') {
const group = document.createElement('div');
group.className = 'mwp-sfe-btn-group';
group.appendChild(btn);
container.appendChild(group);
} else {
container.appendChild(btn);
}
}
});
};
buildItems(this.getFormats(), this.toolbar);
this.attachToolbarDropdownCloseHandler();
const toolbarContainer = this.host?.options?.toolbarContainer || null;
if (toolbarContainer) {
toolbarContainer.innerHTML = '';
toolbarContainer.appendChild(this.toolbar);
} else if (this.host?.element?.parentNode) {
this.host.element.parentNode.insertBefore(this.toolbar, this.host.element);
}
this.updateUndoRedoButtons();
}
closeToolbarDropdowns() {
if (!this.toolbar) {
return;
}
this.toolbar.querySelectorAll('.mwp-sfe-dropdown-content.mwp-sfe-show').forEach((element) => {
element.classList.remove('mwp-sfe-show');
});
this._activeToolbarDropdownWrapper = null;
}
attachToolbarDropdownCloseHandler() {
if (!this.toolbar) {
return;
}
if (this._toolbarPointerdownHandler) {
document.removeEventListener('pointerdown', this._toolbarPointerdownHandler, true);
}
this._toolbarPointerdownHandler = (event) => {
if (
!this.toolbar ||
(
this._activeToolbarDropdownWrapper &&
this._activeToolbarDropdownWrapper.contains(event.target)
)
) {
return;
}
this.closeToolbarDropdowns();
};
document.addEventListener('pointerdown', this._toolbarPointerdownHandler, true);
}
updateUndoRedoButtons() {
if (!this.toolbar) return;
const undoBtn = this.toolbar.querySelector('[data-action="undo"]');
const redoBtn = this.toolbar.querySelector('[data-action="redo"]');
const canUndo = typeof this.host?.canUndo === 'function'
? this.host.canUndo()
: (
typeof this.host?.historyIndex === 'number' &&
this.host.historyIndex > 0
);
const canRedo = typeof this.host?.canRedo === 'function'
? this.host.canRedo()
: (
typeof this.host?.historyIndex === 'number' &&
Array.isArray(this.host?.history) &&
this.host.historyIndex < this.host.history.length - 1
);
if (undoBtn) {
undoBtn.disabled = !canUndo;
}
if (redoBtn) {
redoBtn.disabled = !canRedo;
}
}
setToolbarButtonDisabled(title, isDisabled) {
if (!this.toolbar || !title) {
return;
}
const button = this.toolbar.querySelector(`button[title="${title}"]`);
if (button) {
button.disabled = !!isDisabled;
}
}
updateToolbarState() {
if (!this.toolbar || !this.host) return;
const selection = window.getSelection();
const hasSelectionInEditor = (
selection &&
selection.rangeCount &&
typeof this.host.isSelectionInEditor === 'function' &&
this.host.isSelectionInEditor()
);
const parents = [];
if (this.host.element?.tagName) {
parents.push(this.host.element.tagName.toLowerCase());
}
if (hasSelectionInEditor) {
const range = selection.getRangeAt(0);
let node = range.commonAncestorContainer;
while (node && node !== this.host.element) {
if (node.nodeType === 1) parents.push(node.tagName.toLowerCase());
node = node.parentNode;
}
}
this.toolbar.querySelectorAll('.mwp-sfe-editor-btn').forEach(btn => {
btn.classList.remove('mwp-sfe-editor-btn-active');
});
const checkActive = (format, tags) => {
if (!format || !Array.isArray(tags) || !tags.some(tag => parents.includes(tag))) {
return false;
}
const btn = this.toolbar.querySelector(`button[title="${format.title}"]`);
if (btn) btn.classList.add('mwp-sfe-editor-btn-active');
return true;
};
if (hasSelectionInEditor) {
this.getFlatFormats().forEach((format) => {
if (!Array.isArray(format?.activeTags) || !format.activeTags.length) {
return;
}
checkActive(format, format.activeTags);
});
}
const currentAlign = typeof this.host.getBlockAlignState === 'function'
? this.host.getBlockAlignState()
: 'none';
const currentTextAlignment = typeof this.host.getTextAlignmentState === 'function'
? this.host.getTextAlignmentState()
: 'left';
const currentHeadingLevel = typeof this.host.getHeadingLevelState === 'function'
? this.host.getHeadingLevelState()
: null;
const getDropdownFormats = (items) => {
const dropdowns = [];
(items || []).forEach(item => {
if (Array.isArray(item)) {
dropdowns.push(...getDropdownFormats(item));
return;
}
if (item && item.type === 'dropdown') {
dropdowns.push(item);
}
});
return dropdowns;
};
getDropdownFormats(this.getFormats()).forEach(item => {
const toggle = this.toolbar.querySelector(`button[title="${item.title}"]`);
if (!toggle) return;
const activeOption = item.options.find(opt => {
const headingLevel = typeof this.host.getHeadingLevelValueForOption === 'function'
? this.host.getHeadingLevelValueForOption(opt)
: null;
if ( item.formatKey === 'headingLevels' && headingLevel === currentHeadingLevel ) {
return true;
}
if (
typeof this.host.isTextAlignmentOptionActive === 'function' &&
this.host.isTextAlignmentOptionActive(opt, currentTextAlignment)
) {
return true;
}
if (
typeof this.host.isBlockAlignOptionActive === 'function' &&
this.host.isBlockAlignOptionActive(opt, currentAlign)
) {
return true;
}
return false;
});
const selectorSvg = ' ';
if (activeOption) {
toggle.innerHTML = item.formatKey === 'headingLevels'
? `${activeOption.icon} ${selectorSvg} `
: `${activeOption.icon}`;
} else {
toggle.innerHTML = item.formatKey === 'headingLevels'
? `${item.defaultIcon} ${selectorSvg} `
: `${item.defaultIcon}`;
}
item.options.forEach(opt => {
const optionButton = this.toolbar.querySelector(`button[title="${opt.title}"]`);
if (!optionButton) return;
let isDisabled = false;
if (item.formatKey === 'headingLevels') {
const optionLevel = typeof this.host.getHeadingLevelValueForOption === 'function'
? this.host.getHeadingLevelValueForOption(opt)
: null;
isDisabled = optionLevel === currentHeadingLevel;
} else if (
typeof this.host.getTextAlignmentValueForOption === 'function' &&
this.host.getTextAlignmentValueForOption(opt)
) {
isDisabled = typeof this.host.isTextAlignmentOptionActive === 'function'
? this.host.isTextAlignmentOptionActive(opt, currentTextAlignment)
: false;
} else if (
typeof this.host.getBlockAlignValueForOption === 'function' &&
this.host.getBlockAlignValueForOption(opt)
) {
isDisabled = typeof this.host.isBlockAlignOptionActive === 'function'
? this.host.isBlockAlignOptionActive(opt, currentAlign)
: false;
}
optionButton.disabled = isDisabled;
});
});
const operationExecutor = SFE.SchemaOperationExecutor || null;
const currentListItem = typeof this.host.getCurrentListItem === 'function'
? this.host.getCurrentListItem()
: null;
const currentList = (
operationExecutor &&
typeof operationExecutor.getCurrentListElement === 'function'
)
? operationExecutor.getCurrentListElement(this.host)
: (
typeof this.host.getParentList === 'function'
? this.host.getParentList()
: null
);
const canIndent = typeof this.host.canIndentListItem === 'function'
? this.host.canIndentListItem(currentListItem)
: false;
const canOutdent = typeof this.host.canOutdentListItem === 'function'
? this.host.canOutdentListItem(currentListItem)
: false;
this.setToolbarButtonDisabled('Ordered List', !currentList || currentList.tagName === 'OL');
this.setToolbarButtonDisabled('Unordered List', !currentList || currentList.tagName === 'UL');
this.setToolbarButtonDisabled('Indent', !currentListItem || !canIndent);
this.setToolbarButtonDisabled('Outdent', !currentListItem || !canOutdent);
this.updateUndoRedoButtons();
}
destroy(options = {}) {
const removeToolbar = options.removeToolbar !== false;
if (this._toolbarPointerdownHandler) {
document.removeEventListener('pointerdown', this._toolbarPointerdownHandler, true);
this._toolbarPointerdownHandler = null;
}
this._activeToolbarDropdownWrapper = null;
if (removeToolbar && this.toolbar && this.toolbar.parentNode) {
this.toolbar.remove();
}
if (this.host && typeof this.host.detachToolbarManager === 'function') {
this.host.detachToolbarManager(this);
}
this.toolbar = removeToolbar ? null : this.toolbar;
this.host = null;
}
static resolveFormats(editorOptions = {}, element = null) {
const schemaFormats = buildFormatsFromSchemaSpec(editorOptions?.formats, element, editorOptions);
return Array.isArray(schemaFormats) && schemaFormats.length
? schemaFormats
: [];
}
}
SFE.ToolbarManager = ToolbarManager;
if (typeof module !== 'undefined' && module.exports) {
module.exports = { ToolbarManager };
}
})();
@import "partials/display";