").text(b).html(),b=c.trim(b),b||a.Menus.data.l10n.unnamed}wpNavMenu.originalInit=wpNavMenu.init,wpNavMenu.options.menuItemDepthPerLevel=20,wpNavMenu.options.sortableItems="> .customize-control-nav_menu_item",wpNavMenu.options.targetTolerance=10,wpNavMenu.init=function(){this.jQueryExtensions()},a.Menus=a.Menus||{},a.Menus.data={itemTypes:[],l10n:{},menuItemTransport:"postMessage",phpIntMax:0,defaultSettingValues:{nav_menu:{},nav_menu_item:{}},locationSlugMappedToName:{}},"undefined"!=typeof _wpCustomizeNavMenusSettings&&c.extend(a.Menus.data,_wpCustomizeNavMenusSettings),a.Menus.generatePlaceholderAutoIncrementId=function(){return-Math.ceil(a.Menus.data.phpIntMax*Math.random())},a.Menus.AvailableItemModel=Backbone.Model.extend(c.extend({id:null},a.Menus.data.defaultSettingValues.nav_menu_item)),a.Menus.AvailableItemCollection=Backbone.Collection.extend({model:a.Menus.AvailableItemModel,sort_key:"order",comparator:function(a){return-a.get(this.sort_key)},sortByField:function(a){this.sort_key=a,this.sort()}}),a.Menus.availableMenuItems=new a.Menus.AvailableItemCollection(a.Menus.data.availableMenuItems),a.Menus.AvailableMenuItemsPanelView=b.Backbone.View.extend({el:"#available-menu-items",events:{"input #menu-items-search":"debounceSearch","keyup #menu-items-search":"debounceSearch","focus .menu-item-tpl":"focus","click .menu-item-tpl":"_submit","click #custom-menu-item-submit":"_submitLink","keypress #custom-menu-item-name":"_submitLink",keydown:"keyboardAccessible"},selected:null,currentMenuControl:null,debounceSearch:null,$search:null,searchTerm:"",rendered:!1,pages:{},sectionContent:"",loading:!1,initialize:function(){var b=this;a.panel.has("nav_menus")&&(this.$search=c("#menu-items-search"),this.sectionContent=this.$el.find(".accordion-section-content"),this.debounceSearch=_.debounce(b.search,500),_.bindAll(this,"close"),c("#customize-controls, .customize-section-back").on("click keydown",function(a){var d=c(a.target).is(".item-delete, .item-delete *"),e=c(a.target).is(".add-new-menu-item, .add-new-menu-item *");!c("body").hasClass("adding-menu-items")||d||e||b.close()}),c(".clear-results").on("click keydown",function(a){("keydown"!==a.type||13===a.which||32===a.which)&&(a.preventDefault(),c("#menu-items-search").val("").focus(),a.target.value="",b.search(a))}),this.$el.on("input","#custom-menu-item-name.invalid, #custom-menu-item-url.invalid",function(){c(this).removeClass("invalid")}),a.panel("nav_menus").container.bind("expanded",function(){b.rendered||(b.initList(),b.rendered=!0)}),this.sectionContent.scroll(function(){var a=b.$el.find(".accordion-section.open .accordion-section-content").prop("scrollHeight"),d=b.$el.find(".accordion-section.open").height();if(!b.loading&&c(this).scrollTop()>.75*a-d){var e=c(this).data("type"),f=c(this).data("object");"search"===e?b.searchTerm&&b.doSearch(b.pages.search):b.loadItems(e,f)}}),a.previewer.bind("url",this.close))},search:function(a){var b=c("#available-menu-items-search"),d=c("#available-menu-items .accordion-section").not(b);a&&this.searchTerm!==a.target.value&&(""===a.target.value||b.hasClass("open")?""===a.target.value&&(b.removeClass("open"),d.show(),b.find(".clear-results").prop("tabIndex",-1).removeClass("is-visible")):(d.fadeOut(100),b.find(".accordion-section-content").slideDown("fast"),b.addClass("open"),b.find(".clear-results").prop("tabIndex",0).addClass("is-visible")),this.searchTerm=a.target.value,this.pages.search=1,this.doSearch(1))},doSearch:function(d){var e,f=this,g=c("#available-menu-items-search"),h=g.find(".accordion-section-content"),i=b.template("available-menu-item");if(f.currentRequest&&f.currentRequest.abort(),!(0>d)){if(d>1)g.addClass("loading-more"),h.attr("aria-busy","true"),b.a11y.speak(a.Menus.data.l10n.itemsLoadingMore);else if(""===f.searchTerm)return h.html(""),void b.a11y.speak("");g.addClass("loading"),f.loading=!0,e={"customize-menus-nonce":a.settings.nonce["customize-menus"],wp_customize:"on",search:f.searchTerm,page:d},f.currentRequest=b.ajax.post("search-available-menu-items-customizer",e),f.currentRequest.done(function(c){var e;1===d&&h.empty(),g.removeClass("loading loading-more"),h.attr("aria-busy","false"),g.addClass("open"),f.loading=!1,e=new a.Menus.AvailableItemCollection(c.items),f.collection.add(e.models),e.each(function(a){h.append(i(a.attributes))}),20>e.length?f.pages.search=-1:f.pages.search=f.pages.search+1,e&&d>1?b.a11y.speak(a.Menus.data.l10n.itemsFoundMore.replace("%d",e.length)):e&&1===d&&b.a11y.speak(a.Menus.data.l10n.itemsFound.replace("%d",e.length))}),f.currentRequest.fail(function(a){a.message&&(h.empty().append(c('
').text(a.message)),b.a11y.speak(a.message)),f.pages.search=-1}),f.currentRequest.always(function(){g.removeClass("loading loading-more"),h.attr("aria-busy","false"),f.loading=!1,f.currentRequest=null})}},initList:function(){var b=this;_.each(a.Menus.data.itemTypes,function(a){b.pages[a.type+":"+a.object]=0,b.loadItems(a.type,a.object)})},loadItems:function(d,e){var f,g,h,i,j=this;h=b.template("available-menu-item"),-1!==j.pages[d+":"+e]&&(i=c("#available-menu-items-"+d+"-"+e),i.find(".accordion-section-title").addClass("loading"),j.loading=!0,f={"customize-menus-nonce":a.settings.nonce["customize-menus"],wp_customize:"on",type:d,object:e,page:j.pages[d+":"+e]},g=b.ajax.post("load-available-menu-items-customizer",f),g.done(function(b){var c,f;return c=b.items,0===c.length?(0===j.pages[d+":"+e]&&i.addClass("cannot-expand").removeClass("loading").find(".accordion-section-title > button").prop("tabIndex",-1),void(j.pages[d+":"+e]=-1)):(c=new a.Menus.AvailableItemCollection(c),j.collection.add(c.models),f=i.find(".accordion-section-content"),c.each(function(a){f.append(h(a.attributes))}),void(j.pages[d+":"+e]+=1))}),g.fail(function(a){"undefined"!=typeof console&&console.error&&console.error(a)}),g.always(function(){i.find(".accordion-section-title").removeClass("loading"),j.loading=!1}))},itemSectionHeight:function(){var a,b,c,d;b=window.innerHeight,a=this.$el.find(".accordion-section:not( #available-menu-items-search ) .accordion-section-content"),c=46*(2+a.length)-13,d=b-c,d>120&&290>d&&a.css("max-height",d)},select:function(a){this.selected=c(a),this.selected.siblings(".menu-item-tpl").removeClass("selected"),this.selected.addClass("selected")},focus:function(a){this.select(c(a.currentTarget))},_submit:function(a){("keypress"!==a.type||13===a.which||32===a.which)&&this.submit(c(a.currentTarget))},submit:function(a){var b,d;a||(a=this.selected),a&&this.currentMenuControl&&(this.select(a),b=c(this.selected).data("menu-item-id"),d=this.collection.findWhere({id:b}),d&&(this.currentMenuControl.addItemToMenu(d.attributes),c(a).find(".menu-item-handle").addClass("item-added")))},_submitLink:function(a){("keypress"!==a.type||13===a.which)&&this.submitLink()},submitLink:function(){var b,d=c("#custom-menu-item-name"),e=c("#custom-menu-item-url");if(this.currentMenuControl){if(""===d.val())return void d.addClass("invalid");if(""===e.val()||"http://"===e.val())return void e.addClass("invalid");b={title:d.val(),url:e.val(),type:"custom",type_label:a.Menus.data.l10n.custom_label,object:""},this.currentMenuControl.addItemToMenu(b),e.val("http://"),d.val("")}},open:function(a){this.currentMenuControl=a,this.itemSectionHeight(),c("body").addClass("adding-menu-items"),_(this.currentMenuControl.getMenuItemControls()).each(function(a){a.collapseForm()}),this.$el.find(".selected").removeClass("selected"),this.$search.focus()},close:function(a){a=a||{},a.returnFocus&&this.currentMenuControl&&this.currentMenuControl.container.find(".add-new-menu-item").focus(),this.currentMenuControl=null,this.selected=null,c("body").removeClass("adding-menu-items"),c("#available-menu-items .menu-item-handle.item-added").removeClass("item-added"),this.$search.val("")},keyboardAccessible:function(a){var b=13===a.which,d=27===a.which,e=9===a.which&&a.shiftKey,f=c(a.target).is(this.$search);(!b||this.$search.val())&&(f&&e?(this.currentMenuControl.container.find(".add-new-menu-item").focus(),a.preventDefault()):d&&this.close({returnFocus:!0}))}}),a.Menus.MenusPanel=a.Panel.extend({attachEvents:function(){a.Panel.prototype.attachEvents.call(this);var b=this,d=b.container.find(".panel-meta"),e=d.find(".customize-help-toggle"),f=d.find(".customize-panel-description"),g=c("#screen-options-wrap"),h=d.find(".customize-screen-options-toggle");h.on("click keydown",function(b){return a.utils.isKeydownButNotEnterEvent(b)?void 0:(b.preventDefault(),f.not(":hidden")&&(f.slideUp("fast"),e.attr("aria-expanded","false")),"true"===h.attr("aria-expanded")?(h.attr("aria-expanded","false"),d.removeClass("open"),d.removeClass("active-menu-screen-options"),g.slideUp("fast")):(h.attr("aria-expanded","true"),d.addClass("open"),d.addClass("active-menu-screen-options"),g.slideDown("fast")),!1)}),e.on("click keydown",function(b){a.utils.isKeydownButNotEnterEvent(b)||(b.preventDefault(),"true"===h.attr("aria-expanded")&&(h.attr("aria-expanded","false"),e.attr("aria-expanded","true"),d.addClass("open"),d.removeClass("active-menu-screen-options"),g.slideUp("fast"),f.slideDown("fast")))})},ready:function(){var a=this;this.container.find(".hide-column-tog").click(function(){var b=c(this),d=b.val();b.prop("checked")?a.checked(d):a.unchecked(d),a.saveManageColumnsState()}),this.container.find(".hide-column-tog").each(function(){var b=c(this),d=b.val();b.prop("checked")?a.checked(d):a.unchecked(d)})},saveManageColumnsState:function(){var a=this.hidden();c.post(b.ajax.settings.url,{action:"hidden-columns",hidden:a,screenoptionnonce:c("#screenoptionnonce").val(),page:"nav-menus"})},checked:function(a){this.container.addClass("field-"+a+"-active")},unchecked:function(a){this.container.removeClass("field-"+a+"-active")},hidden:function(){this.hidden=function(){return c(".hide-column-tog").not(":checked").map(function(){var a=this.id;return a.substring(a,a.length-5)}).get().join(",")}}}),a.Menus.MenuSection=a.Section.extend({initialize:function(b,d){var e=this;a.Section.prototype.initialize.call(e,b,d),e.deferred.initSortables=c.Deferred()},ready:function(){var b=this;if("undefined"==typeof b.params.menu_id)throw new Error("params.menu_id was not defined");b.active.validate=function(){return a.has(b.id)?!!a(b.id).get():!1},b.populateControls(),b.navMenuLocationSettings={},b.assignedLocations=new a.Value([]),a.each(function(a,c){var d=c.match(/^nav_menu_locations\[(.+?)]/);d&&(b.navMenuLocationSettings[d[1]]=a,a.bind(function(){b.refreshAssignedLocations()}))}),b.assignedLocations.bind(function(a){b.updateAssignedLocationsInSectionTitle(a)}),b.refreshAssignedLocations(),a.bind("pane-contents-reflowed",function(){b.container.parent().length&&(b.container.find(".menu-item .menu-item-reorder-nav button").attr({tabindex:"0","aria-hidden":"false"}),b.container.find(".menu-item.move-up-disabled .menus-move-up").attr({tabindex:"-1","aria-hidden":"true"}),b.container.find(".menu-item.move-down-disabled .menus-move-down").attr({tabindex:"-1","aria-hidden":"true"}),b.container.find(".menu-item.move-left-disabled .menus-move-left").attr({tabindex:"-1","aria-hidden":"true"}),b.container.find(".menu-item.move-right-disabled .menus-move-right").attr({tabindex:"-1","aria-hidden":"true"}))})},populateControls:function(){var b,c,d,e,f,g=this;b=g.id+"[name]",e=a.control(b),e||(e=new a.controlConstructor.nav_menu_name(b,{params:{type:"nav_menu_name",content:'',label:a.Menus.data.l10n.menuNameLabel,active:!0,section:g.id,priority:0,settings:{"default":g.id}}}),a.control.add(e.id,e),e.active.set(!0)),d=a.control(g.id),d||(d=new a.controlConstructor.nav_menu(g.id,{params:{type:"nav_menu",content:'',section:g.id,priority:998,active:!0,settings:{"default":g.id},menu_id:g.params.menu_id}}),a.control.add(d.id,d),d.active.set(!0)),c=g.id+"[auto_add]",f=a.control(c),f||(f=new a.controlConstructor.nav_menu_auto_add(c,{params:{type:"nav_menu_auto_add",content:'',label:"",active:!0,section:g.id,priority:999,settings:{"default":g.id}}}),a.control.add(f.id,f),f.active.set(!0))},refreshAssignedLocations:function(){var a=this,b=a.params.menu_id,c=[];_.each(a.navMenuLocationSettings,function(a,d){a()===b&&c.push(d)}),a.assignedLocations.set(c)},updateAssignedLocationsInSectionTitle:function(b){var d,e=this;d=e.container.find(".accordion-section-title:first"),d.find(".menu-in-location").remove(),_.each(b,function(b){var e,f;e=c(''),f=a.Menus.data.locationSlugMappedToName[b],e.text(a.Menus.data.l10n.menuLocation.replace("%s",f)),d.append(e)}),e.container.toggleClass("assigned-to-menu-location",0!==b.length)},onChangeExpanded:function(b,d){var e=this;b&&(wpNavMenu.menuList=e.container.find(".accordion-section-content:first"),wpNavMenu.targetList=wpNavMenu.menuList,c("#menu-to-edit").removeAttr("id"),wpNavMenu.menuList.attr("id","menu-to-edit").addClass("menu"),_.each(a.section(e.id).controls(),function(a){"nav_menu_item"===a.params.type&&a.actuallyEmbed()}),"resolved"!==e.deferred.initSortables.state()&&(wpNavMenu.initSortables(),e.deferred.initSortables.resolve(wpNavMenu.menuList),a.control("nav_menu["+String(e.params.menu_id)+"]").reflowMenuItems())),a.Section.prototype.onChangeExpanded.call(e,b,d)}}),a.Menus.NewMenuSection=a.Section.extend({attachEvents:function(){var a=this;this.container.on("click",".add-menu-toggle",function(){a.expanded()?a.collapse():a.expand()})},onChangeExpanded:function(a){var b=this,c=b.container.find(".add-menu-toggle"),d=b.container.find(".new-menu-section-content"),e=b.container.closest(".wp-full-overlay-sidebar-content");a?(c.addClass("open"),c.attr("aria-expanded","true"),d.slideDown("fast",function(){e.scrollTop(e.height())})):(c.removeClass("open"),c.attr("aria-expanded","false"),d.slideUp("fast"),d.find(".menu-name-field").removeClass("invalid"))}}),a.Menus.MenuLocationControl=a.Control.extend({initialize:function(b,c){var d=this,e=b.match(/^nav_menu_locations\[(.+?)]/);d.themeLocation=e[1],a.Control.prototype.initialize.call(d,b,c)},ready:function(){var b=this,c=/^nav_menu\[(-?\d+)]/;b.setting.validate=function(a){return parseInt(a,10)},a.bind("add",function(a){var d,f,g=a.id.match(c);g&&!1!==a()&&(f=g[1],d=new Option(e(a().name),f),b.container.find("select").append(d))}),a.bind("remove",function(a){var d,e=a.id.match(c);e&&(d=parseInt(e[1],10),b.setting()===d&&b.setting.set(""),b.container.find("option[value="+d+"]").remove())}),a.bind("change",function(a){var d,f=a.id.match(c);f&&(d=parseInt(f[1],10),!1===a()?(b.setting()===d&&b.setting.set(""),b.container.find("option[value="+d+"]").remove()):b.container.find("option[value="+d+"]").text(e(a().name)))})}}),a.Menus.MenuItemControl=a.Control.extend({initialize:function(b,c){var d=this;a.Control.prototype.initialize.call(d,b,c),d.active.validate=function(){var b,c=a.section(d.section());return b=c?c.active():!1}},embed:function(){var b,c=this,d=c.section();d&&(b=a.section(d),(b&&b.expanded()||a.settings.autofocus.control===c.id)&&c.actuallyEmbed())},actuallyEmbed:function(){var a=this;"resolved"!==a.deferred.embedded.state()&&(a.renderContent(),a.deferred.embedded.resolve())},ready:function(){if("undefined"==typeof this.params.menu_item_id)throw new Error("params.menu_item_id was not defined");this._setupControlToggle(),this._setupReorderUI(),this._setupUpdateUI(),this._setupRemoveUI(),this._setupLinksUI(),this._setupTitleUI()},_setupControlToggle:function(){var a=this;this.container.find(".menu-item-handle").on("click",function(b){b.preventDefault(),b.stopPropagation();var c=a.getMenuControl();c.isReordering||c.isSorting||a.toggleForm()})},_setupReorderUI:function(){var a,d,e=this;a=b.template("menu-item-reorder-nav"),e.container.find(".item-controls").after(a),d=e.container.find(".menu-item-reorder-nav"),d.find(".menus-move-up, .menus-move-down, .menus-move-left, .menus-move-right").on("click",function(){var a=c(this);a.focus();var b=a.is(".menus-move-up"),d=a.is(".menus-move-down"),f=a.is(".menus-move-left"),g=a.is(".menus-move-right");b?e.moveUp():d?e.moveDown():f?e.moveLeft():g&&e.moveRight(),a.focus()})},_setupUpdateUI:function(){var b=this,c=b.setting();b.elements={},b.elements.url=new a.Element(b.container.find(".edit-menu-item-url")),b.elements.title=new a.Element(b.container.find(".edit-menu-item-title")),b.elements.attr_title=new a.Element(b.container.find(".edit-menu-item-attr-title")),b.elements.target=new a.Element(b.container.find(".edit-menu-item-target")),b.elements.classes=new a.Element(b.container.find(".edit-menu-item-classes")),b.elements.xfn=new a.Element(b.container.find(".edit-menu-item-xfn")),b.elements.description=new a.Element(b.container.find(".edit-menu-item-description")),_.each(b.elements,function(a,d){a.bind(function(c){a.element.is("input[type=checkbox]")&&(c=c?a.element.val():"");var e=b.setting();e&&e[d]!==c&&(e=_.clone(e),e[d]=c,b.setting.set(e))}),c&&("classes"!==d&&"xfn"!==d||!_.isArray(c[d])?a.set(c[d]):a.set(c[d].join(" ")))}),b.setting.bind(function(c,d){var e,f=b.params.menu_item_id,g=[],h=[];!1===c?(e=a.control("nav_menu["+String(d.nav_menu_term_id)+"]"),b.container.remove(),_.each(e.getMenuItemControls(),function(a){d.menu_item_parent===a.setting().menu_item_parent&&a.setting().position>d.position?g.push(a):a.setting().menu_item_parent===f&&h.push(a)}),_.each(g,function(a){var b=_.clone(a.setting());b.position+=h.length,a.setting.set(b)}),_.each(h,function(a,b){var c=_.clone(a.setting());c.position=d.position+b,c.menu_item_parent=d.menu_item_parent,a.setting.set(c)}),e.debouncedReflowMenuItems()):(_.each(c,function(a,d){b.elements[d]&&b.elements[d].set(c[d])}),b.container.find(".menu-item-data-parent-id").val(c.menu_item_parent),(c.position!==d.position||c.menu_item_parent!==d.menu_item_parent)&&b.getMenuControl().debouncedReflowMenuItems())})},_setupRemoveUI:function(){var d,e=this;d=e.container.find(".item-delete"),d.on("click",function(){var d,f,g,h=!0;c("body").hasClass("adding-menu-items")||(h=!1),f=e.container.nextAll(".customize-control-nav_menu_item:visible").first(),g=e.container.prevAll(".customize-control-nav_menu_item:visible").first(),d=f.length?f.find(!1===h?".item-edit":".item-delete").first():g.length?g.find(!1===h?".item-edit":".item-delete").first():e.container.nextAll(".customize-control-nav_menu").find(".add-new-menu-item").first(),e.container.slideUp(function(){e.setting.set(!1),b.a11y.speak(a.Menus.data.l10n.itemDeleted),d.focus()})})},_setupLinksUI:function(){var b;b=this.container.find("a.original-link"),b.on("click",function(b){b.preventDefault(),a.previewer.previewUrl(b.target.toString())})},_setupTitleUI:function(){var b=this;b.setting.bind(function(c){if(c){var d=b.container.find(".menu-item-title"),e=c.title||a.Menus.data.l10n.untitled;c._invalid&&(e=a.Menus.data.l10n.invalidTitleTpl.replace("%s",e)),c.title?d.text(e).removeClass("no-title"):d.text(e).addClass("no-title")}})},getDepth:function(){var b=this,c=b.setting(),d=0;if(!c)return 0;for(;c&&c.menu_item_parent&&(d+=1,b=a.control("nav_menu_item["+c.menu_item_parent+"]"));)c=b.setting();return d},renderContent:function(){var b,c=this,d=c.setting();c.params.title=d.title||"",c.params.depth=c.getDepth(),c.container.data("item-depth",c.params.depth),b=["menu-item","menu-item-depth-"+String(c.params.depth),"menu-item-"+d.object,"menu-item-edit-inactive"],d._invalid?(b.push("menu-item-invalid"),c.params.title=a.Menus.data.l10n.invalidTitleTpl.replace("%s",c.params.title)):"draft"===d.status&&(b.push("pending"),c.params.title=a.Menus.data.pendingTitleTpl.replace("%s",c.params.title)),c.params.el_classes=b.join(" "),c.params.item_type_label=d.type_label,c.params.item_type=d.type,c.params.url=d.url,c.params.target=d.target,c.params.attr_title=d.attr_title,c.params.classes=_.isArray(d.classes)?d.classes.join(" "):d.classes,c.params.attr_title=d.attr_title,c.params.xfn=d.xfn,c.params.description=d.description,c.params.parent=d.menu_item_parent,c.params.original_title=d.original_title||"",c.container.addClass(c.params.el_classes),a.Control.prototype.renderContent.call(c)},getMenuControl:function(){var b=this,c=b.setting();return c&&c.nav_menu_term_id?a.control("nav_menu["+c.nav_menu_term_id+"]"):null},expandControlSection:function(){var a=this.container.closest(".accordion-section");a.hasClass("open")||a.find(".accordion-section-title:first").trigger("click")},expandForm:function(a){this.toggleForm(!0,a)},collapseForm:function(a){this.toggleForm(!1,a)},toggleForm:function(b,c){var d,e,f,g=this;return d=this.container,e=d.find(".menu-item-settings:first"),"undefined"==typeof b&&(b=!e.is(":visible")),e.is(":visible")===b?void(c&&c.completeCallback&&c.completeCallback()):void(b?(a.control.each(function(a){g.params.type===a.params.type&&g!==a&&a.collapseForm()}),f=function(){d.removeClass("menu-item-edit-inactive").addClass("menu-item-edit-active"),g.container.trigger("expanded"),c&&c.completeCallback&&c.completeCallback()},d.find(".item-edit").attr("aria-expanded","true"),e.slideDown("fast",f),g.container.trigger("expand")):(f=function(){d.addClass("menu-item-edit-inactive").removeClass("menu-item-edit-active"),g.container.trigger("collapsed"),c&&c.completeCallback&&c.completeCallback()},g.container.trigger("collapse"),d.find(".item-edit").attr("aria-expanded","false"),e.slideUp("fast",f)))},focus:function(a){a=a||{};var b=this,c=a.completeCallback;b.expandControlSection(),a.completeCallback=function(){var a;a=b.container.find(".menu-item-settings").find("input, select, textarea, button, object, a[href], [tabindex]").filter(":visible"),a.first().focus(),c&&c()},b.expandForm(a)},moveUp:function(){this._changePosition(-1),b.a11y.speak(a.Menus.data.l10n.movedUp)},moveDown:function(){this._changePosition(1),b.a11y.speak(a.Menus.data.l10n.movedDown)},moveLeft:function(){this._changeDepth(-1),b.a11y.speak(a.Menus.data.l10n.movedLeft)},moveRight:function(){this._changeDepth(1),b.a11y.speak(a.Menus.data.l10n.movedRight)},_changePosition:function(a){var b,d,e=this,f=_.clone(e.setting()),g=[];if(1!==a&&-1!==a)throw new Error("Offset changes by 1 are only supported.");if(e.setting()){if(_(e.getMenuControl().getMenuItemControls()).each(function(a){a.setting().menu_item_parent===f.menu_item_parent&&g.push(a.setting)}),g.sort(function(a,b){return a().position-b().position}),d=_.indexOf(g,e.setting),-1===d)throw new Error("Expected setting to be among siblings.");0===d&&0>a||d===g.length-1&&a>0||(b=g[d+a],b&&b.set(c.extend(_.clone(b()),{position:f.position})),f.position+=a,e.setting.set(f))}},_changeDepth:function(b){if(1!==b&&-1!==b)throw new Error("Offset changes by 1 are only supported.");var d,e,f,g=this,h=_.clone(g.setting()),i=[];if(_(g.getMenuControl().getMenuItemControls()).each(function(a){a.setting().menu_item_parent===h.menu_item_parent&&i.push(a)}),i.sort(function(a,b){return a.setting().position-b.setting().position}),d=_.indexOf(i,g),-1===d)throw new Error("Expected control to be among siblings.");if(-1===b){if(!h.menu_item_parent)return;f=a.control("nav_menu_item["+h.menu_item_parent+"]"),_(i).chain().slice(d).each(function(a,b){a.setting.set(c.extend({},a.setting(),{menu_item_parent:g.params.menu_item_id,position:b}))}),_(g.getMenuControl().getMenuItemControls()).each(function(a){var b,d;d=a.setting().menu_item_parent===f.setting().menu_item_parent&&a.setting().position>f.setting().position,d&&(b=_.clone(a.setting()),a.setting.set(c.extend(b,{position:b.position+1})))}),h.position=f.setting().position+1,h.menu_item_parent=f.setting().menu_item_parent,g.setting.set(h)}else if(1===b){if(0===d)return;e=i[d-1],h.menu_item_parent=e.params.menu_item_id,h.position=0,_(g.getMenuControl().getMenuItemControls()).each(function(a){a.setting().menu_item_parent===h.menu_item_parent&&(h.position=Math.max(h.position,a.setting().position))}),h.position+=1,g.setting.set(h)}}}),a.Menus.MenuNameControl=a.Control.extend({ready:function(){var b=this,c=b.setting();b.active.validate=function(){var c,d=a.section(b.section());return c=d?d.active():!1},b.nameElement=new a.Element(b.container.find(".menu-name-field")),b.nameElement.bind(function(a){var c=b.setting();c&&c.name!==a&&(c=_.clone(c),c.name=a,b.setting.set(c))}),c&&b.nameElement.set(c.name),b.setting.bind(function(a){a&&b.nameElement.set(a.name)})}}),a.Menus.MenuAutoAddControl=a.Control.extend({ready:function(){var b=this,c=b.setting();b.active.validate=function(){var c,d=a.section(b.section());return c=d?d.active():!1},b.autoAddElement=new a.Element(b.container.find("input[type=checkbox].auto_add")),b.autoAddElement.bind(function(a){var c=b.setting();c&&c.name!==a&&(c=_.clone(c),c.auto_add=a,b.setting.set(c))}),c&&b.autoAddElement.set(c.auto_add),b.setting.bind(function(a){a&&b.autoAddElement.set(a.auto_add)})}}),a.Menus.MenuControl=a.Control.extend({ready:function(){var b,d,f,g=this,h=g.params.menu_id,i=g.setting();if("undefined"==typeof this.params.menu_id)throw new Error("params.menu_id was not defined");g.active.validate=function(){var b,c=a.section(g.section());return b=c?c.active():!1},g.$controlSection=g.container.closest(".control-section"),g.$sectionContent=g.container.closest(".accordion-section-content"),this._setupModel(),a.section(g.section(),function(a){a.deferred.initSortables.done(function(a){g._setupSortable(a)})}),this._setupAddition(),this._setupLocations(),this._setupTitle(),i&&(b=e(i.name),a.control.each(function(c){c.extended(a.controlConstructor.widget_form)&&"nav_menu"===c.params.widget_id_base&&(c.container.find(".nav-menu-widget-form-controls:first").show(),c.container.find(".nav-menu-widget-no-menus-message:first").hide(),f=c.container.find("select"),0===f.find("option[value="+String(h)+"]").length&&f.append(new Option(b,h)))}),d=c("#available-widgets-list .widget-tpl:has( input.id_base[ value=nav_menu ] )"),d.find(".nav-menu-widget-form-controls:first").show(),d.find(".nav-menu-widget-no-menus-message:first").hide(),f=d.find(".widget-inside select:first"),0===f.find("option[value="+String(h)+"]").length&&f.append(new Option(b,h)))},_setupModel:function(){var b=this,c=b.params.menu_id;b.setting.bind(function(d){var f;!1===d?b._handleDeletion():(f=e(d.name),a.control.each(function(b){if(b.extended(a.controlConstructor.widget_form)&&"nav_menu"===b.params.widget_id_base){var d=b.container.find("select");d.find("option[value="+String(c)+"]").text(f)}}))}),b.container.find(".menu-delete").on("click",function(a){a.stopPropagation(),a.preventDefault(),b.setting.set(!1)})},_setupSortable:function(b){var c=this;if(!b.is(c.$sectionContent))throw new Error("Unexpected menuList.");b.on("sortstart",function(){c.isSorting=!0}),b.on("sortstop",function(){setTimeout(function(){var b=c.$sectionContent.sortable("toArray"),d=[],e=0,f=10;c.isSorting=!1,c.$sectionContent.scrollLeft(0),_.each(b,function(b){var c,e,f;f=b.match(/^customize-control-nav_menu_item-(-?\d+)$/,""),f&&(c=parseInt(f[1],10),e=a.control("nav_menu_item["+String(c)+"]"),e&&d.push(e))}),_.each(d,function(a){if(!1!==a.setting()){var b=_.clone(a.setting());e+=1,f+=1,b.position=e,a.priority(f),b.menu_item_parent=parseInt(a.container.find(".menu-item-data-parent-id").val(),10),b.menu_item_parent||(b.menu_item_parent=0),a.setting.set(b)}})})}),c.isReordering=!1,this.container.find(".reorder-toggle").on("click",function(){c.toggleReordering(!c.isReordering)})},_setupAddition:function(){var b=this;this.container.find(".add-new-menu-item").on("click",function(d){b.$sectionContent.hasClass("reordering")||(c("body").hasClass("adding-menu-items")?(c(this).attr("aria-expanded","false"),a.Menus.availableMenuItemsPanel.close(),d.stopPropagation()):(c(this).attr("aria-expanded","true"),a.Menus.availableMenuItemsPanel.open(b)))})},_handleDeletion:function(){var d,e,f,g=this,h=g.params.menu_id,i=0;d=a.section(g.section()),e=function(){d.container.remove(),a.section.remove(d.id)},d&&d.expanded()?d.collapse({completeCallback:function(){e(),b.a11y.speak(a.Menus.data.l10n.menuDeleted),a.panel("nav_menus").focus()}}):e(),a.each(function(a){/^nav_menu\[/.test(a.id)&&!1!==a()&&(i+=1)}),a.control.each(function(b){if(b.extended(a.controlConstructor.widget_form)&&"nav_menu"===b.params.widget_id_base){var c=b.container.find("select");c.val()===String(h)&&c.prop("selectedIndex",0).trigger("change"),b.container.find(".nav-menu-widget-form-controls:first").toggle(0!==i),b.container.find(".nav-menu-widget-no-menus-message:first").toggle(0===i),b.container.find("option[value="+String(h)+"]").remove()}}),f=c("#available-widgets-list .widget-tpl:has( input.id_base[ value=nav_menu ] )"),f.find(".nav-menu-widget-form-controls:first").toggle(0!==i),f.find(".nav-menu-widget-no-menus-message:first").toggle(0===i),f.find("option[value="+String(h)+"]").remove()},_setupLocations:function(){var b=this;b.container.find(".assigned-menu-location").each(function(){var d,f,g=c(this),h=g.find("input[type=checkbox]"),i=a("nav_menu_locations["+h.data("location-id")+"]");f=function(b){var c=a("nav_menu["+String(b)+"]");b&&c&&c()?g.find(".theme-location-set").show().find("span").text(e(c().name)):g.find(".theme-location-set").hide()},d=new a.Element(h),d.set(i.get()===b.params.menu_id),h.on("change",function(){i.set(this.checked?b.params.menu_id:0)}),i.bind(function(a){d.set(a===b.params.menu_id),f(a)}),f(i.get())})},_setupTitle:function(){var b=this;b.setting.bind(function(d){if(d){var f=b.container.closest(".accordion-section"),g=b.params.menu_id,h=f.find(".accordion-section-title"),i=f.find(".customize-section-title h3"),j=f.find(".menu-in-location"),k=i.find(".customize-action"),l=e(d.name);h.text(l),j.length&&j.appendTo(h),i.text(l),k.length&&k.prependTo(i),a.control.each(function(a){/^nav_menu_locations\[/.test(a.id)&&a.container.find("option[value="+g+"]").text(l)}),f.find(".customize-control-checkbox input").each(function(){c(this).prop("checked")&&c(".current-menu-location-name-"+c(this).data("location-id")).text(l)})}})},toggleReordering:function(c){var d=this.container.find(".add-new-menu-item"),e=this.container.find(".reorder-toggle"),f=this.$sectionContent.find(".item-title");c=Boolean(c),c!==this.$sectionContent.hasClass("reordering")&&(this.isReordering=c,this.$sectionContent.toggleClass("reordering",c),this.$sectionContent.sortable(this.isReordering?"disable":"enable"),this.isReordering?(d.attr({tabindex:"-1","aria-hidden":"true"}),e.attr("aria-label",a.Menus.data.l10n.reorderLabelOff),b.a11y.speak(a.Menus.data.l10n.reorderModeOn),f.attr("aria-hidden","false")):(d.removeAttr("tabindex aria-hidden"),e.attr("aria-label",a.Menus.data.l10n.reorderLabelOn),b.a11y.speak(a.Menus.data.l10n.reorderModeOff),f.attr("aria-hidden","true")),c&&_(this.getMenuItemControls()).each(function(a){a.collapseForm()}))},getMenuItemControls:function(){var b=this,c=[],d=b.params.menu_id;return a.control.each(function(a){"nav_menu_item"===a.params.type&&a.setting()&&d===a.setting().nav_menu_term_id&&c.push(a)}),c},reflowMenuItems:function(){var a,b=this,c=b.getMenuItemControls();a=function(b){var c=[],d=b.currentParent;_.each(b.menuItemControls,function(a){d===a.setting().menu_item_parent&&c.push(a)}),c.sort(function(a,b){return a.setting().position-b.setting().position}),_.each(c,function(c){b.currentAbsolutePosition+=1,c.priority.set(b.currentAbsolutePosition),c.container.hasClass("menu-item-depth-"+String(b.currentDepth))||(_.each(c.container.prop("className").match(/menu-item-depth-\d+/g),function(a){c.container.removeClass(a)}),c.container.addClass("menu-item-depth-"+String(b.currentDepth))),c.container.data("item-depth",b.currentDepth),b.currentDepth+=1,
-b.currentParent=c.params.menu_item_id,a(b),b.currentDepth-=1,b.currentParent=d}),c.length&&(_(c).each(function(a){a.container.removeClass("move-up-disabled move-down-disabled move-left-disabled move-right-disabled"),0===b.currentDepth?a.container.addClass("move-left-disabled"):10===b.currentDepth&&a.container.addClass("move-right-disabled")}),c[0].container.addClass("move-up-disabled").addClass("move-right-disabled").toggleClass("move-down-disabled",1===c.length),c[c.length-1].container.addClass("move-down-disabled").toggleClass("move-up-disabled",1===c.length))},a({menuItemControls:c,currentParent:0,currentDepth:0,currentAbsolutePosition:0}),b.container.find(".reorder-toggle").toggle(c.length>1)},debouncedReflowMenuItems:_.debounce(function(){this.reflowMenuItems.apply(this,arguments)},0),addItemToMenu:function(d){var e,f,g,h,i,j=this,k=0,l=10;return _.each(j.getMenuItemControls(),function(a){!1!==a.setting()&&(l=Math.max(l,a.priority()),0===a.setting().menu_item_parent&&(k=Math.max(k,a.setting().position)))}),k+=1,l+=1,d=c.extend({},a.Menus.data.defaultSettingValues.nav_menu_item,d,{nav_menu_term_id:j.params.menu_id,original_title:d.title,position:k}),delete d.id,i=a.Menus.generatePlaceholderAutoIncrementId(),e="nav_menu_item["+String(i)+"]",f={type:"nav_menu_item",transport:"postMessage",previewer:a.previewer},g=a.create(e,e,{},f),g.set(d),h=new a.controlConstructor.nav_menu_item(e,{params:{type:"nav_menu_item",content:'',section:j.id,priority:l,active:!0,settings:{"default":e},menu_item_id:i},previewer:a.previewer}),a.control.add(e,h),g.preview(),j.debouncedReflowMenuItems(),b.a11y.speak(a.Menus.data.l10n.itemAdded),h}}),a.Menus.NewMenuControl=a.Control.extend({ready:function(){this._bindHandlers()},_bindHandlers:function(){var a=this,b=c("#customize-control-new_menu_name input"),d=c("#create-new-menu-submit");b.on("keydown",function(b){13===b.which&&a.submit()}),d.on("click",function(b){a.submit(),b.stopPropagation(),b.preventDefault()})},submit:function(){var d,f,g=this,h=g.container.closest(".accordion-section-new-menu"),i=h.find(".menu-name-field").first(),j=i.val(),k=a.Menus.generatePlaceholderAutoIncrementId();return j?(f="nav_menu["+String(k)+"]",a.create(f,f,{},{type:"nav_menu",transport:"postMessage",previewer:a.previewer}),a(f).set(c.extend({},a.Menus.data.defaultSettingValues.nav_menu,{name:j})),d=new a.Menus.MenuSection(f,{params:{id:f,panel:"nav_menus",title:e(j),customizeAction:a.Menus.data.l10n.customizingMenus,type:"nav_menu",priority:10,menu_id:k}}),a.section.add(f,d),i.val(""),i.removeClass("invalid"),b.a11y.speak(a.Menus.data.l10n.menuAdded),a.section(f).focus(),void c("#menu-to-edit").css("margin-top",0)):(i.addClass("invalid"),void i.focus())}}),c.extend(a.controlConstructor,{nav_menu_location:a.Menus.MenuLocationControl,nav_menu_item:a.Menus.MenuItemControl,nav_menu:a.Menus.MenuControl,nav_menu_name:a.Menus.MenuNameControl,nav_menu_auto_add:a.Menus.MenuAutoAddControl,new_menu:a.Menus.NewMenuControl}),c.extend(a.panelConstructor,{nav_menus:a.Menus.MenusPanel}),c.extend(a.sectionConstructor,{nav_menu:a.Menus.MenuSection,new_menu:a.Menus.NewMenuSection}),a.bind("ready",function(){a.Menus.availableMenuItemsPanel=new a.Menus.AvailableMenuItemsPanelView({collection:a.Menus.availableMenuItems}),a.bind("saved",function(b){(b.nav_menu_updates||b.nav_menu_item_updates)&&a.Menus.applySavedData(b)}),a.previewer.bind("refresh",function(){a.previewer.refresh()}),a.previewer.bind("focus-nav-menu-item-control",a.Menus.focusMenuItemControl)}),a.Menus.applySavedData=function(d){var e={},f={};_(d.nav_menu_updates).each(function(d){var f,g,h,i,j,k,l,m,n,o,p,q;if("inserted"===d.status){if(!d.previous_term_id)throw new Error("Expected previous_term_id");if(!d.term_id)throw new Error("Expected term_id");if(f="nav_menu["+String(d.previous_term_id)+"]",!a.has(f))throw new Error("Expected setting to exist: "+f);if(i=a(f),!a.section.has(f))throw new Error("Expected control to exist: "+f);if(m=a.section(f),l=i.get(),!l)throw new Error("Did not expect setting to be empty (deleted).");l=c.extend(_.clone(l),d.saved_value),e[d.previous_term_id]=d.term_id,g="nav_menu["+String(d.term_id)+"]",j=a.create(g,g,l,{type:"nav_menu",transport:"postMessage",previewer:a.previewer}),m.expanded()&&m.collapse(),n=new a.Menus.MenuSection(g,{params:{id:g,panel:"nav_menus",title:l.name,customizeAction:a.Menus.data.l10n.customizingMenus,type:"nav_menu",priority:m.priority.get(),active:!0,menu_id:d.term_id}}),a.section.add(g,n),a.control.each(function(b){if(b.extended(a.controlConstructor.widget_form)&&"nav_menu"===b.params.widget_id_base){var c,e,f;c=b.container.find("select"),e=c.find("option[value="+String(d.previous_term_id)+"]"),f=c.find("option[value="+String(d.term_id)+"]"),f.prop("selected",e.prop("selected")),e.remove()}}),i.callbacks.disable(),i.set(!1),i.preview(),j.preview(),i._dirty=!1,m.container.remove(),a.section.remove(f),q=0,a.each(function(a){/^nav_menu\[/.test(a.id)&&!1!==a()&&(q+=1)}),p=c("#available-widgets-list .widget-tpl:has( input.id_base[ value=nav_menu ] )"),p.find(".nav-menu-widget-form-controls:first").toggle(0!==q),p.find(".nav-menu-widget-no-menus-message:first").toggle(0===q),p.find("option[value="+String(d.previous_term_id)+"]").remove(),b.customize.control.each(function(a){/^nav_menu_locations\[/.test(a.id)&&a.container.find("option[value="+String(d.previous_term_id)+"]").remove()}),a.each(function(b){var c=a.state("saved").get();/^nav_menu_locations\[/.test(b.id)&&b.get()===d.previous_term_id&&(b.set(d.term_id),b._dirty=!1,a.state("saved").set(c),b.preview())}),m.expanded.get()&&n.expand()}else if("updated"===d.status){if(h="nav_menu["+String(d.term_id)+"]",!a.has(h))throw new Error("Expected setting to exist: "+h);k=a(h),_.isEqual(d.saved_value,k.get())||(o=a.state("saved").get(),k.set(d.saved_value),k._dirty=!1,a.state("saved").set(o))}}),_(d.nav_menu_item_updates).each(function(a){a.previous_post_id&&(f[a.previous_post_id]=a.post_id)}),_(d.nav_menu_item_updates).each(function(b){var c,d,g,h,i,j,k;if("inserted"===b.status){if(!b.previous_post_id)throw new Error("Expected previous_post_id");if(!b.post_id)throw new Error("Expected post_id");if(c="nav_menu_item["+String(b.previous_post_id)+"]",!a.has(c))throw new Error("Expected setting to exist: "+c);if(g=a(c),!a.control.has(c))throw new Error("Expected control to exist: "+c);if(j=a.control(c),i=g.get(),!i)throw new Error("Did not expect setting to be empty (deleted).");if(i=_.clone(i),i.menu_item_parent<0){if(!f[i.menu_item_parent])throw new Error("inserted ID for menu_item_parent not available");i.menu_item_parent=f[i.menu_item_parent]}e[i.nav_menu_term_id]&&(i.nav_menu_term_id=e[i.nav_menu_term_id]),d="nav_menu_item["+String(b.post_id)+"]",h=a.create(d,d,i,{type:"nav_menu_item",transport:"postMessage",previewer:a.previewer}),k=new a.controlConstructor.nav_menu_item(d,{params:{type:"nav_menu_item",content:'',menu_id:b.post_id,section:"nav_menu["+String(i.nav_menu_term_id)+"]",priority:j.priority.get(),active:!0,settings:{"default":d},menu_item_id:b.post_id},previewer:a.previewer}),j.container.remove(),a.control.remove(c),a.control.add(d,k),g.callbacks.disable(),g.set(!1),g.preview(),h.preview(),g._dirty=!1,k.container.toggleClass("menu-item-edit-inactive",j.container.hasClass("menu-item-edit-inactive"))}}),_.each(d.widget_nav_menu_updates,function(b,c){var d=a(c);d&&(d._value=b,d.preview())})},a.Menus.focusMenuItemControl=function(b){var c=a.Menus.getMenuItemControl(b);c&&c.focus()},a.Menus.getMenuControl=function(b){return a.control("nav_menu["+b+"]")},a.Menus.getMenuItemControl=function(b){return a.control(d(b))}}(wp.customize,wp,jQuery);
\ No newline at end of file
+!function(a,b,c){"use strict";function d(a){return"nav_menu_item["+a+"]"}function e(b){return b=b||"",b=c("
").text(b).html(),b=c.trim(b),b||a.Menus.data.l10n.unnamed}wpNavMenu.originalInit=wpNavMenu.init,wpNavMenu.options.menuItemDepthPerLevel=20,wpNavMenu.options.sortableItems="> .customize-control-nav_menu_item",wpNavMenu.options.targetTolerance=10,wpNavMenu.init=function(){this.jQueryExtensions()},a.Menus=a.Menus||{},a.Menus.data={itemTypes:[],l10n:{},settingTransport:"refresh",phpIntMax:0,defaultSettingValues:{nav_menu:{},nav_menu_item:{}},locationSlugMappedToName:{}},"undefined"!=typeof _wpCustomizeNavMenusSettings&&c.extend(a.Menus.data,_wpCustomizeNavMenusSettings),a.Menus.generatePlaceholderAutoIncrementId=function(){return-Math.ceil(a.Menus.data.phpIntMax*Math.random())},a.Menus.AvailableItemModel=Backbone.Model.extend(c.extend({id:null},a.Menus.data.defaultSettingValues.nav_menu_item)),a.Menus.AvailableItemCollection=Backbone.Collection.extend({model:a.Menus.AvailableItemModel,sort_key:"order",comparator:function(a){return-a.get(this.sort_key)},sortByField:function(a){this.sort_key=a,this.sort()}}),a.Menus.availableMenuItems=new a.Menus.AvailableItemCollection(a.Menus.data.availableMenuItems),a.Menus.AvailableMenuItemsPanelView=b.Backbone.View.extend({el:"#available-menu-items",events:{"input #menu-items-search":"debounceSearch","keyup #menu-items-search":"debounceSearch","focus .menu-item-tpl":"focus","click .menu-item-tpl":"_submit","click #custom-menu-item-submit":"_submitLink","keypress #custom-menu-item-name":"_submitLink",keydown:"keyboardAccessible"},selected:null,currentMenuControl:null,debounceSearch:null,$search:null,searchTerm:"",rendered:!1,pages:{},sectionContent:"",loading:!1,initialize:function(){var b=this;a.panel.has("nav_menus")&&(this.$search=c("#menu-items-search"),this.sectionContent=this.$el.find(".accordion-section-content"),this.debounceSearch=_.debounce(b.search,500),_.bindAll(this,"close"),c("#customize-controls, .customize-section-back").on("click keydown",function(a){var d=c(a.target).is(".item-delete, .item-delete *"),e=c(a.target).is(".add-new-menu-item, .add-new-menu-item *");!c("body").hasClass("adding-menu-items")||d||e||b.close()}),c(".clear-results").on("click keydown",function(a){("keydown"!==a.type||13===a.which||32===a.which)&&(a.preventDefault(),c("#menu-items-search").val("").focus(),a.target.value="",b.search(a))}),this.$el.on("input","#custom-menu-item-name.invalid, #custom-menu-item-url.invalid",function(){c(this).removeClass("invalid")}),a.panel("nav_menus").container.bind("expanded",function(){b.rendered||(b.initList(),b.rendered=!0)}),this.sectionContent.scroll(function(){var a=b.$el.find(".accordion-section.open .accordion-section-content").prop("scrollHeight"),d=b.$el.find(".accordion-section.open").height();if(!b.loading&&c(this).scrollTop()>.75*a-d){var e=c(this).data("type"),f=c(this).data("object");"search"===e?b.searchTerm&&b.doSearch(b.pages.search):b.loadItems(e,f)}}),a.previewer.bind("url",this.close))},search:function(a){var b=c("#available-menu-items-search"),d=c("#available-menu-items .accordion-section").not(b);a&&this.searchTerm!==a.target.value&&(""===a.target.value||b.hasClass("open")?""===a.target.value&&(b.removeClass("open"),d.show(),b.find(".clear-results").prop("tabIndex",-1).removeClass("is-visible")):(d.fadeOut(100),b.find(".accordion-section-content").slideDown("fast"),b.addClass("open"),b.find(".clear-results").prop("tabIndex",0).addClass("is-visible")),this.searchTerm=a.target.value,this.pages.search=1,this.doSearch(1))},doSearch:function(d){var e,f=this,g=c("#available-menu-items-search"),h=g.find(".accordion-section-content"),i=b.template("available-menu-item");if(f.currentRequest&&f.currentRequest.abort(),!(0>d)){if(d>1)g.addClass("loading-more"),h.attr("aria-busy","true"),b.a11y.speak(a.Menus.data.l10n.itemsLoadingMore);else if(""===f.searchTerm)return h.html(""),void b.a11y.speak("");g.addClass("loading"),f.loading=!0,e={"customize-menus-nonce":a.settings.nonce["customize-menus"],wp_customize:"on",search:f.searchTerm,page:d},f.currentRequest=b.ajax.post("search-available-menu-items-customizer",e),f.currentRequest.done(function(c){var e;1===d&&h.empty(),g.removeClass("loading loading-more"),h.attr("aria-busy","false"),g.addClass("open"),f.loading=!1,e=new a.Menus.AvailableItemCollection(c.items),f.collection.add(e.models),e.each(function(a){h.append(i(a.attributes))}),20>e.length?f.pages.search=-1:f.pages.search=f.pages.search+1,e&&d>1?b.a11y.speak(a.Menus.data.l10n.itemsFoundMore.replace("%d",e.length)):e&&1===d&&b.a11y.speak(a.Menus.data.l10n.itemsFound.replace("%d",e.length))}),f.currentRequest.fail(function(a){a.message&&(h.empty().append(c('
').text(a.message)),b.a11y.speak(a.message)),f.pages.search=-1}),f.currentRequest.always(function(){g.removeClass("loading loading-more"),h.attr("aria-busy","false"),f.loading=!1,f.currentRequest=null})}},initList:function(){var b=this;_.each(a.Menus.data.itemTypes,function(a){b.pages[a.type+":"+a.object]=0,b.loadItems(a.type,a.object)})},loadItems:function(d,e){var f,g,h,i,j=this;h=b.template("available-menu-item"),-1!==j.pages[d+":"+e]&&(i=c("#available-menu-items-"+d+"-"+e),i.find(".accordion-section-title").addClass("loading"),j.loading=!0,f={"customize-menus-nonce":a.settings.nonce["customize-menus"],wp_customize:"on",type:d,object:e,page:j.pages[d+":"+e]},g=b.ajax.post("load-available-menu-items-customizer",f),g.done(function(b){var c,f;return c=b.items,0===c.length?(0===j.pages[d+":"+e]&&i.addClass("cannot-expand").removeClass("loading").find(".accordion-section-title > button").prop("tabIndex",-1),void(j.pages[d+":"+e]=-1)):(c=new a.Menus.AvailableItemCollection(c),j.collection.add(c.models),f=i.find(".accordion-section-content"),c.each(function(a){f.append(h(a.attributes))}),void(j.pages[d+":"+e]+=1))}),g.fail(function(a){"undefined"!=typeof console&&console.error&&console.error(a)}),g.always(function(){i.find(".accordion-section-title").removeClass("loading"),j.loading=!1}))},itemSectionHeight:function(){var a,b,c,d;b=window.innerHeight,a=this.$el.find(".accordion-section:not( #available-menu-items-search ) .accordion-section-content"),c=46*(2+a.length)-13,d=b-c,d>120&&290>d&&a.css("max-height",d)},select:function(a){this.selected=c(a),this.selected.siblings(".menu-item-tpl").removeClass("selected"),this.selected.addClass("selected")},focus:function(a){this.select(c(a.currentTarget))},_submit:function(a){("keypress"!==a.type||13===a.which||32===a.which)&&this.submit(c(a.currentTarget))},submit:function(a){var b,d;a||(a=this.selected),a&&this.currentMenuControl&&(this.select(a),b=c(this.selected).data("menu-item-id"),d=this.collection.findWhere({id:b}),d&&(this.currentMenuControl.addItemToMenu(d.attributes),c(a).find(".menu-item-handle").addClass("item-added")))},_submitLink:function(a){("keypress"!==a.type||13===a.which)&&this.submitLink()},submitLink:function(){var b,d=c("#custom-menu-item-name"),e=c("#custom-menu-item-url");if(this.currentMenuControl){if(""===d.val())return void d.addClass("invalid");if(""===e.val()||"http://"===e.val())return void e.addClass("invalid");b={title:d.val(),url:e.val(),type:"custom",type_label:a.Menus.data.l10n.custom_label,object:""},this.currentMenuControl.addItemToMenu(b),e.val("http://"),d.val("")}},open:function(a){this.currentMenuControl=a,this.itemSectionHeight(),c("body").addClass("adding-menu-items"),_(this.currentMenuControl.getMenuItemControls()).each(function(a){a.collapseForm()}),this.$el.find(".selected").removeClass("selected"),this.$search.focus()},close:function(a){a=a||{},a.returnFocus&&this.currentMenuControl&&this.currentMenuControl.container.find(".add-new-menu-item").focus(),this.currentMenuControl=null,this.selected=null,c("body").removeClass("adding-menu-items"),c("#available-menu-items .menu-item-handle.item-added").removeClass("item-added"),this.$search.val("")},keyboardAccessible:function(a){var b=13===a.which,d=27===a.which,e=9===a.which&&a.shiftKey,f=c(a.target).is(this.$search);(!b||this.$search.val())&&(f&&e?(this.currentMenuControl.container.find(".add-new-menu-item").focus(),a.preventDefault()):d&&this.close({returnFocus:!0}))}}),a.Menus.MenusPanel=a.Panel.extend({attachEvents:function(){a.Panel.prototype.attachEvents.call(this);var b=this,d=b.container.find(".panel-meta"),e=d.find(".customize-help-toggle"),f=d.find(".customize-panel-description"),g=c("#screen-options-wrap"),h=d.find(".customize-screen-options-toggle");h.on("click keydown",function(b){return a.utils.isKeydownButNotEnterEvent(b)?void 0:(b.preventDefault(),f.not(":hidden")&&(f.slideUp("fast"),e.attr("aria-expanded","false")),"true"===h.attr("aria-expanded")?(h.attr("aria-expanded","false"),d.removeClass("open"),d.removeClass("active-menu-screen-options"),g.slideUp("fast")):(h.attr("aria-expanded","true"),d.addClass("open"),d.addClass("active-menu-screen-options"),g.slideDown("fast")),!1)}),e.on("click keydown",function(b){a.utils.isKeydownButNotEnterEvent(b)||(b.preventDefault(),"true"===h.attr("aria-expanded")&&(h.attr("aria-expanded","false"),e.attr("aria-expanded","true"),d.addClass("open"),d.removeClass("active-menu-screen-options"),g.slideUp("fast"),f.slideDown("fast")))})},ready:function(){var a=this;this.container.find(".hide-column-tog").click(function(){var b=c(this),d=b.val();b.prop("checked")?a.checked(d):a.unchecked(d),a.saveManageColumnsState()}),this.container.find(".hide-column-tog").each(function(){var b=c(this),d=b.val();b.prop("checked")?a.checked(d):a.unchecked(d)})},saveManageColumnsState:function(){var a=this.hidden();c.post(b.ajax.settings.url,{action:"hidden-columns",hidden:a,screenoptionnonce:c("#screenoptionnonce").val(),page:"nav-menus"})},checked:function(a){this.container.addClass("field-"+a+"-active")},unchecked:function(a){this.container.removeClass("field-"+a+"-active")},hidden:function(){this.hidden=function(){return c(".hide-column-tog").not(":checked").map(function(){var a=this.id;return a.substring(a,a.length-5)}).get().join(",")}}}),a.Menus.MenuSection=a.Section.extend({initialize:function(b,d){var e=this;a.Section.prototype.initialize.call(e,b,d),e.deferred.initSortables=c.Deferred()},ready:function(){var b=this;if("undefined"==typeof b.params.menu_id)throw new Error("params.menu_id was not defined");b.active.validate=function(){return a.has(b.id)?!!a(b.id).get():!1},b.populateControls(),b.navMenuLocationSettings={},b.assignedLocations=new a.Value([]),a.each(function(a,c){var d=c.match(/^nav_menu_locations\[(.+?)]/);d&&(b.navMenuLocationSettings[d[1]]=a,a.bind(function(){b.refreshAssignedLocations()}))}),b.assignedLocations.bind(function(a){b.updateAssignedLocationsInSectionTitle(a)}),b.refreshAssignedLocations(),a.bind("pane-contents-reflowed",function(){b.container.parent().length&&(b.container.find(".menu-item .menu-item-reorder-nav button").attr({tabindex:"0","aria-hidden":"false"}),b.container.find(".menu-item.move-up-disabled .menus-move-up").attr({tabindex:"-1","aria-hidden":"true"}),b.container.find(".menu-item.move-down-disabled .menus-move-down").attr({tabindex:"-1","aria-hidden":"true"}),b.container.find(".menu-item.move-left-disabled .menus-move-left").attr({tabindex:"-1","aria-hidden":"true"}),b.container.find(".menu-item.move-right-disabled .menus-move-right").attr({tabindex:"-1","aria-hidden":"true"}))})},populateControls:function(){var b,c,d,e,f,g=this;b=g.id+"[name]",e=a.control(b),e||(e=new a.controlConstructor.nav_menu_name(b,{params:{type:"nav_menu_name",content:'',label:a.Menus.data.l10n.menuNameLabel,active:!0,section:g.id,priority:0,settings:{"default":g.id}}}),a.control.add(e.id,e),e.active.set(!0)),d=a.control(g.id),d||(d=new a.controlConstructor.nav_menu(g.id,{params:{type:"nav_menu",content:'',section:g.id,priority:998,active:!0,settings:{"default":g.id},menu_id:g.params.menu_id}}),a.control.add(d.id,d),d.active.set(!0)),c=g.id+"[auto_add]",f=a.control(c),f||(f=new a.controlConstructor.nav_menu_auto_add(c,{params:{type:"nav_menu_auto_add",content:'',label:"",active:!0,section:g.id,priority:999,settings:{"default":g.id}}}),a.control.add(f.id,f),f.active.set(!0))},refreshAssignedLocations:function(){var a=this,b=a.params.menu_id,c=[];_.each(a.navMenuLocationSettings,function(a,d){a()===b&&c.push(d)}),a.assignedLocations.set(c)},updateAssignedLocationsInSectionTitle:function(b){var d,e=this;d=e.container.find(".accordion-section-title:first"),d.find(".menu-in-location").remove(),_.each(b,function(b){var e,f;e=c(''),f=a.Menus.data.locationSlugMappedToName[b],e.text(a.Menus.data.l10n.menuLocation.replace("%s",f)),d.append(e)}),e.container.toggleClass("assigned-to-menu-location",0!==b.length)},onChangeExpanded:function(b,d){var e=this;b&&(wpNavMenu.menuList=e.container.find(".accordion-section-content:first"),wpNavMenu.targetList=wpNavMenu.menuList,c("#menu-to-edit").removeAttr("id"),wpNavMenu.menuList.attr("id","menu-to-edit").addClass("menu"),_.each(a.section(e.id).controls(),function(a){"nav_menu_item"===a.params.type&&a.actuallyEmbed()}),"resolved"!==e.deferred.initSortables.state()&&(wpNavMenu.initSortables(),e.deferred.initSortables.resolve(wpNavMenu.menuList),a.control("nav_menu["+String(e.params.menu_id)+"]").reflowMenuItems())),a.Section.prototype.onChangeExpanded.call(e,b,d)}}),a.Menus.NewMenuSection=a.Section.extend({attachEvents:function(){var a=this;this.container.on("click",".add-menu-toggle",function(){a.expanded()?a.collapse():a.expand()})},onChangeExpanded:function(a){var b=this,c=b.container.find(".add-menu-toggle"),d=b.container.find(".new-menu-section-content"),e=b.container.closest(".wp-full-overlay-sidebar-content");a?(c.addClass("open"),c.attr("aria-expanded","true"),d.slideDown("fast",function(){e.scrollTop(e.height())})):(c.removeClass("open"),c.attr("aria-expanded","false"),d.slideUp("fast"),d.find(".menu-name-field").removeClass("invalid"))}}),a.Menus.MenuLocationControl=a.Control.extend({initialize:function(b,c){var d=this,e=b.match(/^nav_menu_locations\[(.+?)]/);d.themeLocation=e[1],a.Control.prototype.initialize.call(d,b,c)},ready:function(){var b=this,c=/^nav_menu\[(-?\d+)]/;b.setting.validate=function(a){return parseInt(a,10)},a.bind("add",function(a){var d,f,g=a.id.match(c);g&&!1!==a()&&(f=g[1],d=new Option(e(a().name),f),b.container.find("select").append(d))}),a.bind("remove",function(a){var d,e=a.id.match(c);e&&(d=parseInt(e[1],10),b.setting()===d&&b.setting.set(""),b.container.find("option[value="+d+"]").remove())}),a.bind("change",function(a){var d,f=a.id.match(c);f&&(d=parseInt(f[1],10),!1===a()?(b.setting()===d&&b.setting.set(""),b.container.find("option[value="+d+"]").remove()):b.container.find("option[value="+d+"]").text(e(a().name)))})}}),a.Menus.MenuItemControl=a.Control.extend({initialize:function(b,c){var d=this;a.Control.prototype.initialize.call(d,b,c),d.active.validate=function(){var b,c=a.section(d.section());return b=c?c.active():!1}},embed:function(){var b,c=this,d=c.section();d&&(b=a.section(d),(b&&b.expanded()||a.settings.autofocus.control===c.id)&&c.actuallyEmbed())},actuallyEmbed:function(){var a=this;"resolved"!==a.deferred.embedded.state()&&(a.renderContent(),a.deferred.embedded.resolve())},ready:function(){if("undefined"==typeof this.params.menu_item_id)throw new Error("params.menu_item_id was not defined");this._setupControlToggle(),this._setupReorderUI(),this._setupUpdateUI(),this._setupRemoveUI(),this._setupLinksUI(),this._setupTitleUI()},_setupControlToggle:function(){var a=this;this.container.find(".menu-item-handle").on("click",function(b){b.preventDefault(),b.stopPropagation();var c=a.getMenuControl();c.isReordering||c.isSorting||a.toggleForm()})},_setupReorderUI:function(){var a,d,e=this;a=b.template("menu-item-reorder-nav"),e.container.find(".item-controls").after(a),d=e.container.find(".menu-item-reorder-nav"),d.find(".menus-move-up, .menus-move-down, .menus-move-left, .menus-move-right").on("click",function(){var a=c(this);a.focus();var b=a.is(".menus-move-up"),d=a.is(".menus-move-down"),f=a.is(".menus-move-left"),g=a.is(".menus-move-right");b?e.moveUp():d?e.moveDown():f?e.moveLeft():g&&e.moveRight(),a.focus()})},_setupUpdateUI:function(){var b=this,c=b.setting();b.elements={},b.elements.url=new a.Element(b.container.find(".edit-menu-item-url")),b.elements.title=new a.Element(b.container.find(".edit-menu-item-title")),b.elements.attr_title=new a.Element(b.container.find(".edit-menu-item-attr-title")),b.elements.target=new a.Element(b.container.find(".edit-menu-item-target")),b.elements.classes=new a.Element(b.container.find(".edit-menu-item-classes")),b.elements.xfn=new a.Element(b.container.find(".edit-menu-item-xfn")),b.elements.description=new a.Element(b.container.find(".edit-menu-item-description")),_.each(b.elements,function(a,d){a.bind(function(c){a.element.is("input[type=checkbox]")&&(c=c?a.element.val():"");var e=b.setting();e&&e[d]!==c&&(e=_.clone(e),e[d]=c,b.setting.set(e))}),c&&("classes"!==d&&"xfn"!==d||!_.isArray(c[d])?a.set(c[d]):a.set(c[d].join(" ")))}),b.setting.bind(function(c,d){var e,f=b.params.menu_item_id,g=[],h=[];!1===c?(e=a.control("nav_menu["+String(d.nav_menu_term_id)+"]"),b.container.remove(),_.each(e.getMenuItemControls(),function(a){d.menu_item_parent===a.setting().menu_item_parent&&a.setting().position>d.position?g.push(a):a.setting().menu_item_parent===f&&h.push(a)}),_.each(g,function(a){var b=_.clone(a.setting());b.position+=h.length,a.setting.set(b)}),_.each(h,function(a,b){var c=_.clone(a.setting());c.position=d.position+b,c.menu_item_parent=d.menu_item_parent,a.setting.set(c)}),e.debouncedReflowMenuItems()):(_.each(c,function(a,d){b.elements[d]&&b.elements[d].set(c[d])}),b.container.find(".menu-item-data-parent-id").val(c.menu_item_parent),(c.position!==d.position||c.menu_item_parent!==d.menu_item_parent)&&b.getMenuControl().debouncedReflowMenuItems())})},_setupRemoveUI:function(){var d,e=this;d=e.container.find(".item-delete"),d.on("click",function(){var d,f,g,h=!0;c("body").hasClass("adding-menu-items")||(h=!1),f=e.container.nextAll(".customize-control-nav_menu_item:visible").first(),g=e.container.prevAll(".customize-control-nav_menu_item:visible").first(),d=f.length?f.find(!1===h?".item-edit":".item-delete").first():g.length?g.find(!1===h?".item-edit":".item-delete").first():e.container.nextAll(".customize-control-nav_menu").find(".add-new-menu-item").first(),e.container.slideUp(function(){e.setting.set(!1),b.a11y.speak(a.Menus.data.l10n.itemDeleted),d.focus()})})},_setupLinksUI:function(){var b;b=this.container.find("a.original-link"),b.on("click",function(b){b.preventDefault(),a.previewer.previewUrl(b.target.toString())})},_setupTitleUI:function(){var b=this;b.setting.bind(function(c){if(c){var d=b.container.find(".menu-item-title"),e=c.title||a.Menus.data.l10n.untitled;c._invalid&&(e=a.Menus.data.l10n.invalidTitleTpl.replace("%s",e)),c.title?d.text(e).removeClass("no-title"):d.text(e).addClass("no-title")}})},getDepth:function(){var b=this,c=b.setting(),d=0;if(!c)return 0;for(;c&&c.menu_item_parent&&(d+=1,b=a.control("nav_menu_item["+c.menu_item_parent+"]"));)c=b.setting();return d},renderContent:function(){var b,c=this,d=c.setting();c.params.title=d.title||"",c.params.depth=c.getDepth(),c.container.data("item-depth",c.params.depth),b=["menu-item","menu-item-depth-"+String(c.params.depth),"menu-item-"+d.object,"menu-item-edit-inactive"],d._invalid?(b.push("menu-item-invalid"),c.params.title=a.Menus.data.l10n.invalidTitleTpl.replace("%s",c.params.title)):"draft"===d.status&&(b.push("pending"),c.params.title=a.Menus.data.pendingTitleTpl.replace("%s",c.params.title)),c.params.el_classes=b.join(" "),c.params.item_type_label=d.type_label,c.params.item_type=d.type,c.params.url=d.url,c.params.target=d.target,c.params.attr_title=d.attr_title,c.params.classes=_.isArray(d.classes)?d.classes.join(" "):d.classes,c.params.attr_title=d.attr_title,c.params.xfn=d.xfn,c.params.description=d.description,c.params.parent=d.menu_item_parent,c.params.original_title=d.original_title||"",c.container.addClass(c.params.el_classes),a.Control.prototype.renderContent.call(c)},getMenuControl:function(){var b=this,c=b.setting();return c&&c.nav_menu_term_id?a.control("nav_menu["+c.nav_menu_term_id+"]"):null},expandControlSection:function(){var a=this.container.closest(".accordion-section");a.hasClass("open")||a.find(".accordion-section-title:first").trigger("click")},expandForm:function(a){this.toggleForm(!0,a)},collapseForm:function(a){this.toggleForm(!1,a)},toggleForm:function(b,c){var d,e,f,g=this;return d=this.container,e=d.find(".menu-item-settings:first"),"undefined"==typeof b&&(b=!e.is(":visible")),e.is(":visible")===b?void(c&&c.completeCallback&&c.completeCallback()):void(b?(a.control.each(function(a){g.params.type===a.params.type&&g!==a&&a.collapseForm()}),f=function(){d.removeClass("menu-item-edit-inactive").addClass("menu-item-edit-active"),g.container.trigger("expanded"),c&&c.completeCallback&&c.completeCallback()},d.find(".item-edit").attr("aria-expanded","true"),e.slideDown("fast",f),g.container.trigger("expand")):(f=function(){d.addClass("menu-item-edit-inactive").removeClass("menu-item-edit-active"),g.container.trigger("collapsed"),c&&c.completeCallback&&c.completeCallback()},g.container.trigger("collapse"),d.find(".item-edit").attr("aria-expanded","false"),e.slideUp("fast",f)))},focus:function(a){a=a||{};var b=this,c=a.completeCallback;b.expandControlSection(),a.completeCallback=function(){var a;a=b.container.find(".menu-item-settings").find("input, select, textarea, button, object, a[href], [tabindex]").filter(":visible"),a.first().focus(),c&&c()},b.expandForm(a)},moveUp:function(){this._changePosition(-1),b.a11y.speak(a.Menus.data.l10n.movedUp)},moveDown:function(){this._changePosition(1),b.a11y.speak(a.Menus.data.l10n.movedDown)},moveLeft:function(){this._changeDepth(-1),b.a11y.speak(a.Menus.data.l10n.movedLeft)},moveRight:function(){this._changeDepth(1),b.a11y.speak(a.Menus.data.l10n.movedRight)},_changePosition:function(a){var b,d,e=this,f=_.clone(e.setting()),g=[];if(1!==a&&-1!==a)throw new Error("Offset changes by 1 are only supported.");if(e.setting()){if(_(e.getMenuControl().getMenuItemControls()).each(function(a){a.setting().menu_item_parent===f.menu_item_parent&&g.push(a.setting)}),g.sort(function(a,b){return a().position-b().position}),d=_.indexOf(g,e.setting),-1===d)throw new Error("Expected setting to be among siblings.");0===d&&0>a||d===g.length-1&&a>0||(b=g[d+a],b&&b.set(c.extend(_.clone(b()),{position:f.position})),f.position+=a,e.setting.set(f))}},_changeDepth:function(b){if(1!==b&&-1!==b)throw new Error("Offset changes by 1 are only supported.");var d,e,f,g=this,h=_.clone(g.setting()),i=[];if(_(g.getMenuControl().getMenuItemControls()).each(function(a){a.setting().menu_item_parent===h.menu_item_parent&&i.push(a)}),i.sort(function(a,b){return a.setting().position-b.setting().position}),d=_.indexOf(i,g),-1===d)throw new Error("Expected control to be among siblings.");if(-1===b){if(!h.menu_item_parent)return;f=a.control("nav_menu_item["+h.menu_item_parent+"]"),_(i).chain().slice(d).each(function(a,b){a.setting.set(c.extend({},a.setting(),{menu_item_parent:g.params.menu_item_id,position:b}))}),_(g.getMenuControl().getMenuItemControls()).each(function(a){var b,d;d=a.setting().menu_item_parent===f.setting().menu_item_parent&&a.setting().position>f.setting().position,d&&(b=_.clone(a.setting()),a.setting.set(c.extend(b,{position:b.position+1})))}),h.position=f.setting().position+1,h.menu_item_parent=f.setting().menu_item_parent,g.setting.set(h)}else if(1===b){if(0===d)return;e=i[d-1],h.menu_item_parent=e.params.menu_item_id,h.position=0,_(g.getMenuControl().getMenuItemControls()).each(function(a){a.setting().menu_item_parent===h.menu_item_parent&&(h.position=Math.max(h.position,a.setting().position))}),h.position+=1,g.setting.set(h)}}}),a.Menus.MenuNameControl=a.Control.extend({ready:function(){var b=this,c=b.setting();b.active.validate=function(){var c,d=a.section(b.section());return c=d?d.active():!1},b.nameElement=new a.Element(b.container.find(".menu-name-field")),b.nameElement.bind(function(a){var c=b.setting();c&&c.name!==a&&(c=_.clone(c),c.name=a,b.setting.set(c))}),c&&b.nameElement.set(c.name),b.setting.bind(function(a){a&&b.nameElement.set(a.name)})}}),a.Menus.MenuAutoAddControl=a.Control.extend({ready:function(){var b=this,c=b.setting();b.active.validate=function(){var c,d=a.section(b.section());return c=d?d.active():!1},b.autoAddElement=new a.Element(b.container.find("input[type=checkbox].auto_add")),b.autoAddElement.bind(function(a){var c=b.setting();c&&c.name!==a&&(c=_.clone(c),c.auto_add=a,b.setting.set(c))}),c&&b.autoAddElement.set(c.auto_add),b.setting.bind(function(a){a&&b.autoAddElement.set(a.auto_add)})}}),a.Menus.MenuControl=a.Control.extend({ready:function(){var b,d,f,g=this,h=g.params.menu_id,i=g.setting();if("undefined"==typeof this.params.menu_id)throw new Error("params.menu_id was not defined");g.active.validate=function(){var b,c=a.section(g.section());return b=c?c.active():!1},g.$controlSection=g.container.closest(".control-section"),g.$sectionContent=g.container.closest(".accordion-section-content"),this._setupModel(),a.section(g.section(),function(a){a.deferred.initSortables.done(function(a){g._setupSortable(a)})}),this._setupAddition(),this._setupLocations(),this._setupTitle(),i&&(b=e(i.name),a.control.each(function(c){c.extended(a.controlConstructor.widget_form)&&"nav_menu"===c.params.widget_id_base&&(c.container.find(".nav-menu-widget-form-controls:first").show(),c.container.find(".nav-menu-widget-no-menus-message:first").hide(),f=c.container.find("select"),0===f.find("option[value="+String(h)+"]").length&&f.append(new Option(b,h)))}),d=c("#available-widgets-list .widget-tpl:has( input.id_base[ value=nav_menu ] )"),d.find(".nav-menu-widget-form-controls:first").show(),d.find(".nav-menu-widget-no-menus-message:first").hide(),f=d.find(".widget-inside select:first"),0===f.find("option[value="+String(h)+"]").length&&f.append(new Option(b,h)))},_setupModel:function(){var b=this,c=b.params.menu_id;b.setting.bind(function(d){var f;!1===d?b._handleDeletion():(f=e(d.name),a.control.each(function(b){if(b.extended(a.controlConstructor.widget_form)&&"nav_menu"===b.params.widget_id_base){var d=b.container.find("select");d.find("option[value="+String(c)+"]").text(f)}}))}),b.container.find(".menu-delete").on("click",function(a){a.stopPropagation(),a.preventDefault(),b.setting.set(!1)})},_setupSortable:function(b){var c=this;if(!b.is(c.$sectionContent))throw new Error("Unexpected menuList.");b.on("sortstart",function(){c.isSorting=!0}),b.on("sortstop",function(){setTimeout(function(){var b=c.$sectionContent.sortable("toArray"),d=[],e=0,f=10;c.isSorting=!1,c.$sectionContent.scrollLeft(0),_.each(b,function(b){var c,e,f;f=b.match(/^customize-control-nav_menu_item-(-?\d+)$/,""),f&&(c=parseInt(f[1],10),e=a.control("nav_menu_item["+String(c)+"]"),e&&d.push(e))}),_.each(d,function(a){if(!1!==a.setting()){var b=_.clone(a.setting());e+=1,f+=1,b.position=e,a.priority(f),b.menu_item_parent=parseInt(a.container.find(".menu-item-data-parent-id").val(),10),b.menu_item_parent||(b.menu_item_parent=0),a.setting.set(b)}})})}),c.isReordering=!1,this.container.find(".reorder-toggle").on("click",function(){c.toggleReordering(!c.isReordering)})},_setupAddition:function(){var b=this;this.container.find(".add-new-menu-item").on("click",function(d){b.$sectionContent.hasClass("reordering")||(c("body").hasClass("adding-menu-items")?(c(this).attr("aria-expanded","false"),a.Menus.availableMenuItemsPanel.close(),d.stopPropagation()):(c(this).attr("aria-expanded","true"),a.Menus.availableMenuItemsPanel.open(b)))})},_handleDeletion:function(){var d,e,f,g=this,h=g.params.menu_id,i=0;d=a.section(g.section()),e=function(){d.container.remove(),a.section.remove(d.id)},d&&d.expanded()?d.collapse({completeCallback:function(){e(),b.a11y.speak(a.Menus.data.l10n.menuDeleted),a.panel("nav_menus").focus()}}):e(),a.each(function(a){/^nav_menu\[/.test(a.id)&&!1!==a()&&(i+=1)}),a.control.each(function(b){if(b.extended(a.controlConstructor.widget_form)&&"nav_menu"===b.params.widget_id_base){var c=b.container.find("select");c.val()===String(h)&&c.prop("selectedIndex",0).trigger("change"),b.container.find(".nav-menu-widget-form-controls:first").toggle(0!==i),b.container.find(".nav-menu-widget-no-menus-message:first").toggle(0===i),b.container.find("option[value="+String(h)+"]").remove()}}),f=c("#available-widgets-list .widget-tpl:has( input.id_base[ value=nav_menu ] )"),f.find(".nav-menu-widget-form-controls:first").toggle(0!==i),f.find(".nav-menu-widget-no-menus-message:first").toggle(0===i),f.find("option[value="+String(h)+"]").remove()},_setupLocations:function(){var b=this;b.container.find(".assigned-menu-location").each(function(){var d,f,g=c(this),h=g.find("input[type=checkbox]"),i=a("nav_menu_locations["+h.data("location-id")+"]");f=function(b){var c=a("nav_menu["+String(b)+"]");b&&c&&c()?g.find(".theme-location-set").show().find("span").text(e(c().name)):g.find(".theme-location-set").hide()},d=new a.Element(h),d.set(i.get()===b.params.menu_id),h.on("change",function(){i.set(this.checked?b.params.menu_id:0)}),i.bind(function(a){d.set(a===b.params.menu_id),f(a)}),f(i.get())})},_setupTitle:function(){var b=this;b.setting.bind(function(d){if(d){var f=b.container.closest(".accordion-section"),g=b.params.menu_id,h=f.find(".accordion-section-title"),i=f.find(".customize-section-title h3"),j=f.find(".menu-in-location"),k=i.find(".customize-action"),l=e(d.name);h.text(l),j.length&&j.appendTo(h),i.text(l),k.length&&k.prependTo(i),a.control.each(function(a){/^nav_menu_locations\[/.test(a.id)&&a.container.find("option[value="+g+"]").text(l)}),f.find(".customize-control-checkbox input").each(function(){c(this).prop("checked")&&c(".current-menu-location-name-"+c(this).data("location-id")).text(l)})}})},toggleReordering:function(c){var d=this.container.find(".add-new-menu-item"),e=this.container.find(".reorder-toggle"),f=this.$sectionContent.find(".item-title");c=Boolean(c),c!==this.$sectionContent.hasClass("reordering")&&(this.isReordering=c,this.$sectionContent.toggleClass("reordering",c),this.$sectionContent.sortable(this.isReordering?"disable":"enable"),this.isReordering?(d.attr({tabindex:"-1","aria-hidden":"true"}),e.attr("aria-label",a.Menus.data.l10n.reorderLabelOff),b.a11y.speak(a.Menus.data.l10n.reorderModeOn),f.attr("aria-hidden","false")):(d.removeAttr("tabindex aria-hidden"),e.attr("aria-label",a.Menus.data.l10n.reorderLabelOn),b.a11y.speak(a.Menus.data.l10n.reorderModeOff),f.attr("aria-hidden","true")),c&&_(this.getMenuItemControls()).each(function(a){a.collapseForm()}))},getMenuItemControls:function(){var b=this,c=[],d=b.params.menu_id;return a.control.each(function(a){"nav_menu_item"===a.params.type&&a.setting()&&d===a.setting().nav_menu_term_id&&c.push(a)}),c},reflowMenuItems:function(){var a,b=this,c=b.getMenuItemControls();a=function(b){var c=[],d=b.currentParent;_.each(b.menuItemControls,function(a){d===a.setting().menu_item_parent&&c.push(a)}),c.sort(function(a,b){return a.setting().position-b.setting().position}),_.each(c,function(c){b.currentAbsolutePosition+=1,c.priority.set(b.currentAbsolutePosition),c.container.hasClass("menu-item-depth-"+String(b.currentDepth))||(_.each(c.container.prop("className").match(/menu-item-depth-\d+/g),function(a){c.container.removeClass(a)}),c.container.addClass("menu-item-depth-"+String(b.currentDepth))),c.container.data("item-depth",b.currentDepth),b.currentDepth+=1,
+b.currentParent=c.params.menu_item_id,a(b),b.currentDepth-=1,b.currentParent=d}),c.length&&(_(c).each(function(a){a.container.removeClass("move-up-disabled move-down-disabled move-left-disabled move-right-disabled"),0===b.currentDepth?a.container.addClass("move-left-disabled"):10===b.currentDepth&&a.container.addClass("move-right-disabled")}),c[0].container.addClass("move-up-disabled").addClass("move-right-disabled").toggleClass("move-down-disabled",1===c.length),c[c.length-1].container.addClass("move-down-disabled").toggleClass("move-up-disabled",1===c.length))},a({menuItemControls:c,currentParent:0,currentDepth:0,currentAbsolutePosition:0}),b.container.find(".reorder-toggle").toggle(c.length>1)},debouncedReflowMenuItems:_.debounce(function(){this.reflowMenuItems.apply(this,arguments)},0),addItemToMenu:function(d){var e,f,g,h,i,j=this,k=0,l=10;return _.each(j.getMenuItemControls(),function(a){!1!==a.setting()&&(l=Math.max(l,a.priority()),0===a.setting().menu_item_parent&&(k=Math.max(k,a.setting().position)))}),k+=1,l+=1,d=c.extend({},a.Menus.data.defaultSettingValues.nav_menu_item,d,{nav_menu_term_id:j.params.menu_id,original_title:d.title,position:k}),delete d.id,i=a.Menus.generatePlaceholderAutoIncrementId(),e="nav_menu_item["+String(i)+"]",f={type:"nav_menu_item",transport:a.Menus.data.settingTransport,previewer:a.previewer},g=a.create(e,e,{},f),g.set(d),h=new a.controlConstructor.nav_menu_item(e,{params:{type:"nav_menu_item",content:'',section:j.id,priority:l,active:!0,settings:{"default":e},menu_item_id:i},previewer:a.previewer}),a.control.add(e,h),g.preview(),j.debouncedReflowMenuItems(),b.a11y.speak(a.Menus.data.l10n.itemAdded),h}}),a.Menus.NewMenuControl=a.Control.extend({ready:function(){this._bindHandlers()},_bindHandlers:function(){var a=this,b=c("#customize-control-new_menu_name input"),d=c("#create-new-menu-submit");b.on("keydown",function(b){13===b.which&&a.submit()}),d.on("click",function(b){a.submit(),b.stopPropagation(),b.preventDefault()})},submit:function(){var d,f,g=this,h=g.container.closest(".accordion-section-new-menu"),i=h.find(".menu-name-field").first(),j=i.val(),k=a.Menus.generatePlaceholderAutoIncrementId();return j?(f="nav_menu["+String(k)+"]",a.create(f,f,{},{type:"nav_menu",transport:a.Menus.data.settingTransport,previewer:a.previewer}),a(f).set(c.extend({},a.Menus.data.defaultSettingValues.nav_menu,{name:j})),d=new a.Menus.MenuSection(f,{params:{id:f,panel:"nav_menus",title:e(j),customizeAction:a.Menus.data.l10n.customizingMenus,type:"nav_menu",priority:10,menu_id:k}}),a.section.add(f,d),i.val(""),i.removeClass("invalid"),b.a11y.speak(a.Menus.data.l10n.menuAdded),a.section(f).focus(),void c("#menu-to-edit").css("margin-top",0)):(i.addClass("invalid"),void i.focus())}}),c.extend(a.controlConstructor,{nav_menu_location:a.Menus.MenuLocationControl,nav_menu_item:a.Menus.MenuItemControl,nav_menu:a.Menus.MenuControl,nav_menu_name:a.Menus.MenuNameControl,nav_menu_auto_add:a.Menus.MenuAutoAddControl,new_menu:a.Menus.NewMenuControl}),c.extend(a.panelConstructor,{nav_menus:a.Menus.MenusPanel}),c.extend(a.sectionConstructor,{nav_menu:a.Menus.MenuSection,new_menu:a.Menus.NewMenuSection}),a.bind("ready",function(){a.Menus.availableMenuItemsPanel=new a.Menus.AvailableMenuItemsPanelView({collection:a.Menus.availableMenuItems}),a.bind("saved",function(b){(b.nav_menu_updates||b.nav_menu_item_updates)&&a.Menus.applySavedData(b)}),a.previewer.bind("focus-nav-menu-item-control",a.Menus.focusMenuItemControl)}),a.Menus.applySavedData=function(d){var e={},f={};_(d.nav_menu_updates).each(function(d){var f,g,h,i,j,k,l,m,n,o,p,q;if("inserted"===d.status){if(!d.previous_term_id)throw new Error("Expected previous_term_id");if(!d.term_id)throw new Error("Expected term_id");if(f="nav_menu["+String(d.previous_term_id)+"]",!a.has(f))throw new Error("Expected setting to exist: "+f);if(i=a(f),!a.section.has(f))throw new Error("Expected control to exist: "+f);if(m=a.section(f),l=i.get(),!l)throw new Error("Did not expect setting to be empty (deleted).");l=c.extend(_.clone(l),d.saved_value),e[d.previous_term_id]=d.term_id,g="nav_menu["+String(d.term_id)+"]",j=a.create(g,g,l,{type:"nav_menu",transport:a.Menus.data.settingTransport,previewer:a.previewer}),m.expanded()&&m.collapse(),n=new a.Menus.MenuSection(g,{params:{id:g,panel:"nav_menus",title:l.name,customizeAction:a.Menus.data.l10n.customizingMenus,type:"nav_menu",priority:m.priority.get(),active:!0,menu_id:d.term_id}}),a.section.add(g,n),a.control.each(function(b){if(b.extended(a.controlConstructor.widget_form)&&"nav_menu"===b.params.widget_id_base){var c,e,f;c=b.container.find("select"),e=c.find("option[value="+String(d.previous_term_id)+"]"),f=c.find("option[value="+String(d.term_id)+"]"),f.prop("selected",e.prop("selected")),e.remove()}}),i.callbacks.disable(),i.set(!1),i.preview(),j.preview(),i._dirty=!1,m.container.remove(),a.section.remove(f),q=0,a.each(function(a){/^nav_menu\[/.test(a.id)&&!1!==a()&&(q+=1)}),p=c("#available-widgets-list .widget-tpl:has( input.id_base[ value=nav_menu ] )"),p.find(".nav-menu-widget-form-controls:first").toggle(0!==q),p.find(".nav-menu-widget-no-menus-message:first").toggle(0===q),p.find("option[value="+String(d.previous_term_id)+"]").remove(),b.customize.control.each(function(a){/^nav_menu_locations\[/.test(a.id)&&a.container.find("option[value="+String(d.previous_term_id)+"]").remove()}),a.each(function(b){var c=a.state("saved").get();/^nav_menu_locations\[/.test(b.id)&&b.get()===d.previous_term_id&&(b.set(d.term_id),b._dirty=!1,a.state("saved").set(c),b.preview())}),m.expanded.get()&&n.expand()}else if("updated"===d.status){if(h="nav_menu["+String(d.term_id)+"]",!a.has(h))throw new Error("Expected setting to exist: "+h);k=a(h),_.isEqual(d.saved_value,k.get())||(o=a.state("saved").get(),k.set(d.saved_value),k._dirty=!1,a.state("saved").set(o))}}),_(d.nav_menu_item_updates).each(function(a){a.previous_post_id&&(f[a.previous_post_id]=a.post_id)}),_(d.nav_menu_item_updates).each(function(b){var c,d,g,h,i,j,k;if("inserted"===b.status){if(!b.previous_post_id)throw new Error("Expected previous_post_id");if(!b.post_id)throw new Error("Expected post_id");if(c="nav_menu_item["+String(b.previous_post_id)+"]",!a.has(c))throw new Error("Expected setting to exist: "+c);if(g=a(c),!a.control.has(c))throw new Error("Expected control to exist: "+c);if(j=a.control(c),i=g.get(),!i)throw new Error("Did not expect setting to be empty (deleted).");if(i=_.clone(i),i.menu_item_parent<0){if(!f[i.menu_item_parent])throw new Error("inserted ID for menu_item_parent not available");i.menu_item_parent=f[i.menu_item_parent]}e[i.nav_menu_term_id]&&(i.nav_menu_term_id=e[i.nav_menu_term_id]),d="nav_menu_item["+String(b.post_id)+"]",h=a.create(d,d,i,{type:"nav_menu_item",transport:a.Menus.data.settingTransport,previewer:a.previewer}),k=new a.controlConstructor.nav_menu_item(d,{params:{type:"nav_menu_item",content:'',menu_id:b.post_id,section:"nav_menu["+String(i.nav_menu_term_id)+"]",priority:j.priority.get(),active:!0,settings:{"default":d},menu_item_id:b.post_id},previewer:a.previewer}),j.container.remove(),a.control.remove(c),a.control.add(d,k),g.callbacks.disable(),g.set(!1),g.preview(),h.preview(),g._dirty=!1,k.container.toggleClass("menu-item-edit-inactive",j.container.hasClass("menu-item-edit-inactive"))}}),_.each(d.widget_nav_menu_updates,function(b,c){var d=a(c);d&&(d._value=b,d.preview())})},a.Menus.focusMenuItemControl=function(b){var c=a.Menus.getMenuItemControl(b);c&&c.focus()},a.Menus.getMenuControl=function(b){return a.control("nav_menu["+b+"]")},a.Menus.getMenuItemControl=function(b){return a.control(d(b))}}(wp.customize,wp,jQuery);
\ No newline at end of file
diff --git a/wp-admin/js/customize-widgets.js b/wp-admin/js/customize-widgets.js
index 360c18378e..91a65164e9 100644
--- a/wp-admin/js/customize-widgets.js
+++ b/wp-admin/js/customize-widgets.js
@@ -34,7 +34,7 @@
multi_number: null,
name: null,
id_base: null,
- transport: 'refresh',
+ transport: api.Widgets.data.selectiveRefresh ? 'postMessage' : 'refresh',
params: [],
width: null,
height: null,
@@ -1982,7 +1982,7 @@
isExistingWidget = api.has( settingId );
if ( ! isExistingWidget ) {
settingArgs = {
- transport: 'refresh',
+ transport: api.Widgets.data.selectiveRefresh ? 'postMessage' : 'refresh',
previewer: this.setting.previewer
};
setting = api.create( settingId, settingId, '', settingArgs );
diff --git a/wp-admin/js/customize-widgets.min.js b/wp-admin/js/customize-widgets.min.js
index 2d4134d92c..b8089a0a50 100644
--- a/wp-admin/js/customize-widgets.min.js
+++ b/wp-admin/js/customize-widgets.min.js
@@ -1 +1 @@
-!function(a,b){function c(a){var b,c={number:null,id_base:null};return b=a.match(/^(.+)-(\d+)$/),b?(c.id_base=b[1],c.number=parseInt(b[2],10)):c.id_base=a,c}function d(a){var b,d=c(a);return b="widget_"+d.id_base,d.number&&(b+="["+d.number+"]"),b}if(a&&a.customize){var e,f=a.customize;f.Widgets=f.Widgets||{},f.Widgets.savedWidgetIds={},f.Widgets.data=_wpCustomizeWidgetsSettings||{},e=f.Widgets.data.l10n,delete f.Widgets.data.l10n,f.Widgets.WidgetModel=Backbone.Model.extend({id:null,temp_id:null,classname:null,control_tpl:null,description:null,is_disabled:null,is_multi:null,multi_number:null,name:null,id_base:null,transport:"refresh",params:[],width:null,height:null,search_matched:!0}),f.Widgets.WidgetCollection=Backbone.Collection.extend({model:f.Widgets.WidgetModel,doSearch:function(a){this.terms!==a&&(this.terms=a,this.terms.length>0&&this.search(this.terms),""===this.terms&&this.each(function(a){a.set("search_matched",!0)}))},search:function(a){var b,c;a=a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&"),a=a.replace(/ /g,")(?=.*"),b=new RegExp("^(?=.*"+a+").+","i"),this.each(function(a){c=[a.get("name"),a.get("id"),a.get("description")].join(" "),a.set("search_matched",b.test(c))})}}),f.Widgets.availableWidgets=new f.Widgets.WidgetCollection(f.Widgets.data.availableWidgets),f.Widgets.SidebarModel=Backbone.Model.extend({after_title:null,after_widget:null,before_title:null,before_widget:null,"class":null,description:null,id:null,name:null,is_rendered:!1}),f.Widgets.SidebarCollection=Backbone.Collection.extend({model:f.Widgets.SidebarModel}),f.Widgets.registeredSidebars=new f.Widgets.SidebarCollection(f.Widgets.data.registeredSidebars),f.Widgets.AvailableWidgetsPanelView=a.Backbone.View.extend({el:"#available-widgets",events:{"input #widgets-search":"search","keyup #widgets-search":"search","change #widgets-search":"search","search #widgets-search":"search","focus .widget-tpl":"focus","click .widget-tpl":"_submit","keypress .widget-tpl":"_submit",keydown:"keyboardAccessible"},selected:null,currentSidebarControl:null,$search:null,initialize:function(){var a=this;this.$search=b("#widgets-search"),_.bindAll(this,"close"),this.listenTo(this.collection,"change",this.updateList),this.updateList(),b("#customize-controls, #available-widgets .customize-section-title").on("click keydown",function(c){var d=b(c.target).is(".add-new-widget, .add-new-widget *");b("body").hasClass("adding-widget")&&!d&&a.close()}),f.previewer.bind("url",this.close)},search:function(a){var b;this.collection.doSearch(a.target.value),this.selected&&!this.selected.is(":visible")&&(this.selected.removeClass("selected"),this.selected=null),this.selected&&!a.target.value&&(this.selected.removeClass("selected"),this.selected=null),!this.selected&&a.target.value&&(b=this.$el.find("> .widget-tpl:visible:first"),b.length&&this.select(b))},updateList:function(){this.collection.each(function(a){var c=b("#widget-tpl-"+a.id);c.toggle(a.get("search_matched")&&!a.get("is_disabled")),a.get("is_disabled")&&c.is(this.selected)&&(this.selected=null)})},select:function(a){this.selected=b(a),this.selected.siblings(".widget-tpl").removeClass("selected"),this.selected.addClass("selected")},focus:function(a){this.select(b(a.currentTarget))},_submit:function(a){("keypress"!==a.type||13===a.which||32===a.which)&&this.submit(b(a.currentTarget))},submit:function(a){var c,d,e;a||(a=this.selected),a&&this.currentSidebarControl&&(this.select(a),c=b(this.selected).data("widget-id"),d=this.collection.findWhere({id:c}),d&&(e=this.currentSidebarControl.addWidget(d.get("id_base")),e&&e.focus(),this.close()))},open:function(a){this.currentSidebarControl=a,_(this.currentSidebarControl.getWidgetFormControls()).each(function(a){a.params.is_wide&&a.collapseForm()}),b("body").addClass("adding-widget"),this.$el.find(".selected").removeClass("selected"),this.collection.doSearch(""),f.settings.browser.mobile||this.$search.focus()},close:function(a){a=a||{},a.returnFocus&&this.currentSidebarControl&&this.currentSidebarControl.container.find(".add-new-widget").focus(),this.currentSidebarControl=null,this.selected=null,b("body").removeClass("adding-widget"),this.$search.val("")},keyboardAccessible:function(a){var c=13===a.which,d=27===a.which,e=40===a.which,f=38===a.which,g=9===a.which,h=a.shiftKey,i=null,j=this.$el.find("> .widget-tpl:visible:first"),k=this.$el.find("> .widget-tpl:visible:last"),l=b(a.target).is(this.$search),m=b(a.target).is(".widget-tpl:visible:last");return e||f?(e?l?i=j:this.selected&&0!==this.selected.nextAll(".widget-tpl:visible").length&&(i=this.selected.nextAll(".widget-tpl:visible:first")):f&&(l?i=k:this.selected&&0!==this.selected.prevAll(".widget-tpl:visible").length&&(i=this.selected.prevAll(".widget-tpl:visible:first"))),this.select(i),void(i?i.focus():this.$search.focus())):void((!c||this.$search.val())&&(c?this.submit():d&&this.close({returnFocus:!0}),this.currentSidebarControl&&g&&(h&&l||!h&&m)&&(this.currentSidebarControl.container.find(".add-new-widget").focus(),a.preventDefault())))}}),f.Widgets.formSyncHandlers={rss:function(a,c,d){var e=c.find(".widget-error:first"),f=b("
"+d+"
").find(".widget-error:first");e.length&&f.length?e.replaceWith(f):e.length?e.remove():f.length&&c.find(".widget-content:first").prepend(f)}},f.Widgets.WidgetControl=f.Control.extend({defaultExpandedArguments:{duration:"fast",completeCallback:b.noop},initialize:function(a,c){var d=this;d.widgetControlEmbedded=!1,d.widgetContentEmbedded=!1,d.expanded=new f.Value(!1),d.expandedArgumentsQueue=[],d.expanded.bind(function(a){var c=d.expandedArgumentsQueue.shift();c=b.extend({},d.defaultExpandedArguments,c),d.onChangeExpanded(a,c)}),f.Control.prototype.initialize.call(d,a,c)},ready:function(){var a=this;a.section()?f.section(a.section(),function(b){var c=function(d){d&&(a.embedWidgetControl(),b.expanded.unbind(c))};b.expanded()?c(!0):b.expanded.bind(c)}):a.embedWidgetControl()},embedWidgetControl:function(){var a,c=this;c.widgetControlEmbedded||(c.widgetControlEmbedded=!0,a=b(c.params.widget_control),c.container.append(a),c._setupModel(),c._setupWideWidget(),c._setupControlToggle(),c._setupWidgetTitle(),c._setupReorderUI(),c._setupHighlightEffects(),c._setupUpdateUI(),c._setupRemoveUI())},embedWidgetContent:function(){var a,c=this;c.embedWidgetControl(),c.widgetContentEmbedded||(c.widgetContentEmbedded=!0,a=b(c.params.widget_content),c.container.find(".widget-content:first").append(a),b(document).trigger("widget-added",[c.container.find(".widget:first")]))},_setupModel:function(){var a,b=this;a=function(){f.Widgets.savedWidgetIds[b.params.widget_id]=!0},f.bind("ready",a),f.bind("saved",a),this._updateCount=0,this.isWidgetUpdating=!1,this.liveUpdateMode=!0,this.setting.bind(function(a,c){_(c).isEqual(a)||b.isWidgetUpdating||b.updateWidget({instance:a})})},_setupWideWidget:function(){var a,c,d,e,g,h=this;this.params.is_wide&&(a=this.container.find(".widget-inside"),c=a.find("> .form"),d=b(".wp-full-overlay-sidebar-content:first"),this.container.addClass("wide-widget-control"),this.container.find(".widget-content:first").css({"max-width":this.params.width,"min-height":this.params.height}),g=function(){var d,e=h.container.offset().top,f=b(window).height(),g=c.outerHeight();a.css("max-height",f),d=Math.max(0,Math.min(Math.max(e,0),f-g)),a.css("top",d)},e=b("#customize-theme-controls"),this.container.on("expand",function(){g(),d.on("scroll",g),b(window).on("resize",g),e.on("expanded collapsed",g)}),this.container.on("collapsed",function(){d.off("scroll",g),b(window).off("resize",g),e.off("expanded collapsed",g)}),f.each(function(a){0===a.id.indexOf("sidebars_widgets[")&&a.bind(function(){h.container.hasClass("expanded")&&g()})}))},_setupControlToggle:function(){var a,b=this;this.container.find(".widget-top").on("click",function(a){a.preventDefault();var c=b.getSidebarWidgetsControl();c.isReordering||b.expanded(!b.expanded())}),a=this.container.find(".widget-control-close"),a.on("click",function(a){a.preventDefault(),b.collapse(),b.container.find(".widget-top .widget-action:first").focus()})},_setupWidgetTitle:function(){var a,b=this;a=function(){var a=b.setting().title,c=b.container.find(".in-widget-title");a?c.text(": "+a):c.text("")},this.setting.bind(a),a()},_setupReorderUI:function(){var c,d,g,h,i,j=this;c=function(a){a.siblings(".selected").removeClass("selected"),a.addClass("selected");var b=a.data("id")===j.params.sidebar_id;j.container.find(".move-widget-btn").prop("disabled",b)},this.container.find(".widget-title-action").after(b(f.Widgets.data.tpl.widgetReorderNav)),i=_.template(f.Widgets.data.tpl.moveWidgetArea),d=b(i({sidebars:_(f.Widgets.registeredSidebars.toArray()).pluck("attributes")})),this.container.find(".widget-top").after(d),h=function(){var a,e=d.find("li"),g=0;a=e.filter(function(){return b(this).data("id")===j.params.sidebar_id}),e.each(function(){var d,e,h,i=b(this);d=i.data("id"),e=f.Widgets.registeredSidebars.get(d),h=e.get("is_rendered"),i.toggle(h),h&&(g+=1),i.hasClass("selected")&&!h&&c(a)}),g>1?j.container.find(".move-widget").show():j.container.find(".move-widget").hide()},h(),f.Widgets.registeredSidebars.on("change:is_rendered",h),g=this.container.find(".widget-reorder-nav"),g.find(".move-widget, .move-widget-down, .move-widget-up").each(function(){b(this).prepend(j.container.find(".widget-title").text()+": ")}).on("click keypress",function(c){if("keypress"!==c.type||13===c.which||32===c.which)if(b(this).focus(),b(this).is(".move-widget"))j.toggleWidgetMoveArea();else{var d=b(this).is(".move-widget-down"),f=b(this).is(".move-widget-up"),g=j.getWidgetSidebarPosition();if(f&&0===g||d&&g===j.getSidebarWidgetsControl().setting().length-1)return;f?(j.moveUp(),a.a11y.speak(e.widgetMovedUp)):(j.moveDown(),a.a11y.speak(e.widgetMovedDown)),b(this).focus()}}),this.container.find(".widget-area-select").on("click keypress","li",function(a){("keypress"!==a.type||13===a.which||32===a.which)&&(a.preventDefault(),c(b(this)))}),this.container.find(".move-widget-btn").click(function(){j.getSidebarWidgetsControl().toggleReordering(!1);var a,b,c,d,e,g=j.params.sidebar_id,h=j.container.find(".widget-area-select li.selected").data("id");a=f("sidebars_widgets["+g+"]"),b=f("sidebars_widgets["+h+"]"),c=Array.prototype.slice.call(a()),d=Array.prototype.slice.call(b()),e=j.getWidgetSidebarPosition(),c.splice(e,1),d.push(j.params.widget_id),a(c),b(d),j.focus()})},_setupHighlightEffects:function(){var a=this;this.container.on("mouseenter click",function(){a.setting.previewer.send("highlight-widget",a.params.widget_id)}),this.setting.bind(function(){a.setting.previewer.send("highlight-widget",a.params.widget_id)})},_setupUpdateUI:function(){var a,c,d,g,h,i=this;a=this.container.find(".widget:first"),c=a.find(".widget-content:first"),d=this.container.find(".widget-control-save"),d.val(e.saveBtnLabel),d.attr("title",e.saveBtnTooltip),d.removeClass("button-primary").addClass("button-secondary"),d.on("click",function(a){a.preventDefault(),i.updateWidget({disable_form:!0})}),g=_.debounce(function(){i.updateWidget()},250),c.on("keydown","input",function(a){13===a.which&&(a.preventDefault(),i.updateWidget({ignoreActiveElement:!0}))}),c.on("change input propertychange",":input",function(a){i.liveUpdateMode&&("change"===a.type||this.checkValidity&&this.checkValidity())&&g()}),this.setting.previewer.channel.bind("synced",function(){i.container.removeClass("previewer-loading")}),f.previewer.bind("widget-updated",function(a){a===i.params.widget_id&&i.container.removeClass("previewer-loading")}),h=f.Widgets.formSyncHandlers[this.params.widget_id_base],h&&b(document).on("widget-synced",function(b,c){a.is(c)&&h.apply(document,arguments)})},onChangeActive:function(a,b){this.container.toggleClass("widget-rendered",a),b.completeCallback&&b.completeCallback()},_setupRemoveUI:function(){var a,b,c=this;a=this.container.find("a.widget-control-remove"),a.on("click",function(a){a.preventDefault();var b;b=c.container.next().is(".customize-control-widget_form")?c.container.next().find(".widget-action:first"):c.container.prev().is(".customize-control-widget_form")?c.container.prev().find(".widget-action:first"):c.container.next(".customize-control-sidebar_widgets").find(".add-new-widget:first"),c.container.slideUp(function(){var a,d,e=f.Widgets.getSidebarWidgetControlContainingWidget(c.params.widget_id);e&&(a=e.setting().slice(),d=_.indexOf(a,c.params.widget_id),-1!==d&&(a.splice(d,1),e.setting(a),b.focus()))})}),b=function(){a.text(e.removeBtnLabel),a.attr("title",e.removeBtnTooltip)},this.params.is_new?f.bind("saved",b):b()},_getInputs:function(a){return b(a).find(":input[name]")},_getInputsSignature:function(a){var c=_(a).map(function(a){var c,d=b(a);return c=d.is(":checkbox, :radio")?[d.attr("id"),d.attr("name"),d.prop("value")]:[d.attr("id"),d.attr("name")],c.join(",")});return c.join(";")},_getInputState:function(a){return a=b(a),a.is(":radio, :checkbox")?a.prop("checked"):a.is("select[multiple]")?a.find("option:selected").map(function(){return b(this).val()}).get():a.val()},_setInputState:function(a,c){a=b(a),a.is(":radio, :checkbox")?a.prop("checked",c):a.is("select[multiple]")?(c=b.isArray(c)?_.map(c,function(a){return String(a)}):[],a.find("option").each(function(){b(this).prop("selected",-1!==_.indexOf(c,String(this.value)))})):a.val(c)},getSidebarWidgetsControl:function(){var a,b;return a="sidebars_widgets["+this.params.sidebar_id+"]",(b=f.control(a))?b:void 0},updateWidget:function(c){var d,g,h,i,j,k,l,m,n,o,p,q=this;q.embedWidgetContent(),c=b.extend({instance:null,complete:null,ignoreActiveElement:!1},c),d=c.instance,g=c.complete,this._updateCount+=1,j=this._updateCount,h=this.container.find(".widget:first"),i=h.find(".widget-content:first"),i.find(".widget-error").remove(),this.container.addClass("widget-form-loading"),this.container.addClass("previewer-loading"),n=f.state("processing"),n(n()+1),this.liveUpdateMode||this.container.addClass("widget-form-disabled"),k={},k.action="update-widget",k.wp_customize="on",k.nonce=f.settings.nonce["update-widget"],k.theme=f.settings.theme.stylesheet,k.customized=a.customize.previewer.query().customized,l=b.param(k),m=this._getInputs(i),m.each(function(){b(this).data("state"+j,q._getInputState(this))}),l+=d?"&"+b.param({sanitized_widget_setting:JSON.stringify(d)}):"&"+m.serialize(),l+="&"+i.find("~ :input").serialize(),this._previousUpdateRequest&&this._previousUpdateRequest.abort(),o=b.post(a.ajax.settings.url,l),this._previousUpdateRequest=o,o.done(function(a){var d,k,l,n,o=!1;return"0"===a?(f.previewer.preview.iframe.hide(),void f.previewer.login().done(function(){q.updateWidget(c),f.previewer.preview.iframe.show()})):"-1"===a?void f.previewer.cheatin():void(a.success?(k=b("
"+a.data.form+"
"),l=q._getInputs(k),n=q._getInputsSignature(m)===q._getInputsSignature(l),n&&!q.liveUpdateMode&&(q.liveUpdateMode=!0,q.container.removeClass("widget-form-disabled"),q.container.find('input[name="savewidget"]').hide()),n&&q.liveUpdateMode?(m.each(function(a){var d,e,f,g=b(this),h=b(l[a]);d=g.data("state"+j),e=q._getInputState(h),g.data("sanitized",e),f=!_.isEqual(d,e)&&(c.ignoreActiveElement||!g.is(document.activeElement)),f&&q._setInputState(g,e)}),b(document).trigger("widget-synced",[h,a.data.form])):q.liveUpdateMode?(q.liveUpdateMode=!1,q.container.find('input[name="savewidget"]').show(),o=!0):(i.html(a.data.form),q.container.removeClass("widget-form-disabled"),b(document).trigger("widget-updated",[h])),p=!o&&!_(q.setting()).isEqual(a.data.instance),p?(q.isWidgetUpdating=!0,q.setting(a.data.instance),q.isWidgetUpdating=!1):q.container.removeClass("previewer-loading"),g&&g.call(q,null,{noChange:!p,ajaxFinished:!0})):(d=e.error,a.data&&a.data.message&&(d=a.data.message),g?g.call(q,d):i.prepend('
'+d+"
")))}),o.fail(function(a,b){g&&g.call(q,b)}),o.always(function(){q.container.removeClass("widget-form-loading"),m.each(function(){b(this).removeData("state"+j)}),n(n()-1)})},expandControlSection:function(){f.Control.prototype.expand.call(this)},_toggleExpanded:f.Section.prototype._toggleExpanded,expand:f.Section.prototype.expand,expandForm:function(){this.expand()},collapse:f.Section.prototype.collapse,collapseForm:function(){this.collapse()},toggleForm:function(a){"undefined"==typeof a&&(a=!this.expanded()),this.expanded(a)},onChangeExpanded:function(a,b){var c,d,e,g,h=this;return h.embedWidgetControl(),a&&h.embedWidgetContent(),b.unchanged?void(a&&f.Control.prototype.expand.call(h,{completeCallback:b.completeCallback})):(c=this.container.find("div.widget:first"),d=c.find(".widget-inside:first"),void(a?(h.section()&&f.section(h.section())&&h.expandControlSection(),f.control.each(function(a){h.params.type===a.params.type&&h!==a&&a.collapse()}),e=function(){h.container.removeClass("expanding"),h.container.addClass("expanded"),h.container.trigger("expanded")},b.completeCallback&&(g=e,e=function(){g(),b.completeCallback()}),h.params.is_wide?d.fadeIn(b.duration,e):d.slideDown(b.duration,e),h.container.trigger("expand"),h.container.addClass("expanding")):(e=function(){h.container.removeClass("collapsing"),h.container.removeClass("expanded"),h.container.trigger("collapsed")},b.completeCallback&&(g=e,e=function(){g(),b.completeCallback()}),h.container.trigger("collapse"),h.container.addClass("collapsing"),h.params.is_wide?d.fadeOut(b.duration,e):d.slideUp(b.duration,function(){c.css({width:"",margin:""}),e()}))))},getWidgetSidebarPosition:function(){var a,b;return a=this.getSidebarWidgetsControl().setting(),b=_.indexOf(a,this.params.widget_id),-1!==b?b:void 0},moveUp:function(){this._moveWidgetByOne(-1)},moveDown:function(){this._moveWidgetByOne(1)},_moveWidgetByOne:function(a){var b,c,d,e;b=this.getWidgetSidebarPosition(),c=this.getSidebarWidgetsControl().setting,d=Array.prototype.slice.call(c()),e=d[b+a],d[b+a]=this.params.widget_id,d[b]=e,c(d)},toggleWidgetMoveArea:function(a){var c,d=this;c=this.container.find(".move-widget-area"),"undefined"==typeof a&&(a=!c.hasClass("active")),a&&(c.find(".selected").removeClass("selected"),c.find("li").filter(function(){return b(this).data("id")===d.params.sidebar_id}).addClass("selected"),this.container.find(".move-widget-btn").prop("disabled",!0)),c.toggleClass("active",a)},highlightSectionAndControl:function(){var a;a=this.container.is(":hidden")?this.container.closest(".control-section"):this.container,b(".highlighted").removeClass("highlighted"),a.addClass("highlighted"),setTimeout(function(){a.removeClass("highlighted")},500)}}),f.Widgets.WidgetsPanel=f.Panel.extend({ready:function(){var a=this;f.Panel.prototype.ready.call(a),a.deferred.embedded.done(function(){var c,d,g;c=a.container.find(".panel-meta"),d=b("
",{"class":"no-widget-areas-rendered-notice"}),d.append(b("
",{text:e.noAreasRendered})),c.append(d),g=function(){return 0===_.filter(a.sections(),function(a){return a.active()}).length},d.toggle(g()),f.previewer.deferred.active.done(function(){d.toggle(g())}),f.bind("pane-contents-reflowed",function(){var a="resolved"===f.previewer.deferred.active.state()?"fast":0;g()?d.slideDown(a):d.slideUp(a)})})},isContextuallyActive:function(){var a=this;return a.active()}}),f.Widgets.SidebarSection=f.Section.extend({ready:function(){var a,b=this;f.Section.prototype.ready.call(this),a=f.Widgets.registeredSidebars.get(b.params.sidebarId),b.active.bind(function(b){a.set("is_rendered",b)}),a.set("is_rendered",b.active())}}),f.Widgets.SidebarControl=f.Control.extend({ready:function(){this.$controlSection=this.container.closest(".control-section"),this.$sectionContent=this.container.closest(".accordion-section-content"),this._setupModel(),this._setupSortable(),this._setupAddition(),this._applyCardinalOrderClassNames()},_setupModel:function(){var a=this;this.setting.bind(function(d,e){var g,h,i;h=_(e).difference(d),d=_(d).filter(function(a){var b=c(a);return!!f.Widgets.availableWidgets.findWhere({id_base:b.id_base})}),g=_(d).map(function(b){var c=f.Widgets.getWidgetFormControlForWidget(b);return c||(c=a.addWidget(b)),c}),g.sort(function(a,b){var c=_.indexOf(d,a.params.widget_id),e=_.indexOf(d,b.params.widget_id);return c-e}),i=0,_(g).each(function(b){b.priority(i),b.section(a.section()),i+=1}),a.priority(i),a._applyCardinalOrderClassNames(),_(g).each(function(b){b.params.sidebar_id=a.params.sidebar_id}),_(h).each(function(d){setTimeout(function(){var e,g,h,i,j,k=!1;f.each(function(b){if(b.id!==a.setting.id&&0===b.id.indexOf("sidebars_widgets[")&&"sidebars_widgets[wp_inactive_widgets]"!==b.id){var c,e=b();c=_.indexOf(e,d),-1!==c&&(k=!0)}}),k||(e=f.Widgets.getWidgetFormControlForWidget(d),g=e&&b.contains(document,e.container[0])&&!b.contains(a.$sectionContent[0],e.container[0]),e&&!g&&(f.control.remove(e.id),e.container.remove()),f.Widgets.savedWidgetIds[d]&&(h=f.value("sidebars_widgets[wp_inactive_widgets]")().slice(),h.push(d),f.value("sidebars_widgets[wp_inactive_widgets]")(_(h).unique())),i=c(d).id_base,j=f.Widgets.availableWidgets.findWhere({id_base:i}),j&&!j.get("is_multi")&&j.set("is_disabled",!1))})})})},_setupSortable:function(){var a=this;this.isReordering=!1,this.$sectionContent.sortable({items:"> .customize-control-widget_form",handle:".widget-top",axis:"y",tolerance:"pointer",connectWith:".accordion-section-content:has(.customize-control-sidebar_widgets)",update:function(){var c,d=a.$sectionContent.sortable("toArray");c=b.map(d,function(a){return b("#"+a).find(":input[name=widget-id]").val()}),a.setting(c)}}),this.$controlSection.find(".accordion-section-title").droppable({accept:".customize-control-widget_form",over:function(){var b=f.section(a.section.get());b.expand({allowMultiple:!0,completeCallback:function(){f.section.each(function(a){a.container.find(".customize-control-sidebar_widgets").length&&a.container.find(".accordion-section-content:first").sortable("refreshPositions")})}})}}),this.container.find(".reorder-toggle").on("click",function(){a.toggleReordering(!a.isReordering)})},_setupAddition:function(){var a=this;this.container.find(".add-new-widget").on("click",function(){var c=b(this);a.$sectionContent.hasClass("reordering")||(b("body").hasClass("adding-widget")?(c.attr("aria-expanded","false"),f.Widgets.availableWidgetsPanel.close()):(c.attr("aria-expanded","true"),f.Widgets.availableWidgetsPanel.open(a)))})},_applyCardinalOrderClassNames:function(){var a=[];return _.each(this.setting(),function(b){var c=f.Widgets.getWidgetFormControlForWidget(b);c&&a.push(c)}),0===a.length||1===f.Widgets.registeredSidebars.length&&a.length<=1?void this.container.find(".reorder-toggle").hide():(this.container.find(".reorder-toggle").show(),b(a).each(function(){b(this.container).removeClass("first-widget").removeClass("last-widget").find(".move-widget-down, .move-widget-up").prop("tabIndex",0)}),_.first(a).container.addClass("first-widget").find(".move-widget-up").prop("tabIndex",-1),void _.last(a).container.addClass("last-widget").find(".move-widget-down").prop("tabIndex",-1))},toggleReordering:function(b){var c=this.$sectionContent.find(".add-new-widget"),d=this.container.find(".reorder-toggle"),f=this.$sectionContent.find(".widget-title");b=Boolean(b),b!==this.$sectionContent.hasClass("reordering")&&(this.isReordering=b,this.$sectionContent.toggleClass("reordering",b),b?(_(this.getWidgetFormControls()).each(function(a){a.collapse()}),c.attr({tabindex:"-1","aria-hidden":"true"}),d.attr("aria-label",e.reorderLabelOff),a.a11y.speak(e.reorderModeOn),f.attr("aria-hidden","true")):(c.removeAttr("tabindex aria-hidden"),d.attr("aria-label",e.reorderLabelOn),a.a11y.speak(e.reorderModeOff),f.attr("aria-hidden","false")))},getWidgetFormControls:function(){var a=[];return _(this.setting()).each(function(b){var c=d(b),e=f.control(c);e&&a.push(e)}),a},addWidget:function(a){var d,e,g,h,i,j,k,l,m,n,o=this,p="widget_form",q=c(a),r=q.number,s=q.id_base,t=f.Widgets.availableWidgets.findWhere({id_base:s});return t?r&&!t.get("is_multi")?!1:(t.get("is_multi")&&!r&&(t.set("multi_number",t.get("multi_number")+1),r=t.get("multi_number")),d=b.trim(b("#widget-tpl-"+t.get("id")).html()),t.get("is_multi")?d=d.replace(/<[^<>]+>/g,function(a){return a.replace(/__i__|%i%/g,r)}):t.set("is_disabled",!0),e=b(d),g=b("
").addClass("customize-control").addClass("customize-control-"+p).append(e),g.find("> .widget-icon").remove(),t.get("is_multi")&&(g.find('input[name="widget_number"]').val(r),g.find('input[name="multi_number"]').val(r)),a=g.find('[name="widget-id"]').val(),g.hide(),i="widget_"+t.get("id_base"),t.get("is_multi")&&(i+="["+r+"]"),g.attr("id","customize-control-"+i.replace(/\]/g,"").replace(/\[/g,"-")),j=f.has(i),j||(m={transport:"refresh",previewer:this.setting.previewer},n=f.create(i,i,"",m),n.set({})),h=f.controlConstructor[p],k=new h(i,{params:{settings:{"default":i},content:g,sidebar_id:o.params.sidebar_id,widget_id:a,widget_id_base:t.get("id_base"),type:p,is_new:!j,width:t.get("width"),height:t.get("height"),is_wide:t.get("is_wide"),active:!0},previewer:o.setting.previewer}),f.control.add(i,k),f.each(function(b){if(b.id!==o.setting.id&&0===b.id.indexOf("sidebars_widgets[")){var c=b().slice(),d=_.indexOf(c,a);-1!==d&&(c.splice(d),b(c))}}),l=this.setting().slice(),-1===_.indexOf(l,a)&&(l.push(a),this.setting(l)),g.slideDown(function(){j&&k.updateWidget({instance:k.setting()})}),k):!1}}),b.extend(f.panelConstructor,{widgets:f.Widgets.WidgetsPanel}),b.extend(f.sectionConstructor,{sidebar:f.Widgets.SidebarSection}),b.extend(f.controlConstructor,{widget_form:f.Widgets.WidgetControl,sidebar_widgets:f.Widgets.SidebarControl}),f.bind("ready",function(){f.Widgets.availableWidgetsPanel=new f.Widgets.AvailableWidgetsPanelView({collection:f.Widgets.availableWidgets}),f.previewer.bind("highlight-widget-control",f.Widgets.highlightWidgetFormControl),f.previewer.bind("focus-widget-control",f.Widgets.focusWidgetFormControl)}),f.Widgets.highlightWidgetFormControl=function(a){var b=f.Widgets.getWidgetFormControlForWidget(a);b&&b.highlightSectionAndControl()},f.Widgets.focusWidgetFormControl=function(a){var b=f.Widgets.getWidgetFormControlForWidget(a);b&&b.focus()},f.Widgets.getSidebarWidgetControlContainingWidget=function(a){var b=null;return f.control.each(function(c){"sidebar_widgets"===c.params.type&&-1!==_.indexOf(c.setting(),a)&&(b=c)}),b},f.Widgets.getWidgetFormControlForWidget=function(a){var b=null;return f.control.each(function(c){"widget_form"===c.params.type&&c.params.widget_id===a&&(b=c)}),b}}}(window.wp,jQuery);
\ No newline at end of file
+!function(a,b){function c(a){var b,c={number:null,id_base:null};return b=a.match(/^(.+)-(\d+)$/),b?(c.id_base=b[1],c.number=parseInt(b[2],10)):c.id_base=a,c}function d(a){var b,d=c(a);return b="widget_"+d.id_base,d.number&&(b+="["+d.number+"]"),b}if(a&&a.customize){var e,f=a.customize;f.Widgets=f.Widgets||{},f.Widgets.savedWidgetIds={},f.Widgets.data=_wpCustomizeWidgetsSettings||{},e=f.Widgets.data.l10n,delete f.Widgets.data.l10n,f.Widgets.WidgetModel=Backbone.Model.extend({id:null,temp_id:null,classname:null,control_tpl:null,description:null,is_disabled:null,is_multi:null,multi_number:null,name:null,id_base:null,transport:f.Widgets.data.selectiveRefresh?"postMessage":"refresh",params:[],width:null,height:null,search_matched:!0}),f.Widgets.WidgetCollection=Backbone.Collection.extend({model:f.Widgets.WidgetModel,doSearch:function(a){this.terms!==a&&(this.terms=a,this.terms.length>0&&this.search(this.terms),""===this.terms&&this.each(function(a){a.set("search_matched",!0)}))},search:function(a){var b,c;a=a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&"),a=a.replace(/ /g,")(?=.*"),b=new RegExp("^(?=.*"+a+").+","i"),this.each(function(a){c=[a.get("name"),a.get("id"),a.get("description")].join(" "),a.set("search_matched",b.test(c))})}}),f.Widgets.availableWidgets=new f.Widgets.WidgetCollection(f.Widgets.data.availableWidgets),f.Widgets.SidebarModel=Backbone.Model.extend({after_title:null,after_widget:null,before_title:null,before_widget:null,"class":null,description:null,id:null,name:null,is_rendered:!1}),f.Widgets.SidebarCollection=Backbone.Collection.extend({model:f.Widgets.SidebarModel}),f.Widgets.registeredSidebars=new f.Widgets.SidebarCollection(f.Widgets.data.registeredSidebars),f.Widgets.AvailableWidgetsPanelView=a.Backbone.View.extend({el:"#available-widgets",events:{"input #widgets-search":"search","keyup #widgets-search":"search","change #widgets-search":"search","search #widgets-search":"search","focus .widget-tpl":"focus","click .widget-tpl":"_submit","keypress .widget-tpl":"_submit",keydown:"keyboardAccessible"},selected:null,currentSidebarControl:null,$search:null,initialize:function(){var a=this;this.$search=b("#widgets-search"),_.bindAll(this,"close"),this.listenTo(this.collection,"change",this.updateList),this.updateList(),b("#customize-controls, #available-widgets .customize-section-title").on("click keydown",function(c){var d=b(c.target).is(".add-new-widget, .add-new-widget *");b("body").hasClass("adding-widget")&&!d&&a.close()}),f.previewer.bind("url",this.close)},search:function(a){var b;this.collection.doSearch(a.target.value),this.selected&&!this.selected.is(":visible")&&(this.selected.removeClass("selected"),this.selected=null),this.selected&&!a.target.value&&(this.selected.removeClass("selected"),this.selected=null),!this.selected&&a.target.value&&(b=this.$el.find("> .widget-tpl:visible:first"),b.length&&this.select(b))},updateList:function(){this.collection.each(function(a){var c=b("#widget-tpl-"+a.id);c.toggle(a.get("search_matched")&&!a.get("is_disabled")),a.get("is_disabled")&&c.is(this.selected)&&(this.selected=null)})},select:function(a){this.selected=b(a),this.selected.siblings(".widget-tpl").removeClass("selected"),this.selected.addClass("selected")},focus:function(a){this.select(b(a.currentTarget))},_submit:function(a){("keypress"!==a.type||13===a.which||32===a.which)&&this.submit(b(a.currentTarget))},submit:function(a){var c,d,e;a||(a=this.selected),a&&this.currentSidebarControl&&(this.select(a),c=b(this.selected).data("widget-id"),d=this.collection.findWhere({id:c}),d&&(e=this.currentSidebarControl.addWidget(d.get("id_base")),e&&e.focus(),this.close()))},open:function(a){this.currentSidebarControl=a,_(this.currentSidebarControl.getWidgetFormControls()).each(function(a){a.params.is_wide&&a.collapseForm()}),b("body").addClass("adding-widget"),this.$el.find(".selected").removeClass("selected"),this.collection.doSearch(""),f.settings.browser.mobile||this.$search.focus()},close:function(a){a=a||{},a.returnFocus&&this.currentSidebarControl&&this.currentSidebarControl.container.find(".add-new-widget").focus(),this.currentSidebarControl=null,this.selected=null,b("body").removeClass("adding-widget"),this.$search.val("")},keyboardAccessible:function(a){var c=13===a.which,d=27===a.which,e=40===a.which,f=38===a.which,g=9===a.which,h=a.shiftKey,i=null,j=this.$el.find("> .widget-tpl:visible:first"),k=this.$el.find("> .widget-tpl:visible:last"),l=b(a.target).is(this.$search),m=b(a.target).is(".widget-tpl:visible:last");return e||f?(e?l?i=j:this.selected&&0!==this.selected.nextAll(".widget-tpl:visible").length&&(i=this.selected.nextAll(".widget-tpl:visible:first")):f&&(l?i=k:this.selected&&0!==this.selected.prevAll(".widget-tpl:visible").length&&(i=this.selected.prevAll(".widget-tpl:visible:first"))),this.select(i),void(i?i.focus():this.$search.focus())):void((!c||this.$search.val())&&(c?this.submit():d&&this.close({returnFocus:!0}),this.currentSidebarControl&&g&&(h&&l||!h&&m)&&(this.currentSidebarControl.container.find(".add-new-widget").focus(),a.preventDefault())))}}),f.Widgets.formSyncHandlers={rss:function(a,c,d){var e=c.find(".widget-error:first"),f=b("
"+d+"
").find(".widget-error:first");e.length&&f.length?e.replaceWith(f):e.length?e.remove():f.length&&c.find(".widget-content:first").prepend(f)}},f.Widgets.WidgetControl=f.Control.extend({defaultExpandedArguments:{duration:"fast",completeCallback:b.noop},initialize:function(a,c){var d=this;d.widgetControlEmbedded=!1,d.widgetContentEmbedded=!1,d.expanded=new f.Value(!1),d.expandedArgumentsQueue=[],d.expanded.bind(function(a){var c=d.expandedArgumentsQueue.shift();c=b.extend({},d.defaultExpandedArguments,c),d.onChangeExpanded(a,c)}),f.Control.prototype.initialize.call(d,a,c)},ready:function(){var a=this;a.section()?f.section(a.section(),function(b){var c=function(d){d&&(a.embedWidgetControl(),b.expanded.unbind(c))};b.expanded()?c(!0):b.expanded.bind(c)}):a.embedWidgetControl()},embedWidgetControl:function(){var a,c=this;c.widgetControlEmbedded||(c.widgetControlEmbedded=!0,a=b(c.params.widget_control),c.container.append(a),c._setupModel(),c._setupWideWidget(),c._setupControlToggle(),c._setupWidgetTitle(),c._setupReorderUI(),c._setupHighlightEffects(),c._setupUpdateUI(),c._setupRemoveUI())},embedWidgetContent:function(){var a,c=this;c.embedWidgetControl(),c.widgetContentEmbedded||(c.widgetContentEmbedded=!0,a=b(c.params.widget_content),c.container.find(".widget-content:first").append(a),b(document).trigger("widget-added",[c.container.find(".widget:first")]))},_setupModel:function(){var a,b=this;a=function(){f.Widgets.savedWidgetIds[b.params.widget_id]=!0},f.bind("ready",a),f.bind("saved",a),this._updateCount=0,this.isWidgetUpdating=!1,this.liveUpdateMode=!0,this.setting.bind(function(a,c){_(c).isEqual(a)||b.isWidgetUpdating||b.updateWidget({instance:a})})},_setupWideWidget:function(){var a,c,d,e,g,h=this;this.params.is_wide&&(a=this.container.find(".widget-inside"),c=a.find("> .form"),d=b(".wp-full-overlay-sidebar-content:first"),this.container.addClass("wide-widget-control"),this.container.find(".widget-content:first").css({"max-width":this.params.width,"min-height":this.params.height}),g=function(){var d,e=h.container.offset().top,f=b(window).height(),g=c.outerHeight();a.css("max-height",f),d=Math.max(0,Math.min(Math.max(e,0),f-g)),a.css("top",d)},e=b("#customize-theme-controls"),this.container.on("expand",function(){g(),d.on("scroll",g),b(window).on("resize",g),e.on("expanded collapsed",g)}),this.container.on("collapsed",function(){d.off("scroll",g),b(window).off("resize",g),e.off("expanded collapsed",g)}),f.each(function(a){0===a.id.indexOf("sidebars_widgets[")&&a.bind(function(){h.container.hasClass("expanded")&&g()})}))},_setupControlToggle:function(){var a,b=this;this.container.find(".widget-top").on("click",function(a){a.preventDefault();var c=b.getSidebarWidgetsControl();c.isReordering||b.expanded(!b.expanded())}),a=this.container.find(".widget-control-close"),a.on("click",function(a){a.preventDefault(),b.collapse(),b.container.find(".widget-top .widget-action:first").focus()})},_setupWidgetTitle:function(){var a,b=this;a=function(){var a=b.setting().title,c=b.container.find(".in-widget-title");a?c.text(": "+a):c.text("")},this.setting.bind(a),a()},_setupReorderUI:function(){var c,d,g,h,i,j=this;c=function(a){a.siblings(".selected").removeClass("selected"),a.addClass("selected");var b=a.data("id")===j.params.sidebar_id;j.container.find(".move-widget-btn").prop("disabled",b)},this.container.find(".widget-title-action").after(b(f.Widgets.data.tpl.widgetReorderNav)),i=_.template(f.Widgets.data.tpl.moveWidgetArea),d=b(i({sidebars:_(f.Widgets.registeredSidebars.toArray()).pluck("attributes")})),this.container.find(".widget-top").after(d),h=function(){var a,e=d.find("li"),g=0;a=e.filter(function(){return b(this).data("id")===j.params.sidebar_id}),e.each(function(){var d,e,h,i=b(this);d=i.data("id"),e=f.Widgets.registeredSidebars.get(d),h=e.get("is_rendered"),i.toggle(h),h&&(g+=1),i.hasClass("selected")&&!h&&c(a)}),g>1?j.container.find(".move-widget").show():j.container.find(".move-widget").hide()},h(),f.Widgets.registeredSidebars.on("change:is_rendered",h),g=this.container.find(".widget-reorder-nav"),g.find(".move-widget, .move-widget-down, .move-widget-up").each(function(){b(this).prepend(j.container.find(".widget-title").text()+": ")}).on("click keypress",function(c){if("keypress"!==c.type||13===c.which||32===c.which)if(b(this).focus(),b(this).is(".move-widget"))j.toggleWidgetMoveArea();else{var d=b(this).is(".move-widget-down"),f=b(this).is(".move-widget-up"),g=j.getWidgetSidebarPosition();if(f&&0===g||d&&g===j.getSidebarWidgetsControl().setting().length-1)return;f?(j.moveUp(),a.a11y.speak(e.widgetMovedUp)):(j.moveDown(),a.a11y.speak(e.widgetMovedDown)),b(this).focus()}}),this.container.find(".widget-area-select").on("click keypress","li",function(a){("keypress"!==a.type||13===a.which||32===a.which)&&(a.preventDefault(),c(b(this)))}),this.container.find(".move-widget-btn").click(function(){j.getSidebarWidgetsControl().toggleReordering(!1);var a,b,c,d,e,g=j.params.sidebar_id,h=j.container.find(".widget-area-select li.selected").data("id");a=f("sidebars_widgets["+g+"]"),b=f("sidebars_widgets["+h+"]"),c=Array.prototype.slice.call(a()),d=Array.prototype.slice.call(b()),e=j.getWidgetSidebarPosition(),c.splice(e,1),d.push(j.params.widget_id),a(c),b(d),j.focus()})},_setupHighlightEffects:function(){var a=this;this.container.on("mouseenter click",function(){a.setting.previewer.send("highlight-widget",a.params.widget_id)}),this.setting.bind(function(){a.setting.previewer.send("highlight-widget",a.params.widget_id)})},_setupUpdateUI:function(){var a,c,d,g,h,i=this;a=this.container.find(".widget:first"),c=a.find(".widget-content:first"),d=this.container.find(".widget-control-save"),d.val(e.saveBtnLabel),d.attr("title",e.saveBtnTooltip),d.removeClass("button-primary").addClass("button-secondary"),d.on("click",function(a){a.preventDefault(),i.updateWidget({disable_form:!0})}),g=_.debounce(function(){i.updateWidget()},250),c.on("keydown","input",function(a){13===a.which&&(a.preventDefault(),i.updateWidget({ignoreActiveElement:!0}))}),c.on("change input propertychange",":input",function(a){i.liveUpdateMode&&("change"===a.type||this.checkValidity&&this.checkValidity())&&g()}),this.setting.previewer.channel.bind("synced",function(){i.container.removeClass("previewer-loading")}),f.previewer.bind("widget-updated",function(a){a===i.params.widget_id&&i.container.removeClass("previewer-loading")}),h=f.Widgets.formSyncHandlers[this.params.widget_id_base],h&&b(document).on("widget-synced",function(b,c){a.is(c)&&h.apply(document,arguments)})},onChangeActive:function(a,b){this.container.toggleClass("widget-rendered",a),b.completeCallback&&b.completeCallback()},_setupRemoveUI:function(){var a,b,c=this;a=this.container.find("a.widget-control-remove"),a.on("click",function(a){a.preventDefault();var b;b=c.container.next().is(".customize-control-widget_form")?c.container.next().find(".widget-action:first"):c.container.prev().is(".customize-control-widget_form")?c.container.prev().find(".widget-action:first"):c.container.next(".customize-control-sidebar_widgets").find(".add-new-widget:first"),c.container.slideUp(function(){var a,d,e=f.Widgets.getSidebarWidgetControlContainingWidget(c.params.widget_id);e&&(a=e.setting().slice(),d=_.indexOf(a,c.params.widget_id),-1!==d&&(a.splice(d,1),e.setting(a),b.focus()))})}),b=function(){a.text(e.removeBtnLabel),a.attr("title",e.removeBtnTooltip)},this.params.is_new?f.bind("saved",b):b()},_getInputs:function(a){return b(a).find(":input[name]")},_getInputsSignature:function(a){var c=_(a).map(function(a){var c,d=b(a);return c=d.is(":checkbox, :radio")?[d.attr("id"),d.attr("name"),d.prop("value")]:[d.attr("id"),d.attr("name")],c.join(",")});return c.join(";")},_getInputState:function(a){return a=b(a),a.is(":radio, :checkbox")?a.prop("checked"):a.is("select[multiple]")?a.find("option:selected").map(function(){return b(this).val()}).get():a.val()},_setInputState:function(a,c){a=b(a),a.is(":radio, :checkbox")?a.prop("checked",c):a.is("select[multiple]")?(c=b.isArray(c)?_.map(c,function(a){return String(a)}):[],a.find("option").each(function(){b(this).prop("selected",-1!==_.indexOf(c,String(this.value)))})):a.val(c)},getSidebarWidgetsControl:function(){var a,b;return a="sidebars_widgets["+this.params.sidebar_id+"]",(b=f.control(a))?b:void 0},updateWidget:function(c){var d,g,h,i,j,k,l,m,n,o,p,q=this;q.embedWidgetContent(),c=b.extend({instance:null,complete:null,ignoreActiveElement:!1},c),d=c.instance,g=c.complete,this._updateCount+=1,j=this._updateCount,h=this.container.find(".widget:first"),i=h.find(".widget-content:first"),i.find(".widget-error").remove(),this.container.addClass("widget-form-loading"),this.container.addClass("previewer-loading"),n=f.state("processing"),n(n()+1),this.liveUpdateMode||this.container.addClass("widget-form-disabled"),k={},k.action="update-widget",k.wp_customize="on",k.nonce=f.settings.nonce["update-widget"],k.theme=f.settings.theme.stylesheet,k.customized=a.customize.previewer.query().customized,l=b.param(k),m=this._getInputs(i),m.each(function(){b(this).data("state"+j,q._getInputState(this))}),l+=d?"&"+b.param({sanitized_widget_setting:JSON.stringify(d)}):"&"+m.serialize(),l+="&"+i.find("~ :input").serialize(),this._previousUpdateRequest&&this._previousUpdateRequest.abort(),o=b.post(a.ajax.settings.url,l),this._previousUpdateRequest=o,o.done(function(a){var d,k,l,n,o=!1;return"0"===a?(f.previewer.preview.iframe.hide(),void f.previewer.login().done(function(){q.updateWidget(c),f.previewer.preview.iframe.show()})):"-1"===a?void f.previewer.cheatin():void(a.success?(k=b("
"+a.data.form+"
"),l=q._getInputs(k),n=q._getInputsSignature(m)===q._getInputsSignature(l),n&&!q.liveUpdateMode&&(q.liveUpdateMode=!0,q.container.removeClass("widget-form-disabled"),q.container.find('input[name="savewidget"]').hide()),n&&q.liveUpdateMode?(m.each(function(a){var d,e,f,g=b(this),h=b(l[a]);d=g.data("state"+j),e=q._getInputState(h),g.data("sanitized",e),f=!_.isEqual(d,e)&&(c.ignoreActiveElement||!g.is(document.activeElement)),f&&q._setInputState(g,e)}),b(document).trigger("widget-synced",[h,a.data.form])):q.liveUpdateMode?(q.liveUpdateMode=!1,q.container.find('input[name="savewidget"]').show(),o=!0):(i.html(a.data.form),q.container.removeClass("widget-form-disabled"),b(document).trigger("widget-updated",[h])),p=!o&&!_(q.setting()).isEqual(a.data.instance),p?(q.isWidgetUpdating=!0,q.setting(a.data.instance),q.isWidgetUpdating=!1):q.container.removeClass("previewer-loading"),g&&g.call(q,null,{noChange:!p,ajaxFinished:!0})):(d=e.error,a.data&&a.data.message&&(d=a.data.message),g?g.call(q,d):i.prepend('
'+d+"
")))}),o.fail(function(a,b){g&&g.call(q,b)}),o.always(function(){q.container.removeClass("widget-form-loading"),m.each(function(){b(this).removeData("state"+j)}),n(n()-1)})},expandControlSection:function(){f.Control.prototype.expand.call(this)},_toggleExpanded:f.Section.prototype._toggleExpanded,expand:f.Section.prototype.expand,expandForm:function(){this.expand()},collapse:f.Section.prototype.collapse,collapseForm:function(){this.collapse()},toggleForm:function(a){"undefined"==typeof a&&(a=!this.expanded()),this.expanded(a)},onChangeExpanded:function(a,b){var c,d,e,g,h=this;return h.embedWidgetControl(),a&&h.embedWidgetContent(),b.unchanged?void(a&&f.Control.prototype.expand.call(h,{completeCallback:b.completeCallback})):(c=this.container.find("div.widget:first"),d=c.find(".widget-inside:first"),void(a?(h.section()&&f.section(h.section())&&h.expandControlSection(),f.control.each(function(a){h.params.type===a.params.type&&h!==a&&a.collapse()}),e=function(){h.container.removeClass("expanding"),h.container.addClass("expanded"),h.container.trigger("expanded")},b.completeCallback&&(g=e,e=function(){g(),b.completeCallback()}),h.params.is_wide?d.fadeIn(b.duration,e):d.slideDown(b.duration,e),h.container.trigger("expand"),h.container.addClass("expanding")):(e=function(){h.container.removeClass("collapsing"),h.container.removeClass("expanded"),h.container.trigger("collapsed")},b.completeCallback&&(g=e,e=function(){g(),b.completeCallback()}),h.container.trigger("collapse"),h.container.addClass("collapsing"),h.params.is_wide?d.fadeOut(b.duration,e):d.slideUp(b.duration,function(){c.css({width:"",margin:""}),e()}))))},getWidgetSidebarPosition:function(){var a,b;return a=this.getSidebarWidgetsControl().setting(),b=_.indexOf(a,this.params.widget_id),-1!==b?b:void 0},moveUp:function(){this._moveWidgetByOne(-1)},moveDown:function(){this._moveWidgetByOne(1)},_moveWidgetByOne:function(a){var b,c,d,e;b=this.getWidgetSidebarPosition(),c=this.getSidebarWidgetsControl().setting,d=Array.prototype.slice.call(c()),e=d[b+a],d[b+a]=this.params.widget_id,d[b]=e,c(d)},toggleWidgetMoveArea:function(a){var c,d=this;c=this.container.find(".move-widget-area"),"undefined"==typeof a&&(a=!c.hasClass("active")),a&&(c.find(".selected").removeClass("selected"),c.find("li").filter(function(){return b(this).data("id")===d.params.sidebar_id}).addClass("selected"),this.container.find(".move-widget-btn").prop("disabled",!0)),c.toggleClass("active",a)},highlightSectionAndControl:function(){var a;a=this.container.is(":hidden")?this.container.closest(".control-section"):this.container,b(".highlighted").removeClass("highlighted"),a.addClass("highlighted"),setTimeout(function(){a.removeClass("highlighted")},500)}}),f.Widgets.WidgetsPanel=f.Panel.extend({ready:function(){var a=this;f.Panel.prototype.ready.call(a),a.deferred.embedded.done(function(){var c,d,g;c=a.container.find(".panel-meta"),d=b("
",{"class":"no-widget-areas-rendered-notice"}),d.append(b("
",{text:e.noAreasRendered})),c.append(d),g=function(){return 0===_.filter(a.sections(),function(a){return a.active()}).length},d.toggle(g()),f.previewer.deferred.active.done(function(){d.toggle(g())}),f.bind("pane-contents-reflowed",function(){var a="resolved"===f.previewer.deferred.active.state()?"fast":0;g()?d.slideDown(a):d.slideUp(a)})})},isContextuallyActive:function(){var a=this;return a.active()}}),f.Widgets.SidebarSection=f.Section.extend({ready:function(){var a,b=this;f.Section.prototype.ready.call(this),a=f.Widgets.registeredSidebars.get(b.params.sidebarId),b.active.bind(function(b){a.set("is_rendered",b)}),a.set("is_rendered",b.active())}}),f.Widgets.SidebarControl=f.Control.extend({ready:function(){this.$controlSection=this.container.closest(".control-section"),this.$sectionContent=this.container.closest(".accordion-section-content"),this._setupModel(),this._setupSortable(),this._setupAddition(),this._applyCardinalOrderClassNames()},_setupModel:function(){var a=this;this.setting.bind(function(d,e){var g,h,i;h=_(e).difference(d),d=_(d).filter(function(a){var b=c(a);return!!f.Widgets.availableWidgets.findWhere({id_base:b.id_base})}),g=_(d).map(function(b){var c=f.Widgets.getWidgetFormControlForWidget(b);return c||(c=a.addWidget(b)),c}),g.sort(function(a,b){var c=_.indexOf(d,a.params.widget_id),e=_.indexOf(d,b.params.widget_id);return c-e}),i=0,_(g).each(function(b){b.priority(i),b.section(a.section()),i+=1}),a.priority(i),a._applyCardinalOrderClassNames(),_(g).each(function(b){b.params.sidebar_id=a.params.sidebar_id}),_(h).each(function(d){setTimeout(function(){var e,g,h,i,j,k=!1;f.each(function(b){if(b.id!==a.setting.id&&0===b.id.indexOf("sidebars_widgets[")&&"sidebars_widgets[wp_inactive_widgets]"!==b.id){var c,e=b();c=_.indexOf(e,d),-1!==c&&(k=!0)}}),k||(e=f.Widgets.getWidgetFormControlForWidget(d),g=e&&b.contains(document,e.container[0])&&!b.contains(a.$sectionContent[0],e.container[0]),e&&!g&&(f.control.remove(e.id),e.container.remove()),f.Widgets.savedWidgetIds[d]&&(h=f.value("sidebars_widgets[wp_inactive_widgets]")().slice(),h.push(d),f.value("sidebars_widgets[wp_inactive_widgets]")(_(h).unique())),i=c(d).id_base,j=f.Widgets.availableWidgets.findWhere({id_base:i}),j&&!j.get("is_multi")&&j.set("is_disabled",!1))})})})},_setupSortable:function(){var a=this;this.isReordering=!1,this.$sectionContent.sortable({items:"> .customize-control-widget_form",handle:".widget-top",axis:"y",tolerance:"pointer",connectWith:".accordion-section-content:has(.customize-control-sidebar_widgets)",update:function(){var c,d=a.$sectionContent.sortable("toArray");c=b.map(d,function(a){return b("#"+a).find(":input[name=widget-id]").val()}),a.setting(c)}}),this.$controlSection.find(".accordion-section-title").droppable({accept:".customize-control-widget_form",over:function(){var b=f.section(a.section.get());b.expand({allowMultiple:!0,completeCallback:function(){f.section.each(function(a){a.container.find(".customize-control-sidebar_widgets").length&&a.container.find(".accordion-section-content:first").sortable("refreshPositions")})}})}}),this.container.find(".reorder-toggle").on("click",function(){a.toggleReordering(!a.isReordering)})},_setupAddition:function(){var a=this;this.container.find(".add-new-widget").on("click",function(){var c=b(this);a.$sectionContent.hasClass("reordering")||(b("body").hasClass("adding-widget")?(c.attr("aria-expanded","false"),f.Widgets.availableWidgetsPanel.close()):(c.attr("aria-expanded","true"),f.Widgets.availableWidgetsPanel.open(a)))})},_applyCardinalOrderClassNames:function(){var a=[];return _.each(this.setting(),function(b){var c=f.Widgets.getWidgetFormControlForWidget(b);c&&a.push(c)}),0===a.length||1===f.Widgets.registeredSidebars.length&&a.length<=1?void this.container.find(".reorder-toggle").hide():(this.container.find(".reorder-toggle").show(),b(a).each(function(){b(this.container).removeClass("first-widget").removeClass("last-widget").find(".move-widget-down, .move-widget-up").prop("tabIndex",0)}),_.first(a).container.addClass("first-widget").find(".move-widget-up").prop("tabIndex",-1),void _.last(a).container.addClass("last-widget").find(".move-widget-down").prop("tabIndex",-1))},toggleReordering:function(b){var c=this.$sectionContent.find(".add-new-widget"),d=this.container.find(".reorder-toggle"),f=this.$sectionContent.find(".widget-title");b=Boolean(b),b!==this.$sectionContent.hasClass("reordering")&&(this.isReordering=b,this.$sectionContent.toggleClass("reordering",b),b?(_(this.getWidgetFormControls()).each(function(a){a.collapse()}),c.attr({tabindex:"-1","aria-hidden":"true"}),d.attr("aria-label",e.reorderLabelOff),a.a11y.speak(e.reorderModeOn),f.attr("aria-hidden","true")):(c.removeAttr("tabindex aria-hidden"),d.attr("aria-label",e.reorderLabelOn),a.a11y.speak(e.reorderModeOff),f.attr("aria-hidden","false")))},getWidgetFormControls:function(){var a=[];return _(this.setting()).each(function(b){var c=d(b),e=f.control(c);e&&a.push(e)}),a},addWidget:function(a){var d,e,g,h,i,j,k,l,m,n,o=this,p="widget_form",q=c(a),r=q.number,s=q.id_base,t=f.Widgets.availableWidgets.findWhere({id_base:s});return t?r&&!t.get("is_multi")?!1:(t.get("is_multi")&&!r&&(t.set("multi_number",t.get("multi_number")+1),r=t.get("multi_number")),d=b.trim(b("#widget-tpl-"+t.get("id")).html()),t.get("is_multi")?d=d.replace(/<[^<>]+>/g,function(a){return a.replace(/__i__|%i%/g,r)}):t.set("is_disabled",!0),e=b(d),g=b("
").addClass("customize-control").addClass("customize-control-"+p).append(e),g.find("> .widget-icon").remove(),t.get("is_multi")&&(g.find('input[name="widget_number"]').val(r),g.find('input[name="multi_number"]').val(r)),a=g.find('[name="widget-id"]').val(),g.hide(),i="widget_"+t.get("id_base"),t.get("is_multi")&&(i+="["+r+"]"),g.attr("id","customize-control-"+i.replace(/\]/g,"").replace(/\[/g,"-")),j=f.has(i),j||(m={transport:f.Widgets.data.selectiveRefresh?"postMessage":"refresh",previewer:this.setting.previewer},n=f.create(i,i,"",m),n.set({})),h=f.controlConstructor[p],k=new h(i,{params:{settings:{"default":i},content:g,sidebar_id:o.params.sidebar_id,widget_id:a,widget_id_base:t.get("id_base"),type:p,is_new:!j,width:t.get("width"),height:t.get("height"),is_wide:t.get("is_wide"),active:!0},previewer:o.setting.previewer}),f.control.add(i,k),f.each(function(b){if(b.id!==o.setting.id&&0===b.id.indexOf("sidebars_widgets[")){var c=b().slice(),d=_.indexOf(c,a);-1!==d&&(c.splice(d),b(c))}}),l=this.setting().slice(),-1===_.indexOf(l,a)&&(l.push(a),this.setting(l)),g.slideDown(function(){j&&k.updateWidget({instance:k.setting()})}),k):!1}}),b.extend(f.panelConstructor,{widgets:f.Widgets.WidgetsPanel}),b.extend(f.sectionConstructor,{sidebar:f.Widgets.SidebarSection}),b.extend(f.controlConstructor,{widget_form:f.Widgets.WidgetControl,sidebar_widgets:f.Widgets.SidebarControl}),f.bind("ready",function(){f.Widgets.availableWidgetsPanel=new f.Widgets.AvailableWidgetsPanelView({collection:f.Widgets.availableWidgets}),f.previewer.bind("highlight-widget-control",f.Widgets.highlightWidgetFormControl),f.previewer.bind("focus-widget-control",f.Widgets.focusWidgetFormControl)}),f.Widgets.highlightWidgetFormControl=function(a){var b=f.Widgets.getWidgetFormControlForWidget(a);b&&b.highlightSectionAndControl()},f.Widgets.focusWidgetFormControl=function(a){var b=f.Widgets.getWidgetFormControlForWidget(a);b&&b.focus()},f.Widgets.getSidebarWidgetControlContainingWidget=function(a){var b=null;return f.control.each(function(c){"sidebar_widgets"===c.params.type&&-1!==_.indexOf(c.setting(),a)&&(b=c)}),b},f.Widgets.getWidgetFormControlForWidget=function(a){var b=null;return f.control.each(function(c){"widget_form"===c.params.type&&c.params.widget_id===a&&(b=c)}),b}}}(window.wp,jQuery);
\ No newline at end of file
diff --git a/wp-content/themes/twentythirteen/js/theme-customizer.js b/wp-content/themes/twentythirteen/js/theme-customizer.js
index 60721045cd..8519752c90 100644
--- a/wp-content/themes/twentythirteen/js/theme-customizer.js
+++ b/wp-content/themes/twentythirteen/js/theme-customizer.js
@@ -38,4 +38,16 @@
}
} );
} );
+
+ if ( wp.customize.selectiveRefresh ) {
+ wp.customize.selectiveRefresh.bind( 'sidebar-updated', function( sidebarPartial ) {
+ var widgetArea;
+ if ( 'sidebar-1' === sidebarPartial.sidebarId && $.isFunction( $.fn.masonry ) ) {
+ widgetArea = $( '#secondary .widget-area' );
+ widgetArea.masonry( 'destroy' );
+ widgetArea.masonry();
+ }
+ } );
+ }
+
} )( jQuery );
diff --git a/wp-includes/class-wp-customize-manager.php b/wp-includes/class-wp-customize-manager.php
index 942d907499..937689bdf0 100644
--- a/wp-includes/class-wp-customize-manager.php
+++ b/wp-includes/class-wp-customize-manager.php
@@ -66,6 +66,15 @@ final class WP_Customize_Manager {
*/
public $nav_menus;
+ /**
+ * Methods and properties dealing with selective refresh in the Customizer preview.
+ *
+ * @since 4.5.0
+ * @access public
+ * @var WP_Customize_Selective_Refresh
+ */
+ public $selective_refresh;
+
/**
* Registered instances of WP_Customize_Setting.
*
@@ -100,7 +109,7 @@ final class WP_Customize_Manager {
* @access protected
* @var array
*/
- protected $components = array( 'widgets', 'nav_menus' );
+ protected $components = array( 'widgets', 'nav_menus', 'selective_refresh' );
/**
* Registered instances of WP_Customize_Section.
@@ -249,15 +258,21 @@ final class WP_Customize_Manager {
*/
$components = apply_filters( 'customize_loaded_components', $this->components, $this );
- if ( in_array( 'widgets', $components ) ) {
+ if ( in_array( 'widgets', $components, true ) ) {
require_once( ABSPATH . WPINC . '/class-wp-customize-widgets.php' );
$this->widgets = new WP_Customize_Widgets( $this );
}
- if ( in_array( 'nav_menus', $components ) ) {
+
+ if ( in_array( 'nav_menus', $components, true ) ) {
require_once( ABSPATH . WPINC . '/class-wp-customize-nav-menus.php' );
$this->nav_menus = new WP_Customize_Nav_Menus( $this );
}
+ if ( in_array( 'selective_refresh', $components, true ) ) {
+ require_once( ABSPATH . WPINC . '/customize/class-wp-customize-selective-refresh.php' );
+ $this->selective_refresh = new WP_Customize_Selective_Refresh( $this );
+ }
+
add_filter( 'wp_die_handler', array( $this, 'wp_die_handler' ) );
add_action( 'setup_theme', array( $this, 'setup_theme' ) );
@@ -1711,6 +1726,7 @@ final class WP_Customize_Manager {
'autofocus' => array(),
'documentTitleTmpl' => $this->get_document_title_template(),
'previewableDevices' => $this->get_previewable_devices(),
+ 'selectiveRefreshEnabled' => isset( $this->selective_refresh ),
);
// Prepare Customize Section objects to pass to JavaScript.
diff --git a/wp-includes/class-wp-customize-nav-menus.php b/wp-includes/class-wp-customize-nav-menus.php
index 8d2b6d5b8e..24384322a0 100644
--- a/wp-includes/class-wp-customize-nav-menus.php
+++ b/wp-includes/class-wp-customize-nav-menus.php
@@ -61,6 +61,9 @@ final class WP_Customize_Nav_Menus {
add_action( 'customize_controls_print_footer_scripts', array( $this, 'print_templates' ) );
add_action( 'customize_controls_print_footer_scripts', array( $this, 'available_items_template' ) );
add_action( 'customize_preview_init', array( $this, 'customize_preview_init' ) );
+
+ // Selective Refresh partials.
+ add_filter( 'customize_dynamic_partial_args', array( $this, 'customize_dynamic_partial_args' ), 10, 2 );
}
/**
@@ -375,7 +378,7 @@ final class WP_Customize_Nav_Menus {
'reorderLabelOn' => esc_attr__( 'Reorder menu items' ),
'reorderLabelOff' => esc_attr__( 'Close reorder mode' ),
),
- 'menuItemTransport' => 'postMessage',
+ 'settingTransport' => isset( $this->manager->selective_refresh ) ? 'postMessage' : 'refresh',
'phpIntMax' => PHP_INT_MAX,
'defaultSettingValues' => array(
'nav_menu' => $temp_nav_menu_setting->default,
@@ -426,11 +429,13 @@ final class WP_Customize_Nav_Menus {
public function filter_dynamic_setting_args( $setting_args, $setting_id ) {
if ( preg_match( WP_Customize_Nav_Menu_Setting::ID_PATTERN, $setting_id ) ) {
$setting_args = array(
- 'type' => WP_Customize_Nav_Menu_Setting::TYPE,
+ 'type' => WP_Customize_Nav_Menu_Setting::TYPE,
+ 'transport' => isset( $this->manager->selective_refresh ) ? 'postMessage' : 'refresh',
);
} elseif ( preg_match( WP_Customize_Nav_Menu_Item_Setting::ID_PATTERN, $setting_id ) ) {
$setting_args = array(
- 'type' => WP_Customize_Nav_Menu_Item_Setting::TYPE,
+ 'type' => WP_Customize_Nav_Menu_Item_Setting::TYPE,
+ 'transport' => isset( $this->manager->selective_refresh ) ? 'postMessage' : 'refresh',
);
}
return $setting_args;
@@ -515,7 +520,7 @@ final class WP_Customize_Nav_Menus {
$setting = $this->manager->get_setting( $setting_id );
if ( $setting ) {
- $setting->transport = 'postMessage';
+ $setting->transport = isset( $this->manager->selective_refresh ) ? 'postMessage' : 'refresh';
remove_filter( "customize_sanitize_{$setting_id}", 'absint' );
add_filter( "customize_sanitize_{$setting_id}", array( $this, 'intval_base10' ) );
} else {
@@ -523,7 +528,7 @@ final class WP_Customize_Nav_Menus {
'sanitize_callback' => array( $this, 'intval_base10' ),
'theme_supports' => 'menus',
'type' => 'theme_mod',
- 'transport' => 'postMessage',
+ 'transport' => isset( $this->manager->selective_refresh ) ? 'postMessage' : 'refresh',
'default' => 0,
) );
}
@@ -549,7 +554,9 @@ final class WP_Customize_Nav_Menus {
) ) );
$nav_menu_setting_id = 'nav_menu[' . $menu_id . ']';
- $this->manager->add_setting( new WP_Customize_Nav_Menu_Setting( $this->manager, $nav_menu_setting_id ) );
+ $this->manager->add_setting( new WP_Customize_Nav_Menu_Setting( $this->manager, $nav_menu_setting_id, array(
+ 'transport' => isset( $this->manager->selective_refresh ) ? 'postMessage' : 'refresh',
+ ) ) );
// Add the menu contents.
$menu_items = (array) wp_get_nav_menu_items( $menu_id );
@@ -562,7 +569,8 @@ final class WP_Customize_Nav_Menus {
$value = (array) $item;
$value['nav_menu_term_id'] = $menu_id;
$this->manager->add_setting( new WP_Customize_Nav_Menu_Item_Setting( $this->manager, $menu_item_setting_id, array(
- 'value' => $value,
+ 'value' => $value,
+ 'transport' => isset( $this->manager->selective_refresh ) ? 'postMessage' : 'refresh',
) ) );
// Create a control for each menu item.
@@ -586,7 +594,7 @@ final class WP_Customize_Nav_Menus {
$this->manager->add_setting( 'new_menu_name', array(
'type' => 'new_menu',
'default' => '',
- 'transport' => 'postMessage',
+ 'transport' => isset( $this->manager->selective_refresh ) ? 'postMessage' : 'refresh',
) );
$this->manager->add_control( 'new_menu_name', array(
@@ -802,28 +810,38 @@ final class WP_Customize_Nav_Menus {
'nav_menu_instance',
+ 'render_callback' => array( $this, 'render_nav_menu_partial' ),
+ 'container_inclusive' => true,
+ )
+ );
+ }
+
+ return $partial_args;
+ }
/**
* Add hooks for the Customizer preview.
@@ -832,13 +850,9 @@ final class WP_Customize_Nav_Menus {
* @access public
*/
public function customize_preview_init() {
- add_action( 'template_redirect', array( $this, 'render_menu' ) );
add_action( 'wp_enqueue_scripts', array( $this, 'customize_preview_enqueue_deps' ) );
-
- if ( ! isset( $_REQUEST[ self::RENDER_QUERY_VAR ] ) ) {
- add_filter( 'wp_nav_menu_args', array( $this, 'filter_wp_nav_menu_args' ), 1000 );
- add_filter( 'wp_nav_menu', array( $this, 'filter_wp_nav_menu' ), 10, 2 );
- }
+ add_filter( 'wp_nav_menu_args', array( $this, 'filter_wp_nav_menu_args' ), 1000 );
+ add_filter( 'wp_nav_menu', array( $this, 'filter_wp_nav_menu' ), 10, 2 );
}
/**
@@ -846,52 +860,68 @@ final class WP_Customize_Nav_Menus {
*
* @since 4.3.0
* @access public
- *
* @see wp_nav_menu()
+ * @see WP_Customize_Widgets_Partial_Refresh::filter_dynamic_sidebar_params()
*
* @param array $args An array containing wp_nav_menu() arguments.
* @return array Arguments.
*/
public function filter_wp_nav_menu_args( $args ) {
- $this->preview_nav_menu_instance_number += 1;
- $args['instance_number'] = $this->preview_nav_menu_instance_number;
-
- $can_partial_refresh = (
+ /*
+ * The following conditions determine whether or not this instance of
+ * wp_nav_menu() can use selective refreshed. A wp_nav_menu() can be
+ * selective refreshed if...
+ */
+ $can_selective_refresh = (
+ // ...if wp_nav_menu() is directly echoing out the menu (and thus isn't manipulating the string after generated),
! empty( $args['echo'] )
&&
+ // ...and if the fallback_cb can be serialized to JSON, since it will be included in the placement context data,
( empty( $args['fallback_cb'] ) || is_string( $args['fallback_cb'] ) )
&&
+ // ...and if the walker can also be serialized to JSON, since it will be included in the placement context data as well,
( empty( $args['walker'] ) || is_string( $args['walker'] ) )
- &&
- (
+ // ...and if it has a theme location assigned or an assigned menu to display,
+ && (
! empty( $args['theme_location'] )
||
( ! empty( $args['menu'] ) && ( is_numeric( $args['menu'] ) || is_object( $args['menu'] ) ) )
)
+ &&
+ // ...and if the nav menu would be rendered with a wrapper container element (upon which to attach data-* attributes).
+ (
+ ! empty( $args['container'] )
+ ||
+ ( isset( $args['items_wrap'] ) && '<' === substr( $args['items_wrap'], 0, 1 ) )
+ )
);
- $args['can_partial_refresh'] = $can_partial_refresh;
- $hashed_args = $args;
-
- if ( ! $can_partial_refresh ) {
- $hashed_args['fallback_cb'] = '';
- $hashed_args['walker'] = '';
+ if ( ! $can_selective_refresh ) {
+ return $args;
}
- // Replace object menu arg with a term_id menu arg, as this exports better to JS and is easier to compare hashes.
- if ( ! empty( $hashed_args['menu'] ) && is_object( $hashed_args['menu'] ) ) {
- $hashed_args['menu'] = $hashed_args['menu']->term_id;
+ $exported_args = $args;
+
+ /*
+ * Replace object menu arg with a term_id menu arg, as this exports better
+ * to JS and is easier to compare hashes.
+ */
+ if ( ! empty( $exported_args['menu'] ) && is_object( $exported_args['menu'] ) ) {
+ $exported_args['menu'] = $exported_args['menu']->term_id;
}
- ksort( $hashed_args );
- $hashed_args['args_hash'] = $this->hash_nav_menu_args( $hashed_args );
+ ksort( $exported_args );
+ $exported_args['args_hmac'] = $this->hash_nav_menu_args( $exported_args );
+
+ $args['customize_preview_nav_menus_args'] = $exported_args;
- $this->preview_nav_menu_instance_args[ $this->preview_nav_menu_instance_number ] = $hashed_args;
return $args;
}
/**
- * Prepare wp_nav_menu() calls for partial refresh. Wraps output in container for refreshing.
+ * Prepares wp_nav_menu() calls for partial refresh.
+ *
+ * Injects attributes into container element.
*
* @since 4.3.0
* @access public
@@ -903,29 +933,29 @@ final class WP_Customize_Nav_Menus {
* @return null
*/
public function filter_wp_nav_menu( $nav_menu_content, $args ) {
- if ( ! empty( $args->can_partial_refresh ) && ! empty( $args->instance_number ) ) {
- $nav_menu_content = preg_replace(
- '/(?<=class=")/',
- sprintf( 'partial-refreshable-nav-menu partial-refreshable-nav-menu-%1$d ', $args->instance_number ),
- $nav_menu_content,
- 1 // Only update the class on the first element found, the menu container.
- );
+ if ( ! empty( $args->customize_preview_nav_menus_args ) ) {
+ $attributes = sprintf( ' data-customize-partial-id="%s"', esc_attr( 'nav_menu_instance[' . $args->customize_preview_nav_menus_args['args_hmac'] . ']' ) );
+ $attributes .= ' data-customize-partial-type="nav_menu_instance"';
+ $attributes .= sprintf( ' data-customize-partial-placement-context="%s"', esc_attr( wp_json_encode( $args->customize_preview_nav_menus_args ) ) );
+ $nav_menu_content = preg_replace( '#^(<\w+)#', '$1 ' . $attributes, $nav_menu_content, 1 );
}
return $nav_menu_content;
}
/**
- * Hash (hmac) the arguments with the nonce and secret auth key to ensure they
- * are not tampered with when submitted in the Ajax request.
+ * Hashes (hmac) the nav menu arguments to ensure they are not tampered with when
+ * submitted in the Ajax request.
+ *
+ * Note that the array is expected to be pre-sorted.
*
* @since 4.3.0
* @access public
*
* @param array $args The arguments to hash.
- * @return string
+ * @return string Hashed nav menu arguments.
*/
public function hash_nav_menu_args( $args ) {
- return wp_hash( wp_create_nonce( self::RENDER_AJAX_ACTION ) . serialize( $args ) );
+ return wp_hash( serialize( $args ) );
}
/**
@@ -935,32 +965,24 @@ final class WP_Customize_Nav_Menus {
* @access public
*/
public function customize_preview_enqueue_deps() {
- wp_enqueue_script( 'customize-preview-nav-menus' );
- wp_enqueue_style( 'customize-preview' );
+ if ( isset( $this->manager->selective_refresh ) ) {
+ $script = wp_scripts()->registered['customize-preview-nav-menus'];
+ $script->deps[] = 'customize-selective-refresh';
+ }
- add_action( 'wp_print_footer_scripts', array( $this, 'export_preview_data' ) );
+ wp_enqueue_script( 'customize-preview-nav-menus' ); // Note that we have overridden this.
+ wp_enqueue_style( 'customize-preview' );
}
/**
- * Export data from PHP to JS.
+ * Exports data from PHP to JS.
*
* @since 4.3.0
+ * @deprecated 4.5.0 Obsolete
* @access public
*/
public function export_preview_data() {
-
- // Why not wp_localize_script? Because we're not localizing, and it forces values into strings.
- $exports = array(
- 'renderQueryVar' => self::RENDER_QUERY_VAR,
- 'renderNonceValue' => wp_create_nonce( self::RENDER_AJAX_ACTION ),
- 'renderNoncePostKey' => self::RENDER_NONCE_POST_KEY,
- 'navMenuInstanceArgs' => $this->preview_nav_menu_instance_args,
- 'l10n' => array(
- 'editNavMenuItemTooltip' => __( 'Shift-click to edit this menu item.' ),
- ),
- );
-
- printf( '', wp_json_encode( $exports ) );
+ _deprecated_function( __METHOD__, '4.5.0' );
}
/**
@@ -970,49 +992,32 @@ final class WP_Customize_Nav_Menus {
* @access public
*
* @see wp_nav_menu()
+ *
+ * @param WP_Customize_Partial $partial Partial.
+ * @param array $nav_menu_args Nav menu args supplied as container context.
+ * @return string|false
*/
- public function render_menu() {
- if ( empty( $_POST[ self::RENDER_QUERY_VAR ] ) ) {
- return;
+ public function render_nav_menu_partial( $partial, $nav_menu_args ) {
+ unset( $partial );
+
+ if ( ! isset( $nav_menu_args['args_hmac'] ) ) {
+ // Error: missing_args_hmac.
+ return false;
}
- $this->manager->remove_preview_signature();
+ $nav_menu_args_hmac = $nav_menu_args['args_hmac'];
+ unset( $nav_menu_args['args_hmac'] );
- if ( empty( $_POST[ self::RENDER_NONCE_POST_KEY ] ) ) {
- wp_send_json_error( 'missing_nonce_param' );
+ ksort( $nav_menu_args );
+ if ( ! hash_equals( $this->hash_nav_menu_args( $nav_menu_args ), $nav_menu_args_hmac ) ) {
+ // Error: args_hmac_mismatch.
+ return false;
}
- if ( ! is_customize_preview() ) {
- wp_send_json_error( 'expected_customize_preview' );
- }
+ ob_start();
+ wp_nav_menu( $nav_menu_args );
+ $content = ob_get_clean();
- if ( ! check_ajax_referer( self::RENDER_AJAX_ACTION, self::RENDER_NONCE_POST_KEY, false ) ) {
- wp_send_json_error( 'nonce_check_fail' );
- }
-
- if ( ! current_user_can( 'edit_theme_options' ) ) {
- wp_send_json_error( 'unauthorized' );
- }
-
- if ( ! isset( $_POST['wp_nav_menu_args'] ) ) {
- wp_send_json_error( 'missing_param' );
- }
-
- if ( ! isset( $_POST['wp_nav_menu_args_hash'] ) ) {
- wp_send_json_error( 'missing_param' );
- }
-
- $wp_nav_menu_args = json_decode( wp_unslash( $_POST['wp_nav_menu_args'] ), true );
- if ( ! is_array( $wp_nav_menu_args ) ) {
- wp_send_json_error( 'wp_nav_menu_args_not_array' );
- }
-
- $wp_nav_menu_args_hash = sanitize_text_field( wp_unslash( $_POST['wp_nav_menu_args_hash'] ) );
- if ( ! hash_equals( $this->hash_nav_menu_args( $wp_nav_menu_args ), $wp_nav_menu_args_hash ) ) {
- wp_send_json_error( 'wp_nav_menu_args_hash_mismatch' );
- }
-
- $wp_nav_menu_args['echo'] = false;
- wp_send_json_success( wp_nav_menu( $wp_nav_menu_args ) );
+ return $content;
}
}
diff --git a/wp-includes/class-wp-customize-widgets.php b/wp-includes/class-wp-customize-widgets.php
index 5a0e62b62a..28eaf1283a 100644
--- a/wp-includes/class-wp-customize-widgets.php
+++ b/wp-includes/class-wp-customize-widgets.php
@@ -100,6 +100,10 @@ final class WP_Customize_Widgets {
add_action( 'dynamic_sidebar', array( $this, 'tally_rendered_widgets' ) );
add_filter( 'is_active_sidebar', array( $this, 'tally_sidebars_via_is_active_sidebar_calls' ), 10, 2 );
add_filter( 'dynamic_sidebar_has_widgets', array( $this, 'tally_sidebars_via_dynamic_sidebar_calls' ), 10, 2 );
+
+ // Selective Refresh.
+ add_filter( 'customize_dynamic_partial_args', array( $this, 'customize_dynamic_partial_args' ), 10, 2 );
+ add_action( 'customize_preview_init', array( $this, 'selective_refresh_init' ) );
}
/**
@@ -682,6 +686,7 @@ final class WP_Customize_Widgets {
'widgetReorderNav' => $widget_reorder_nav_tpl,
'moveWidgetArea' => $move_widget_area_tpl,
),
+ 'selectiveRefresh' => isset( $this->manager->selective_refresh ),
);
foreach ( $settings['registeredWidgets'] as &$registered_widget ) {
@@ -762,7 +767,7 @@ final class WP_Customize_Widgets {
$args = array(
'type' => 'option',
'capability' => 'edit_theme_options',
- 'transport' => 'refresh',
+ 'transport' => isset( $this->manager->selective_refresh ) ? 'postMessage' : 'refresh',
'default' => array(),
);
@@ -884,7 +889,7 @@ final class WP_Customize_Widgets {
'multi_number' => ( $args['_add'] === 'multi' ) ? $args['_multi_num'] : false,
'is_disabled' => $is_disabled,
'id_base' => $id_base,
- 'transport' => 'refresh',
+ 'transport' => isset( $this->manager->selective_refresh ) ? 'postMessage' : 'refresh',
'width' => $wp_registered_widget_controls[$widget['id']]['width'],
'height' => $wp_registered_widget_controls[$widget['id']]['height'],
'is_wide' => $this->is_wide_widget( $widget['id'] ),
@@ -1061,8 +1066,9 @@ final class WP_Customize_Widgets {
'registeredSidebars' => array_values( $wp_registered_sidebars ),
'registeredWidgets' => $wp_registered_widgets,
'l10n' => array(
- 'widgetTooltip' => __( 'Shift-click to edit this widget.' ),
+ 'widgetTooltip' => __( 'Shift-click to edit this widget.' ),
),
+ 'selectiveRefresh' => isset( $this->manager->selective_refresh ),
);
foreach ( $settings['registeredWidgets'] as &$registered_widget ) {
unset( $registered_widget['callback'] ); // may not be JSON-serializeable
@@ -1459,9 +1465,325 @@ final class WP_Customize_Widgets {
wp_send_json_success( compact( 'form', 'instance' ) );
}
- /***************************************************************************
- * Option Update Capturing
- ***************************************************************************/
+ /*
+ * Selective Refresh Methods
+ */
+
+ /**
+ * Filter args for dynamic widget partials.
+ *
+ * @since 4.5.0
+ *
+ * @param array|false $partial_args Partial args.
+ * @param string $partial_id Partial ID.
+ * @return array Partial args
+ */
+ public function customize_dynamic_partial_args( $partial_args, $partial_id ) {
+
+ if ( preg_match( '/^widget\[.+\]$/', $partial_id ) ) {
+ if ( false === $partial_args ) {
+ $partial_args = array();
+ }
+ $partial_args = array_merge(
+ $partial_args,
+ array(
+ 'type' => 'widget',
+ 'render_callback' => array( $this, 'render_widget_partial' ),
+ 'container_inclusive' => true,
+ )
+ );
+ }
+
+ return $partial_args;
+ }
+
+ /**
+ * Add hooks for selective refresh.
+ *
+ * @since 4.5.0
+ * @access public
+ */
+ public function selective_refresh_init() {
+ if ( ! isset( $this->manager->selective_refresh ) ) {
+ return;
+ }
+
+ add_action( 'wp_enqueue_scripts', array( $this, 'customize_preview_enqueue_deps' ) );
+ add_filter( 'dynamic_sidebar_params', array( $this, 'filter_dynamic_sidebar_params' ) );
+ add_filter( 'wp_kses_allowed_html', array( $this, 'filter_wp_kses_allowed_data_attributes' ) );
+ add_action( 'dynamic_sidebar_before', array( $this, 'start_dynamic_sidebar' ) );
+ add_action( 'dynamic_sidebar_after', array( $this, 'end_dynamic_sidebar' ) );
+ }
+
+ /**
+ * Enqueue scripts for the Customizer preview.
+ *
+ * @since 4.5.0
+ * @access public
+ */
+ public function customize_preview_enqueue_deps() {
+ if ( isset( $this->manager->selective_refresh ) ) {
+ $script = wp_scripts()->registered['customize-preview-widgets'];
+ $script->deps[] = 'customize-selective-refresh';
+ }
+
+ wp_enqueue_script( 'customize-preview-widgets' );
+ wp_enqueue_style( 'customize-preview' );
+ }
+
+ /**
+ * Inject selective refresh data attributes into widget container elements.
+ *
+ * @param array $params {
+ * Dynamic sidebar params.
+ *
+ * @type array $args Sidebar args.
+ * @type array $widget_args Widget args.
+ * }
+ * @see WP_Customize_Nav_Menus_Partial_Refresh::filter_wp_nav_menu_args()
+ *
+ * @return array Params.
+ */
+ public function filter_dynamic_sidebar_params( $params ) {
+ $sidebar_args = array_merge(
+ array(
+ 'before_widget' => '',
+ 'after_widget' => '',
+ ),
+ $params[0]
+ );
+
+ // Skip widgets not in a registered sidebar or ones which lack a proper wrapper element to attach the data-* attributes to.
+ $matches = array();
+ $is_valid = (
+ isset( $sidebar_args['id'] )
+ &&
+ is_registered_sidebar( $sidebar_args['id'] )
+ &&
+ ( isset( $this->current_dynamic_sidebar_id_stack[0] ) && $this->current_dynamic_sidebar_id_stack[0] === $sidebar_args['id'] )
+ &&
+ preg_match( '#^<(?P
\w+)#', $sidebar_args['before_widget'], $matches )
+ );
+ if ( ! $is_valid ) {
+ return $params;
+ }
+ $this->before_widget_tags_seen[ $matches['tag_name'] ] = true;
+
+ $context = array(
+ 'sidebar_id' => $sidebar_args['id'],
+ );
+ if ( isset( $this->context_sidebar_instance_number ) ) {
+ $context['sidebar_instance_number'] = $this->context_sidebar_instance_number;
+ } else if ( isset( $sidebar_args['id'] ) && isset( $this->sidebar_instance_count[ $sidebar_args['id'] ] ) ) {
+ $context['sidebar_instance_number'] = $this->sidebar_instance_count[ $sidebar_args['id'] ];
+ }
+
+ $attributes = sprintf( ' data-customize-partial-id="%s"', esc_attr( 'widget[' . $sidebar_args['widget_id'] . ']' ) );
+ $attributes .= ' data-customize-partial-type="widget"';
+ $attributes .= sprintf( ' data-customize-partial-placement-context="%s"', esc_attr( wp_json_encode( $context ) ) );
+ $attributes .= sprintf( ' data-customize-widget-id="%s"', esc_attr( $sidebar_args['widget_id'] ) );
+ $sidebar_args['before_widget'] = preg_replace( '#^(<\w+)#', '$1 ' . $attributes, $sidebar_args['before_widget'] );
+
+ $params[0] = $sidebar_args;
+ return $params;
+ }
+
+ /**
+ * List of the tag names seen for before_widget strings.
+ *
+ * This is used in the filter_wp_kses_allowed_html filter to ensure that the
+ * data-* attributes can be whitelisted.
+ *
+ * @since 4.5.0
+ * @access private
+ * @var array
+ */
+ protected $before_widget_tags_seen = array();
+
+ /**
+ * Ensure that the HTML data-* attributes for selective refresh are allowed by kses.
+ *
+ * This is needed in case the $before_widget is run through wp_kses() when printed.
+ *
+ * @since 4.5.0
+ * @access public
+ *
+ * @param array $allowed_html Allowed HTML.
+ * @return array Allowed HTML.
+ */
+ public function filter_wp_kses_allowed_data_attributes( $allowed_html ) {
+ foreach ( array_keys( $this->before_widget_tags_seen ) as $tag_name ) {
+ if ( ! isset( $allowed_html[ $tag_name ] ) ) {
+ $allowed_html[ $tag_name ] = array();
+ }
+ $allowed_html[ $tag_name ] = array_merge(
+ $allowed_html[ $tag_name ],
+ array_fill_keys( array(
+ 'data-customize-partial-id',
+ 'data-customize-partial-type',
+ 'data-customize-partial-placement-context',
+ 'data-customize-partial-widget-id',
+ 'data-customize-partial-options',
+ ), true )
+ );
+ }
+ return $allowed_html;
+ }
+
+ /**
+ * Keep track of the number of times that dynamic_sidebar() was called for a given sidebar index.
+ *
+ * This helps facilitate the uncommon scenario where a single sidebar is rendered multiple times on a template.
+ *
+ * @since 4.5.0
+ * @access private
+ * @var array
+ */
+ protected $sidebar_instance_count = array();
+
+ /**
+ * The current request's sidebar_instance_number context.
+ *
+ * @since 4.5.0
+ * @access private
+ * @var int
+ */
+ protected $context_sidebar_instance_number;
+
+ /**
+ * Current sidebar ID being rendered.
+ *
+ * @since 4.5.0
+ * @access private
+ * @var array
+ */
+ protected $current_dynamic_sidebar_id_stack = array();
+
+ /**
+ * Start keeping track of the current sidebar being rendered.
+ *
+ * Insert marker before widgets are rendered in a dynamic sidebar.
+ *
+ * @since 4.5.0
+ *
+ * @param int|string $index Index, name, or ID of the dynamic sidebar.
+ */
+ public function start_dynamic_sidebar( $index ) {
+ array_unshift( $this->current_dynamic_sidebar_id_stack, $index );
+ if ( ! isset( $this->sidebar_instance_count[ $index ] ) ) {
+ $this->sidebar_instance_count[ $index ] = 0;
+ }
+ $this->sidebar_instance_count[ $index ] += 1;
+ if ( ! $this->manager->selective_refresh->is_render_partials_request() ) {
+ printf( "\n\n", esc_html( $index ), intval( $this->sidebar_instance_count[ $index ] ) );
+ }
+ }
+
+ /**
+ * Finish keeping track of the current sidebar being rendered.
+ *
+ * Insert marker after widgets are rendered in a dynamic sidebar.
+ *
+ * @since 4.5.0
+ *
+ * @param int|string $index Index, name, or ID of the dynamic sidebar.
+ */
+ public function end_dynamic_sidebar( $index ) {
+ if ( ! $this->manager->selective_refresh->is_render_partials_request() ) {
+ printf( "\n\n", esc_html( $index ), intval( $this->sidebar_instance_count[ $index ] ) );
+ }
+ }
+
+ /**
+ * Current sidebar being rendered.
+ *
+ * @since 4.5.0
+ * @access private
+ * @var string
+ */
+ protected $rendering_widget_id;
+
+ /**
+ * Current widget being rendered.
+ *
+ * @since 4.5.0
+ * @access private
+ * @var string
+ */
+ protected $rendering_sidebar_id;
+
+ /**
+ * Filter sidebars_widgets to ensure the currently-rendered widget is the only widget in the current sidebar.
+ *
+ * @since 4.5.0
+ * @access private
+ *
+ * @param array $sidebars_widgets Sidebars widgets.
+ * @return array Sidebars widgets.
+ */
+ public function filter_sidebars_widgets_for_rendering_widget( $sidebars_widgets ) {
+ $sidebars_widgets[ $this->rendering_sidebar_id ] = array( $this->rendering_widget_id );
+ return $sidebars_widgets;
+ }
+
+ /**
+ * Render a specific widget using the supplied sidebar arguments.
+ *
+ * @since 4.5.0
+ * @access public
+ *
+ * @see dynamic_sidebar()
+ *
+ * @param WP_Customize_Partial $partial Partial.
+ * @param array $context {
+ * Sidebar args supplied as container context.
+ *
+ * @type string $sidebar_id ID for sidebar for widget to render into.
+ * @type int [$sidebar_instance_number] Disambiguating instance number.
+ * }
+ * @return string|false
+ */
+ public function render_widget_partial( $partial, $context ) {
+ $id_data = $partial->id_data();
+ $widget_id = array_shift( $id_data['keys'] );
+
+ if ( ! is_array( $context )
+ || empty( $context['sidebar_id'] )
+ || ! is_registered_sidebar( $context['sidebar_id'] )
+ ) {
+ return false;
+ }
+
+ $this->rendering_sidebar_id = $context['sidebar_id'];
+
+ if ( isset( $context['sidebar_instance_number'] ) ) {
+ $this->context_sidebar_instance_number = intval( $context['sidebar_instance_number'] );
+ }
+
+ // Filter sidebars_widgets so that only the queried widget is in the sidebar.
+ $this->rendering_widget_id = $widget_id;
+
+ $filter_callback = array( $this, 'filter_sidebars_widgets_for_rendering_widget' );
+ add_filter( 'sidebars_widgets', $filter_callback, 1000 );
+
+ // Render the widget.
+ ob_start();
+ dynamic_sidebar( $this->rendering_sidebar_id = $context['sidebar_id'] );
+ $container = ob_get_clean();
+
+ // Reset variables for next partial render.
+ remove_filter( 'sidebars_widgets', $filter_callback, 1000 );
+
+ $this->context_sidebar_instance_number = null;
+ $this->rendering_sidebar_id = null;
+ $this->rendering_widget_id = null;
+
+ return $container;
+ }
+
+ //
+ // Option Update Capturing
+ //
/**
* List of captured widget option updates.
@@ -1611,7 +1933,7 @@ final class WP_Customize_Widgets {
return;
}
- remove_filter( 'pre_update_option', array( $this, 'capture_filter_pre_update_option' ), 10, 3 );
+ remove_filter( 'pre_update_option', array( $this, 'capture_filter_pre_update_option' ), 10 );
foreach ( array_keys( $this->_captured_options ) as $option_name ) {
remove_filter( "pre_option_{$option_name}", array( $this, 'capture_filter_pre_get_option' ) );
diff --git a/wp-includes/css/customize-preview.css b/wp-includes/css/customize-preview.css
index bc4a6fe903..443fbd0c5e 100644
--- a/wp-includes/css/customize-preview.css
+++ b/wp-includes/css/customize-preview.css
@@ -4,3 +4,18 @@
transition: opacity 0.25s;
cursor: progress;
}
+
+/* Override highlight when refreshing */
+.customize-partial-refreshing.widget-customizer-highlighted-widget {
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+
+.customize-render-content-error {
+ outline: solid 1px red;
+}
+.customize-render-content-error-message {
+ display: block;
+ padding: 1em;
+ background-color: #FFCCCC;
+}
diff --git a/wp-includes/css/customize-preview.min.css b/wp-includes/css/customize-preview.min.css
index dadf3f5216..02648f0737 100644
--- a/wp-includes/css/customize-preview.min.css
+++ b/wp-includes/css/customize-preview.min.css
@@ -1 +1 @@
-.customize-partial-refreshing{opacity:.25;-webkit-transition:opacity .25s;transition:opacity .25s;cursor:progress}
\ No newline at end of file
+.customize-partial-refreshing{opacity:.25;-webkit-transition:opacity .25s;transition:opacity .25s;cursor:progress}.customize-partial-refreshing.widget-customizer-highlighted-widget{-webkit-box-shadow:none;box-shadow:none}.customize-render-content-error{outline:red solid 1px}.customize-render-content-error-message{display:block;padding:1em;background-color:#FCC}
\ No newline at end of file
diff --git a/wp-includes/customize/class-wp-customize-nav-menu-item-setting.php b/wp-includes/customize/class-wp-customize-nav-menu-item-setting.php
index 073423ecbe..b89b56cbc0 100644
--- a/wp-includes/customize/class-wp-customize-nav-menu-item-setting.php
+++ b/wp-includes/customize/class-wp-customize-nav-menu-item-setting.php
@@ -67,10 +67,11 @@ class WP_Customize_Nav_Menu_Item_Setting extends WP_Customize_Setting {
* Default transport.
*
* @since 4.3.0
+ * @since 4.5.0 Default changed to 'refresh'
* @access public
* @var string
*/
- public $transport = 'postMessage';
+ public $transport = 'refresh';
/**
* The post ID represented by this setting instance. This is the db_id.
diff --git a/wp-includes/customize/class-wp-customize-partial.php b/wp-includes/customize/class-wp-customize-partial.php
new file mode 100644
index 0000000000..f6e5e44565
--- /dev/null
+++ b/wp-includes/customize/class-wp-customize-partial.php
@@ -0,0 +1,288 @@
+$key = $args[ $key ];
+ }
+ }
+
+ $this->component = $component;
+ $this->id = $id;
+ $this->id_data['keys'] = preg_split( '/\[/', str_replace( ']', '', $this->id ) );
+ $this->id_data['base'] = array_shift( $this->id_data['keys'] );
+
+ if ( empty( $this->render_callback ) ) {
+ $this->render_callback = array( $this, 'render_callback' );
+ }
+
+ // Process settings.
+ if ( empty( $this->settings ) ) {
+ $this->settings = array( $id );
+ } else if ( is_string( $this->settings ) ) {
+ $this->settings = array( $this->settings );
+ }
+
+ if ( empty( $this->primary_setting ) ) {
+ $this->primary_setting = current( $this->settings );
+ }
+ }
+
+ /**
+ * Retrieves parsed ID data for multidimensional setting.
+ *
+ * @since 4.5.0
+ * @access public
+ *
+ * @return array {
+ * ID data for multidimensional partial.
+ *
+ * @type string $base ID base.
+ * @type array $keys Keys for multidimensional array.
+ * }
+ */
+ final public function id_data() {
+ return $this->id_data;
+ }
+
+ /**
+ * Renders the template partial involving the associated settings.
+ *
+ * @since 4.5.0
+ * @access public
+ *
+ * @param array $container_context Optional. Array of context data associated with the target container (placement).
+ * Default empty array.
+ * @return string|array|false The rendered partial as a string, raw data array (for client-side JS template),
+ * or false if no render applied.
+ */
+ final public function render( $container_context = array() ) {
+ $partial = $this;
+ $rendered = false;
+
+ if ( ! empty( $this->render_callback ) ) {
+ ob_start();
+ $return_render = call_user_func( $this->render_callback, $this, $container_context );
+ $ob_render = ob_get_clean();
+
+ if ( null !== $return_render && '' !== $ob_render ) {
+ _doing_it_wrong( __FUNCTION__, __( 'Partial render must echo the content or return the content string (or array), but not both.' ), '4.5.0' );
+ }
+
+ /*
+ * Note that the string return takes precedence because the $ob_render may just\
+ * include PHP warnings or notices.
+ */
+ $rendered = null !== $return_render ? $return_render : $ob_render;
+ }
+
+ /**
+ * Filters partial rendering.
+ *
+ * @since 4.5.0
+ *
+ * @param string|array|false $rendered The partial value. Default false.
+ * @param WP_Customize_Partial $partial WP_Customize_Setting instance.
+ * @param array $container_context Optional array of context data associated with
+ * the target container.
+ */
+ $rendered = apply_filters( 'customize_partial_render', $rendered, $partial, $container_context );
+
+ /**
+ * Filters partial rendering for a specific partial.
+ *
+ * The dynamic portion of the hook name, `$partial->ID` refers to the partial ID.
+ *
+ * @since 4.5.0
+ *
+ * @param string|array|false $rendered The partial value. Default false.
+ * @param WP_Customize_Partial $partial WP_Customize_Setting instance.
+ * @param array $container_context Optional array of context data associated with
+ * the target container.
+ */
+ $rendered = apply_filters( "customize_partial_render_{$partial->id}", $rendered, $partial, $container_context );
+
+ return $rendered;
+ }
+
+ /**
+ * Default callback used when invoking WP_Customize_Control::render().
+ *
+ * Note that this method may echo the partial *or* return the partial as
+ * a string or array, but not both. Output buffering is performed when this
+ * is called. Subclasses can override this with their specific logic, or they
+ * may provide an 'render_callback' argument to the constructor.
+ *
+ * This method may return an HTML string for straight DOM injection, or it
+ * may return an array for supporting Partial JS subclasses to render by
+ * applying to client-side templating.
+ *
+ * @since 4.5.0
+ * @access public
+ *
+ * @return string|array|false
+ */
+ public function render_callback() {
+ return false;
+ }
+
+ /**
+ * Retrieves the data to export to the client via JSON.
+ *
+ * @since 4.5.0
+ * @access public
+ *
+ * @return array Array of parameters passed to the JavaScript.
+ */
+ public function json() {
+ $exports = array(
+ 'settings' => $this->settings,
+ 'primarySetting' => $this->primary_setting,
+ 'selector' => $this->selector,
+ 'type' => $this->type,
+ 'fallbackRefresh' => $this->fallback_refresh,
+ 'containerInclusive' => $this->container_inclusive,
+ );
+ return $exports;
+ }
+}
diff --git a/wp-includes/customize/class-wp-customize-selective-refresh.php b/wp-includes/customize/class-wp-customize-selective-refresh.php
new file mode 100644
index 0000000000..046b878de7
--- /dev/null
+++ b/wp-includes/customize/class-wp-customize-selective-refresh.php
@@ -0,0 +1,437 @@
+manager = $manager;
+ require_once( ABSPATH . WPINC . '/customize/class-wp-customize-partial.php' );
+
+ add_action( 'customize_preview_init', array( $this, 'init_preview' ) );
+ }
+
+ /**
+ * Retrieves the registered partials.
+ *
+ * @since 4.5.0
+ * @access public
+ *
+ * @return array Partials.
+ */
+ public function partials() {
+ return $this->partials;
+ }
+
+ /**
+ * Adds a partial.
+ *
+ * @since 4.5.0
+ * @access public
+ *
+ * @param WP_Customize_Partial|string $id Customize Partial object, or Panel ID.
+ * @param array $args Optional. Partial arguments. Default empty array.
+ * @return WP_Customize_Partial The instance of the panel that was added.
+ */
+ public function add_partial( $id, $args = array() ) {
+ if ( $id instanceof WP_Customize_Partial ) {
+ $partial = $id;
+ } else {
+ $class = 'WP_Customize_Partial';
+
+ /** This filter (will be) documented in wp-includes/class-wp-customize-manager.php */
+ $args = apply_filters( 'customize_dynamic_partial_args', $args, $id );
+
+ /** This filter (will be) documented in wp-includes/class-wp-customize-manager.php */
+ $class = apply_filters( 'customize_dynamic_partial_class', $class, $id, $args );
+
+ $partial = new $class( $this, $id, $args );
+ }
+
+ $this->partials[ $partial->id ] = $partial;
+ return $partial;
+ }
+
+ /**
+ * Retrieves a partial.
+ *
+ * @since 4.5.0
+ * @access public
+ *
+ * @param string $id Customize Partial ID.
+ * @return WP_Customize_Partial|null The partial, if set. Otherwise null.
+ */
+ public function get_partial( $id ) {
+ if ( isset( $this->partials[ $id ] ) ) {
+ return $this->partials[ $id ];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Removes a partial.
+ *
+ * @since 4.5.0
+ * @access public
+ *
+ * @param string $id Customize Partial ID.
+ */
+ public function remove_partial( $id ) {
+ unset( $this->partials[ $id ] );
+ }
+
+ /**
+ * Initializes the Customizer preview.
+ *
+ * @since 4.5.0
+ * @access public
+ */
+ public function init_preview() {
+ add_action( 'template_redirect', array( $this, 'handle_render_partials_request' ) );
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_preview_scripts' ) );
+ }
+
+ /**
+ * Enqueues preview scripts.
+ *
+ * @since 4.5.0
+ * @access public
+ */
+ public function enqueue_preview_scripts() {
+ wp_enqueue_script( 'customize-selective-refresh' );
+ add_action( 'wp_footer', array( $this, 'export_preview_data' ), 1000 );
+ }
+
+ /**
+ * Exports data in preview after it has finished rendering so that partials can be added at runtime.
+ *
+ * @since 4.5.0
+ * @access public
+ */
+ public function export_preview_data() {
+ $partials = array();
+
+ foreach ( $this->partials() as $partial ) {
+ $partials[ $partial->id ] = $partial->json();
+ }
+
+ $exports = array(
+ 'partials' => $partials,
+ 'renderQueryVar' => self::RENDER_QUERY_VAR,
+ 'l10n' => array(
+ 'shiftClickToEdit' => __( 'Shift-click to edit this element.' ),
+ /* translators: %s: message from JS error */
+ 'errorMessageTpl' => __( 'Script error: %s' ),
+ /* translators: %s: document.write() */
+ 'badDocumentWrite' => sprintf( __( '%s is forbidden' ), 'document.write()' ),
+ ),
+ );
+
+ // Export data to JS.
+ echo sprintf( '', wp_json_encode( $exports ) );
+ }
+
+ /**
+ * Registers dynamically-created partials.
+ *
+ * @since 4.5.0
+ * @access public
+ *
+ * @see WP_Customize_Manager::add_dynamic_settings()
+ *
+ * @param array $partial_ids The partial ID to add.
+ * @return array Added WP_Customize_Partial instances.
+ */
+ public function add_dynamic_partials( $partial_ids ) {
+ $new_partials = array();
+
+ foreach ( $partial_ids as $partial_id ) {
+
+ // Skip partials already created.
+ $partial = $this->get_partial( $partial_id );
+ if ( $partial ) {
+ continue;
+ }
+
+ $partial_args = false;
+ $partial_class = 'WP_Customize_Partial';
+
+ /**
+ * Filters a dynamic partial's constructor arguments.
+ *
+ * For a dynamic partial to be registered, this filter must be employed
+ * to override the default false value with an array of args to pass to
+ * the WP_Customize_Partial constructor.
+ *
+ * @since 4.5.0
+ *
+ * @param false|array $partial_args The arguments to the WP_Customize_Partial constructor.
+ * @param string $partial_id ID for dynamic partial.
+ */
+ $partial_args = apply_filters( 'customize_dynamic_partial_args', $partial_args, $partial_id );
+ if ( false === $partial_args ) {
+ continue;
+ }
+
+ /**
+ * Filters the class used to construct partials.
+ *
+ * Allow non-statically created partials to be constructed with custom WP_Customize_Partial subclass.
+ *
+ * @since 4.5.0
+ *
+ * @param string $partial_class WP_Customize_Partial or a subclass.
+ * @param string $partial_id ID for dynamic partial.
+ * @param array $partial_args The arguments to the WP_Customize_Partial constructor.
+ */
+ $partial_class = apply_filters( 'customize_dynamic_partial_class', $partial_class, $partial_id, $partial_args );
+
+ $partial = new $partial_class( $this, $partial_id, $partial_args );
+
+ $this->add_partial( $partial );
+ $new_partials[] = $partial;
+ }
+ return $new_partials;
+ }
+
+ /**
+ * Checks whether the request is for rendering partials.
+ *
+ * Note that this will not consider whether the request is authorized or valid,
+ * just that essentially the route is a match.
+ *
+ * @since 4.5.0
+ * @access public
+ *
+ * @return bool Whether the request is for rendering partials.
+ */
+ public function is_render_partials_request() {
+ return ! empty( $_POST[ self::RENDER_QUERY_VAR ] );
+ }
+
+ /**
+ * Handles PHP errors triggered during rendering the partials.
+ *
+ * These errors will be relayed back to the client in the Ajax response.
+ *
+ * @since 4.5.0
+ * @access private
+ *
+ * @param int $errno Error number.
+ * @param string $errstr Error string.
+ * @param string $errfile Error file.
+ * @param string $errline Error line.
+ * @return true Always true.
+ */
+ public function handle_error( $errno, $errstr, $errfile = null, $errline = null ) {
+ $this->triggered_errors[] = array(
+ 'partial' => $this->current_partial_id,
+ 'error_number' => $errno,
+ 'error_string' => $errstr,
+ 'error_file' => $errfile,
+ 'error_line' => $errline,
+ );
+ return true;
+ }
+
+ /**
+ * Handles the Ajax request to return the rendered partials for the requested placements.
+ *
+ * @since 4.5.0
+ * @access public
+ */
+ public function handle_render_partials_request() {
+ if ( ! $this->is_render_partials_request() ) {
+ return;
+ }
+
+ $this->manager->remove_preview_signature();
+
+ /*
+ * Note that is_customize_preview() returning true will entail that the
+ * user passed the 'customize' capability check and the nonce check, since
+ * WP_Customize_Manager::setup_theme() is where the previewing flag is set.
+ */
+ if ( ! is_customize_preview() ) {
+ status_header( 403 );
+ wp_send_json_error( 'expected_customize_preview' );
+ } else if ( ! isset( $_POST['partials'] ) ) {
+ status_header( 400 );
+ wp_send_json_error( 'missing_partials' );
+ }
+
+ $partials = json_decode( wp_unslash( $_POST['partials'] ), true );
+
+ if ( ! is_array( $partials ) ) {
+ wp_send_json_error( 'malformed_partials' );
+ }
+
+ $this->add_dynamic_partials( array_keys( $partials ) );
+
+ /**
+ * Fires immediately before partials are rendered.
+ *
+ * Plugins may do things like call wp_enqueue_scripts() and gather a list of the scripts
+ * and styles which may get enqueued in the response.
+ *
+ * @since 4.5.0
+ *
+ * @param WP_Customize_Selective_Refresh $this Selective refresh component.
+ * @param array $partials Placements' context data for the partials rendered in the request.
+ * The array is keyed by partial ID, with each item being an array of
+ * the placements' context data.
+ */
+ do_action( 'customize_render_partials_before', $this, $partials );
+
+ set_error_handler( array( $this, 'handle_error' ), error_reporting() );
+
+ $contents = array();
+
+ foreach ( $partials as $partial_id => $container_contexts ) {
+ $this->current_partial_id = $partial_id;
+
+ if ( ! is_array( $container_contexts ) ) {
+ wp_send_json_error( 'malformed_container_contexts' );
+ }
+
+ $partial = $this->get_partial( $partial_id );
+
+ if ( ! $partial ) {
+ $contents[ $partial_id ] = null;
+ continue;
+ }
+
+ $contents[ $partial_id ] = array();
+
+ // @todo The array should include not only the contents, but also whether the container is included?
+ if ( empty( $container_contexts ) ) {
+ // Since there are no container contexts, render just once.
+ $contents[ $partial_id ][] = $partial->render( null );
+ } else {
+ foreach ( $container_contexts as $container_context ) {
+ $contents[ $partial_id ][] = $partial->render( $container_context );
+ }
+ }
+ }
+ $this->current_partial_id = null;
+
+ restore_error_handler();
+
+ /**
+ * Fires immediately after partials are rendered.
+ *
+ * Plugins may do things like call wp_footer() to scrape scripts output and return them
+ * via the {@see 'customize_render_partials_response'} filter.
+ *
+ * @since 4.5.0
+ *
+ * @param WP_Customize_Selective_Refresh $this Selective refresh component.
+ * @param array $partials Placements' context data for the partials rendered in the request.
+ * The array is keyed by partial ID, with each item being an array of
+ * the placements' context data.
+ */
+ do_action( 'customize_render_partials_after', $this, $partials );
+
+ $response = array(
+ 'contents' => $contents,
+ );
+
+ if ( defined( 'WP_DEBUG_DISPLAY' ) && WP_DEBUG_DISPLAY ) {
+ $response['errors'] = $this->triggered_errors;
+ }
+
+ /**
+ * Filters the response from rendering the partials.
+ *
+ * Plugins may use this filter to inject `$scripts` and `$styles`, which are dependencies
+ * for the partials being rendered. The response data will be available to the client via
+ * the `render-partials-response` JS event, so the client can then inject the scripts and
+ * styles into the DOM if they have not already been enqueued there.
+ *
+ * If plugins do this, they'll need to take care for any scripts that do `document.write()`
+ * and make sure that these are not injected, or else to override the function to no-op,
+ * or else the page will be destroyed.
+ *
+ * Plugins should be aware that `$scripts` and `$styles` may eventually be included by
+ * default in the response.
+ *
+ * @since 4.5.0
+ *
+ * @param array $response {
+ * Response.
+ *
+ * @type array $contents Associative array mapping a partial ID its corresponding array of contents
+ * for the containers requested.
+ * @type array $errors List of errors triggered during rendering of partials, if `WP_DEBUG_DISPLAY`
+ * is enabled.
+ * }
+ * @param WP_Customize_Selective_Refresh $this Selective refresh component.
+ * @param array $partials Placements' context data for the partials rendered in the request.
+ * The array is keyed by partial ID, with each item being an array of
+ * the placements' context data.
+ */
+ $response = apply_filters( 'customize_render_partials_response', $response, $this, $partials );
+
+ wp_send_json_success( $response );
+ }
+}
diff --git a/wp-includes/js/customize-preview-nav-menus.js b/wp-includes/js/customize-preview-nav-menus.js
index 9e8449402e..1ba3c87b6a 100644
--- a/wp-includes/js/customize-preview-nav-menus.js
+++ b/wp-includes/js/customize-preview-nav-menus.js
@@ -1,315 +1,217 @@
-/* global JSON, _wpCustomizePreviewNavMenusExports */
-
-( function( $, _, wp ) {
+wp.customize.navMenusPreview = wp.customize.MenusCustomizerPreview = ( function( $, _, wp, api ) {
'use strict';
- if ( ! wp || ! wp.customize ) { return; }
+ var self = {};
- var api = wp.customize,
- currentRefreshDebounced = {},
- refreshDebounceDelay = 200,
- settings = {},
- defaultSettings = {
- renderQueryVar: null,
- renderNonceValue: null,
- renderNoncePostKey: null,
- requestUri: '/',
- navMenuInstanceArgs: {},
- l10n: {}
- };
+ /**
+ * Initialize nav menus preview.
+ */
+ self.init = function() {
+ var self = this;
+
+ if ( api.selectiveRefresh ) {
+ self.watchNavMenuLocationChanges();
+ }
+
+ api.preview.bind( 'active', function() {
+ self.highlightControls();
+ } );
+ };
+
+ if ( api.selectiveRefresh ) {
- api.MenusCustomizerPreview = {
/**
- * Bootstrap functionality.
+ * Partial representing an invocation of wp_nav_menu().
+ *
+ * @class
+ * @augments wp.customize.selectiveRefresh.Partial
+ * @since 4.5.0
*/
- init : function() {
- var self = this, initializedSettings = {};
+ self.NavMenuInstancePartial = api.selectiveRefresh.Partial.extend({
- settings = _.extend( {}, defaultSettings );
- if ( 'undefined' !== typeof _wpCustomizePreviewNavMenusExports ) {
- _.extend( settings, _wpCustomizePreviewNavMenusExports );
- }
-
- api.each( function( setting, id ) {
- setting.id = id;
- initializedSettings[ setting.id ] = true;
- self.bindListener( setting );
- } );
-
- api.preview.bind( 'setting', function( args ) {
- var id, value, setting;
- args = args.slice();
- id = args.shift();
- value = args.shift();
-
- setting = api( id );
- if ( ! setting ) {
- // Currently customize-preview.js is not creating settings for dynamically-created settings in the pane, so we have to do it.
- setting = api.create( id, value ); // @todo This should be in core
+ /**
+ * Constructor.
+ *
+ * @since 4.5.0
+ * @param {string} id - Partial ID.
+ * @param {Object} options
+ * @param {Object} options.params
+ * @param {Object} options.params.navMenuArgs
+ * @param {string} options.params.navMenuArgs.args_hmac
+ * @param {string} [options.params.navMenuArgs.theme_location]
+ * @param {number} [options.params.navMenuArgs.menu]
+ * @param {object} [options.constructingContainerContext]
+ */
+ initialize: function( id, options ) {
+ var partial = this, matches, argsHmac;
+ matches = id.match( /^nav_menu_instance\[([0-9a-f]{32})]$/ );
+ if ( ! matches ) {
+ throw new Error( 'Illegal id for nav_menu_instance partial. The key corresponds with the args HMAC.' );
}
- if ( ! setting.id ) {
- // Currently customize-preview.js doesn't set the id property for each setting, like customize-controls.js does.
- setting.id = id;
+ argsHmac = matches[1];
+
+ options = options || {};
+ options.params = _.extend(
+ {
+ selector: '[data-customize-partial-id="' + id + '"]',
+ navMenuArgs: options.constructingContainerContext || {},
+ containerInclusive: true
+ },
+ options.params || {}
+ );
+ api.selectiveRefresh.Partial.prototype.initialize.call( partial, id, options );
+
+ if ( ! _.isObject( partial.params.navMenuArgs ) ) {
+ throw new Error( 'Missing navMenuArgs' );
+ }
+ if ( partial.params.navMenuArgs.args_hmac !== argsHmac ) {
+ throw new Error( 'args_hmac mismatch with id' );
+ }
+ },
+
+ /**
+ * Return whether the setting is related to this partial.
+ *
+ * @since 4.5.0
+ * @param {wp.customize.Value|string} setting - Object or ID.
+ * @param {number|object|false|null} newValue - New value, or null if the setting was just removed.
+ * @param {number|object|false|null} oldValue - Old value, or null if the setting was just added.
+ * @returns {boolean}
+ */
+ isRelatedSetting: function( setting, newValue, oldValue ) {
+ var partial = this, navMenuLocationSetting, navMenuId, isNavMenuItemSetting;
+ if ( _.isString( setting ) ) {
+ setting = api( setting );
}
- if ( ! initializedSettings[ setting.id ] ) {
- initializedSettings[ setting.id ] = true;
- if ( self.bindListener( setting ) ) {
- setting.callbacks.fireWith( setting, [ setting(), null ] );
+ /*
+ * Prevent nav_menu_item changes only containing type_label differences triggering a refresh.
+ * These settings in the preview do not include type_label property, and so if one of these
+ * nav_menu_item settings is dirty, after a refresh the nav menu instance would do a selective
+ * refresh immediately because the setting from the pane would have the type_label whereas
+ * the setting in the preview would not, thus triggering a change event. The following
+ * condition short-circuits this unnecessary selective refresh and also prevents an infinite
+ * loop in the case where a nav_menu_instance partial had done a fallback refresh.
+ * @todo Nav menu item settings should not include a type_label property to begin with.
+ */
+ isNavMenuItemSetting = /^nav_menu_item\[/.test( setting.id );
+ if ( isNavMenuItemSetting && _.isObject( newValue ) && _.isObject( oldValue ) ) {
+ delete newValue.type_label;
+ delete oldValue.type_label;
+ if ( _.isEqual( oldValue, newValue ) ) {
+ return false;
}
}
- } );
- self.highlightControls();
- },
+ if ( partial.params.navMenuArgs.theme_location ) {
+ if ( 'nav_menu_locations[' + partial.params.navMenuArgs.theme_location + ']' === setting.id ) {
+ return true;
+ }
+ navMenuLocationSetting = api( 'nav_menu_locations[' + partial.params.navMenuArgs.theme_location + ']' );
+ }
+
+ navMenuId = partial.params.navMenuArgs.menu;
+ if ( ! navMenuId && navMenuLocationSetting ) {
+ navMenuId = navMenuLocationSetting();
+ }
+
+ if ( ! navMenuId ) {
+ return false;
+ }
+ return (
+ ( 'nav_menu[' + navMenuId + ']' === setting.id ) ||
+ ( isNavMenuItemSetting && (
+ ( newValue && newValue.nav_menu_term_id === navMenuId ) ||
+ ( oldValue && oldValue.nav_menu_term_id === navMenuId )
+ ) )
+ );
+ },
+
+ /**
+ * Render content.
+ *
+ * @inheritdoc
+ * @param {wp.customize.selectiveRefresh.Placement} placement
+ */
+ renderContent: function( placement ) {
+ var partial = this, previousContainer = placement.container;
+ if ( api.selectiveRefresh.Partial.prototype.renderContent.call( partial, placement ) ) {
+
+ // Trigger deprecated event.
+ $( document ).trigger( 'customize-preview-menu-refreshed', [ {
+ instanceNumber: null, // @deprecated
+ wpNavArgs: placement.context, // @deprecated
+ wpNavMenuArgs: placement.context,
+ oldContainer: previousContainer,
+ newContainer: placement.container
+ } ] );
+ }
+ }
+ });
+
+ api.selectiveRefresh.partialConstructor.nav_menu_instance = self.NavMenuInstancePartial;
/**
+ * Watch for changes to nav_menu_locations[] settings.
*
- * @param {wp.customize.Value} setting
- * @returns {boolean} Whether the setting was bound.
+ * Refresh partials associated with the given nav_menu_locations[] setting,
+ * or request an entire preview refresh if there are no containers in the
+ * document for a partial associated with the theme location.
+ *
+ * @since 4.5.0
*/
- bindListener : function( setting ) {
- var matches, themeLocation;
-
- matches = setting.id.match( /^nav_menu\[(-?\d+)]$/ );
- if ( matches ) {
- setting.navMenuId = parseInt( matches[1], 10 );
- setting.bind( this.onChangeNavMenuSetting );
- return true;
- }
-
- matches = setting.id.match( /^nav_menu_item\[(-?\d+)]$/ );
- if ( matches ) {
- setting.navMenuItemId = parseInt( matches[1], 10 );
- setting.bind( this.onChangeNavMenuItemSetting );
- return true;
- }
-
- matches = setting.id.match( /^nav_menu_locations\[(.+?)]/ );
- if ( matches ) {
+ self.watchNavMenuLocationChanges = function() {
+ api.bind( 'change', function( setting ) {
+ var themeLocation, themeLocationPartialFound = false, matches = setting.id.match( /^nav_menu_locations\[(.+)]$/ );
+ if ( ! matches ) {
+ return;
+ }
themeLocation = matches[1];
- setting.bind( _.bind( function() {
- this.refreshMenuLocation( themeLocation );
- }, this ) );
- return true;
- }
+ api.selectiveRefresh.partial.each( function( partial ) {
+ if ( partial.extended( self.NavMenuInstancePartial ) && partial.params.navMenuArgs.theme_location === themeLocation ) {
+ partial.refresh();
+ themeLocationPartialFound = true;
+ }
+ } );
- return false;
- },
-
- /**
- * Handle changing of a nav_menu setting.
- *
- * @this {wp.customize.Setting}
- */
- onChangeNavMenuSetting : function() {
- var setting = this;
- if ( ! setting.navMenuId ) {
- throw new Error( 'Expected navMenuId property to be set.' );
- }
- api.MenusCustomizerPreview.refreshMenu( setting.navMenuId );
- },
-
- /**
- * Handle changing of a nav_menu_item setting.
- *
- * @this {wp.customize.Setting}
- * @param {object} to
- * @param {object} from
- */
- onChangeNavMenuItemSetting : function( to, from ) {
- if ( from && from.nav_menu_term_id && ( ! to || from.nav_menu_term_id !== to.nav_menu_term_id ) ) {
- api.MenusCustomizerPreview.refreshMenu( from.nav_menu_term_id );
- }
- if ( to && to.nav_menu_term_id ) {
- api.MenusCustomizerPreview.refreshMenu( to.nav_menu_term_id );
- }
- },
-
- /**
- * Update a given menu rendered in the preview.
- *
- * @param {int} menuId
- */
- refreshMenu : function( menuId ) {
- var assignedLocations = [];
-
- api.each(function( setting, id ) {
- var matches = id.match( /^nav_menu_locations\[(.+?)]/ );
- if ( matches && menuId === setting() ) {
- assignedLocations.push( matches[1] );
+ if ( ! themeLocationPartialFound ) {
+ api.selectiveRefresh.requestFullRefresh();
}
- });
+ } );
+ };
+ }
- _.each( settings.navMenuInstanceArgs, function( navMenuArgs, instanceNumber ) {
- if ( menuId === navMenuArgs.menu || -1 !== _.indexOf( assignedLocations, navMenuArgs.theme_location ) ) {
- this.refreshMenuInstanceDebounced( instanceNumber );
- }
- }, this );
- },
+ /**
+ * Connect nav menu items with their corresponding controls in the pane.
+ *
+ * Setup shift-click on nav menu items which are more granular than the nav menu partial itself.
+ * Also this applies even if a nav menu is not partial-refreshable.
+ *
+ * @since 4.5.0
+ */
+ self.highlightControls = function() {
+ var selector = '.menu-item';
- /**
- * Refresh the menu(s) associated with a given nav menu location.
- *
- * @param {string} location
- */
- refreshMenuLocation : function( location ) {
- var foundInstance = false;
- _.each( settings.navMenuInstanceArgs, function( navMenuArgs, instanceNumber ) {
- if ( location === navMenuArgs.theme_location ) {
- this.refreshMenuInstanceDebounced( instanceNumber );
- foundInstance = true;
- }
- }, this );
- if ( ! foundInstance ) {
- api.preview.send( 'refresh' );
- }
- },
-
- /**
- * Update a specific instance of a given menu on the page.
- *
- * @param {int} instanceNumber
- */
- refreshMenuInstance : function( instanceNumber ) {
- var data, menuId, customized, container, request, wpNavMenuArgs, instance, containerInstanceClassName;
-
- if ( ! settings.navMenuInstanceArgs[ instanceNumber ] ) {
- throw new Error( 'unknown_instance_number' );
- }
- instance = settings.navMenuInstanceArgs[ instanceNumber ];
-
- containerInstanceClassName = 'partial-refreshable-nav-menu-' + String( instanceNumber );
- container = $( '.' + containerInstanceClassName );
-
- if ( _.isNumber( instance.menu ) ) {
- menuId = instance.menu;
- } else if ( instance.theme_location && api.has( 'nav_menu_locations[' + instance.theme_location + ']' ) ) {
- menuId = api( 'nav_menu_locations[' + instance.theme_location + ']' ).get();
- }
-
- if ( ! menuId || ! instance.can_partial_refresh || 0 === container.length ) {
- api.preview.send( 'refresh' );
+ // Focus on the menu item control when shift+clicking the menu item.
+ $( document ).on( 'click', selector, function( e ) {
+ var navMenuItemParts;
+ if ( ! e.shiftKey ) {
return;
}
- menuId = parseInt( menuId, 10 );
- data = {
- nonce: wp.customize.settings.nonce.preview,
- wp_customize: 'on'
- };
- if ( ! wp.customize.settings.theme.active ) {
- data.theme = wp.customize.settings.theme.stylesheet;
+ navMenuItemParts = $( this ).attr( 'class' ).match( /(?:^|\s)menu-item-(\d+)(?:\s|$)/ );
+ if ( navMenuItemParts ) {
+ e.preventDefault();
+ e.stopPropagation(); // Make sure a sub-nav menu item will get focused instead of parent items.
+ api.preview.send( 'focus-nav-menu-item-control', parseInt( navMenuItemParts[1], 10 ) );
}
- data[ settings.renderQueryVar ] = '1';
-
- // Gather settings to send in partial refresh request.
- customized = {};
- api.each( function( setting, id ) {
- var value = setting.get(), shouldSend = false;
- // @todo Core should propagate the dirty state into the Preview as well so we can use that here.
-
- // Send setting if it is a nav_menu_locations[] setting.
- shouldSend = shouldSend || /^nav_menu_locations\[/.test( id );
-
- // Send setting if it is the setting for this menu.
- shouldSend = shouldSend || id === 'nav_menu[' + String( menuId ) + ']';
-
- // Send setting if it is one that is associated with this menu, or it is deleted.
- shouldSend = shouldSend || ( /^nav_menu_item\[/.test( id ) && ( false === value || menuId === value.nav_menu_term_id ) );
-
- if ( shouldSend ) {
- customized[ id ] = value;
- }
- } );
- data.customized = JSON.stringify( customized );
- data[ settings.renderNoncePostKey ] = settings.renderNonceValue;
-
- wpNavMenuArgs = $.extend( {}, instance );
- data.wp_nav_menu_args_hash = wpNavMenuArgs.args_hash;
- delete wpNavMenuArgs.args_hash;
- data.wp_nav_menu_args = JSON.stringify( wpNavMenuArgs );
-
- container.addClass( 'customize-partial-refreshing' );
-
- request = wp.ajax.send( null, {
- data: data,
- url: api.settings.url.self
- } );
- request.done( function( data ) {
- // If the menu is now not visible, refresh since the page layout may have changed.
- if ( false === data ) {
- api.preview.send( 'refresh' );
- return;
- }
-
- var eventParam, previousContainer = container;
- container = $( data );
- container.addClass( containerInstanceClassName );
- container.addClass( 'partial-refreshable-nav-menu customize-partial-refreshing' );
- previousContainer.replaceWith( container );
- eventParam = {
- instanceNumber: instanceNumber,
- wpNavArgs: wpNavMenuArgs, // @deprecated
- wpNavMenuArgs: wpNavMenuArgs,
- oldContainer: previousContainer,
- newContainer: container
- };
- container.removeClass( 'customize-partial-refreshing' );
- $( document ).trigger( 'customize-preview-menu-refreshed', [ eventParam ] );
- } );
- request.fail( function() {
- api.preview.send( 'refresh' );
- } );
- },
-
- refreshMenuInstanceDebounced : function( instanceNumber ) {
- if ( currentRefreshDebounced[ instanceNumber ] ) {
- clearTimeout( currentRefreshDebounced[ instanceNumber ] );
- }
- currentRefreshDebounced[ instanceNumber ] = setTimeout(
- _.bind( function() {
- this.refreshMenuInstance( instanceNumber );
- }, this ),
- refreshDebounceDelay
- );
- },
-
- /**
- * Connect nav menu items with their corresponding controls in the pane.
- */
- highlightControls: function() {
- var selector = '.menu-item',
- addTooltips;
-
- // Open expand the menu item control when shift+clicking the menu item
- $( document ).on( 'click', selector, function( e ) {
- var navMenuItemParts;
- if ( ! e.shiftKey ) {
- return;
- }
-
- navMenuItemParts = $( this ).attr( 'class' ).match( /(?:^|\s)menu-item-(\d+)(?:\s|$)/ );
- if ( navMenuItemParts ) {
- e.preventDefault();
- e.stopPropagation(); // Make sure a sub-nav menu item will get focused instead of parent items.
- api.preview.send( 'focus-nav-menu-item-control', parseInt( navMenuItemParts[1], 10 ) );
- }
- });
-
- addTooltips = function( e, params ) {
- params.newContainer.find( selector ).attr( 'title', settings.l10n.editNavMenuItemTooltip );
- };
-
- addTooltips( null, { newContainer: $( document.body ) } );
- $( document ).on( 'customize-preview-menu-refreshed', addTooltips );
- }
+ });
};
api.bind( 'preview-ready', function() {
- api.preview.bind( 'active', function() {
- api.MenusCustomizerPreview.init();
- } );
+ self.init();
} );
-}( jQuery, _, wp ) );
+ return self;
+
+}( jQuery, _, wp, wp.customize ) );
diff --git a/wp-includes/js/customize-preview-nav-menus.min.js b/wp-includes/js/customize-preview-nav-menus.min.js
index ee13dcfbe9..f1870a0a05 100644
--- a/wp-includes/js/customize-preview-nav-menus.min.js
+++ b/wp-includes/js/customize-preview-nav-menus.min.js
@@ -1 +1 @@
-!function(a,b,c){"use strict";if(c&&c.customize){var d=c.customize,e={},f=200,g={},h={renderQueryVar:null,renderNonceValue:null,renderNoncePostKey:null,requestUri:"/",navMenuInstanceArgs:{},l10n:{}};d.MenusCustomizerPreview={init:function(){var a=this,c={};g=b.extend({},h),"undefined"!=typeof _wpCustomizePreviewNavMenusExports&&b.extend(g,_wpCustomizePreviewNavMenusExports),d.each(function(b,d){b.id=d,c[b.id]=!0,a.bindListener(b)}),d.preview.bind("setting",function(b){var e,f,g;b=b.slice(),e=b.shift(),f=b.shift(),g=d(e),g||(g=d.create(e,f)),g.id||(g.id=e),c[g.id]||(c[g.id]=!0,a.bindListener(g)&&g.callbacks.fireWith(g,[g(),null]))}),a.highlightControls()},bindListener:function(a){var c,d;return(c=a.id.match(/^nav_menu\[(-?\d+)]$/))?(a.navMenuId=parseInt(c[1],10),a.bind(this.onChangeNavMenuSetting),!0):(c=a.id.match(/^nav_menu_item\[(-?\d+)]$/))?(a.navMenuItemId=parseInt(c[1],10),a.bind(this.onChangeNavMenuItemSetting),!0):(c=a.id.match(/^nav_menu_locations\[(.+?)]/),c?(d=c[1],a.bind(b.bind(function(){this.refreshMenuLocation(d)},this)),!0):!1)},onChangeNavMenuSetting:function(){var a=this;if(!a.navMenuId)throw new Error("Expected navMenuId property to be set.");d.MenusCustomizerPreview.refreshMenu(a.navMenuId)},onChangeNavMenuItemSetting:function(a,b){!b||!b.nav_menu_term_id||a&&b.nav_menu_term_id===a.nav_menu_term_id||d.MenusCustomizerPreview.refreshMenu(b.nav_menu_term_id),a&&a.nav_menu_term_id&&d.MenusCustomizerPreview.refreshMenu(a.nav_menu_term_id)},refreshMenu:function(a){var c=[];d.each(function(b,d){var e=d.match(/^nav_menu_locations\[(.+?)]/);e&&a===b()&&c.push(e[1])}),b.each(g.navMenuInstanceArgs,function(d,e){(a===d.menu||-1!==b.indexOf(c,d.theme_location))&&this.refreshMenuInstanceDebounced(e)},this)},refreshMenuLocation:function(a){var c=!1;b.each(g.navMenuInstanceArgs,function(b,d){a===b.theme_location&&(this.refreshMenuInstanceDebounced(d),c=!0)},this),c||d.preview.send("refresh")},refreshMenuInstance:function(e){var f,h,i,j,k,l,m,n;if(!g.navMenuInstanceArgs[e])throw new Error("unknown_instance_number");return m=g.navMenuInstanceArgs[e],n="partial-refreshable-nav-menu-"+String(e),j=a("."+n),b.isNumber(m.menu)?h=m.menu:m.theme_location&&d.has("nav_menu_locations["+m.theme_location+"]")&&(h=d("nav_menu_locations["+m.theme_location+"]").get()),h&&m.can_partial_refresh&&0!==j.length?(h=parseInt(h,10),f={nonce:c.customize.settings.nonce.preview,wp_customize:"on"},c.customize.settings.theme.active||(f.theme=c.customize.settings.theme.stylesheet),f[g.renderQueryVar]="1",i={},d.each(function(a,b){var c=a.get(),d=!1;d=d||/^nav_menu_locations\[/.test(b),d=d||b==="nav_menu["+String(h)+"]",d=d||/^nav_menu_item\[/.test(b)&&(!1===c||h===c.nav_menu_term_id),d&&(i[b]=c)}),f.customized=JSON.stringify(i),f[g.renderNoncePostKey]=g.renderNonceValue,l=a.extend({},m),f.wp_nav_menu_args_hash=l.args_hash,delete l.args_hash,f.wp_nav_menu_args=JSON.stringify(l),j.addClass("customize-partial-refreshing"),k=c.ajax.send(null,{data:f,url:d.settings.url.self}),k.done(function(b){if(!1===b)return void d.preview.send("refresh");var c,f=j;j=a(b),j.addClass(n),j.addClass("partial-refreshable-nav-menu customize-partial-refreshing"),f.replaceWith(j),c={instanceNumber:e,wpNavArgs:l,wpNavMenuArgs:l,oldContainer:f,newContainer:j},j.removeClass("customize-partial-refreshing"),a(document).trigger("customize-preview-menu-refreshed",[c])}),void k.fail(function(){d.preview.send("refresh")})):void d.preview.send("refresh")},refreshMenuInstanceDebounced:function(a){e[a]&&clearTimeout(e[a]),e[a]=setTimeout(b.bind(function(){this.refreshMenuInstance(a)},this),f)},highlightControls:function(){var b,c=".menu-item";a(document).on("click",c,function(b){var c;b.shiftKey&&(c=a(this).attr("class").match(/(?:^|\s)menu-item-(\d+)(?:\s|$)/),c&&(b.preventDefault(),b.stopPropagation(),d.preview.send("focus-nav-menu-item-control",parseInt(c[1],10))))}),b=function(a,b){b.newContainer.find(c).attr("title",g.l10n.editNavMenuItemTooltip)},b(null,{newContainer:a(document.body)}),a(document).on("customize-preview-menu-refreshed",b)}},d.bind("preview-ready",function(){d.preview.bind("active",function(){d.MenusCustomizerPreview.init()})})}}(jQuery,_,wp);
\ No newline at end of file
+wp.customize.navMenusPreview=wp.customize.MenusCustomizerPreview=function(a,b,c,d){"use strict";var e={};return e.init=function(){var a=this;d.selectiveRefresh&&a.watchNavMenuLocationChanges(),d.preview.bind("active",function(){a.highlightControls()})},d.selectiveRefresh&&(e.NavMenuInstancePartial=d.selectiveRefresh.Partial.extend({initialize:function(a,c){var e,f,g=this;if(e=a.match(/^nav_menu_instance\[([0-9a-f]{32})]$/),!e)throw new Error("Illegal id for nav_menu_instance partial. The key corresponds with the args HMAC.");if(f=e[1],c=c||{},c.params=b.extend({selector:'[data-customize-partial-id="'+a+'"]',navMenuArgs:c.constructingContainerContext||{},containerInclusive:!0},c.params||{}),d.selectiveRefresh.Partial.prototype.initialize.call(g,a,c),!b.isObject(g.params.navMenuArgs))throw new Error("Missing navMenuArgs");if(g.params.navMenuArgs.args_hmac!==f)throw new Error("args_hmac mismatch with id")},isRelatedSetting:function(a,c,e){var f,g,h,i=this;if(b.isString(a)&&(a=d(a)),h=/^nav_menu_item\[/.test(a.id),h&&b.isObject(c)&&b.isObject(e)&&(delete c.type_label,delete e.type_label,b.isEqual(e,c)))return!1;if(i.params.navMenuArgs.theme_location){if("nav_menu_locations["+i.params.navMenuArgs.theme_location+"]"===a.id)return!0;f=d("nav_menu_locations["+i.params.navMenuArgs.theme_location+"]")}return g=i.params.navMenuArgs.menu,!g&&f&&(g=f()),g?"nav_menu["+g+"]"===a.id||h&&(c&&c.nav_menu_term_id===g||e&&e.nav_menu_term_id===g):!1},renderContent:function(b){var c=this,e=b.container;d.selectiveRefresh.Partial.prototype.renderContent.call(c,b)&&a(document).trigger("customize-preview-menu-refreshed",[{instanceNumber:null,wpNavArgs:b.context,wpNavMenuArgs:b.context,oldContainer:e,newContainer:b.container}])}}),d.selectiveRefresh.partialConstructor.nav_menu_instance=e.NavMenuInstancePartial,e.watchNavMenuLocationChanges=function(){d.bind("change",function(a){var b,c=!1,f=a.id.match(/^nav_menu_locations\[(.+)]$/);f&&(b=f[1],d.selectiveRefresh.partial.each(function(a){a.extended(e.NavMenuInstancePartial)&&a.params.navMenuArgs.theme_location===b&&(a.refresh(),c=!0)}),c||d.selectiveRefresh.requestFullRefresh())})}),e.highlightControls=function(){var b=".menu-item";a(document).on("click",b,function(b){var c;b.shiftKey&&(c=a(this).attr("class").match(/(?:^|\s)menu-item-(\d+)(?:\s|$)/),c&&(b.preventDefault(),b.stopPropagation(),d.preview.send("focus-nav-menu-item-control",parseInt(c[1],10))))})},d.bind("preview-ready",function(){e.init()}),e}(jQuery,_,wp,wp.customize);
\ No newline at end of file
diff --git a/wp-includes/js/customize-preview-widgets.js b/wp-includes/js/customize-preview-widgets.js
index f9828295fc..92e7732c83 100644
--- a/wp-includes/js/customize-preview-widgets.js
+++ b/wp-includes/js/customize-preview-widgets.js
@@ -1,119 +1,648 @@
-(function( wp, $ ){
+/* global _wpWidgetCustomizerPreviewSettings */
+wp.customize.widgetsPreview = wp.customize.WidgetCustomizerPreview = (function( $, _, wp, api ) {
- if ( ! wp || ! wp.customize ) { return; }
+ var self;
- var api = wp.customize;
-
- /**
- * wp.customize.WidgetCustomizerPreview
- *
- */
- api.WidgetCustomizerPreview = {
- renderedSidebars: {}, // @todo Make rendered a property of the Backbone model
- renderedWidgets: {}, // @todo Make rendered a property of the Backbone model
- registeredSidebars: [], // @todo Make a Backbone collection
- registeredWidgets: {}, // @todo Make array, Backbone collection
+ self = {
+ renderedSidebars: {},
+ renderedWidgets: {},
+ registeredSidebars: [],
+ registeredWidgets: {},
widgetSelectors: [],
preview: null,
- l10n: {},
-
- init: function () {
- var self = this;
-
- this.preview = api.preview;
- this.buildWidgetSelectors();
- this.highlightControls();
-
- this.preview.bind( 'highlight-widget', self.highlightWidget );
- },
-
- /**
- * Calculate the selector for the sidebar's widgets based on the registered sidebar's info
- */
- buildWidgetSelectors: function () {
- var self = this;
-
- $.each( this.registeredSidebars, function ( i, sidebar ) {
- var widgetTpl = [
- sidebar.before_widget.replace('%1$s', '').replace('%2$s', ''),
- sidebar.before_title,
- sidebar.after_title,
- sidebar.after_widget
- ].join(''),
- emptyWidget,
- widgetSelector,
- widgetClasses;
-
- emptyWidget = $(widgetTpl);
- widgetSelector = emptyWidget.prop('tagName');
- widgetClasses = emptyWidget.prop('className');
-
- // Prevent a rare case when before_widget, before_title, after_title and after_widget is empty.
- if ( ! widgetClasses ) {
- return;
- }
-
- widgetClasses = widgetClasses.replace(/^\s+|\s+$/g, '');
-
- if ( widgetClasses ) {
- widgetSelector += '.' + widgetClasses.split(/\s+/).join('.');
- }
- self.widgetSelectors.push(widgetSelector);
- });
- },
-
- /**
- * Highlight the widget on widget updates or widget control mouse overs.
- *
- * @param {string} widgetId ID of the widget.
- */
- highlightWidget: function( widgetId ) {
- var $body = $( document.body ),
- $widget = $( '#' + widgetId );
-
- $body.find( '.widget-customizer-highlighted-widget' ).removeClass( 'widget-customizer-highlighted-widget' );
-
- $widget.addClass( 'widget-customizer-highlighted-widget' );
- setTimeout( function () {
- $widget.removeClass( 'widget-customizer-highlighted-widget' );
- }, 500 );
- },
-
- /**
- * Show a title and highlight widgets on hover. On shift+clicking
- * focus the widget control.
- */
- highlightControls: function() {
- var self = this,
- selector = this.widgetSelectors.join(',');
-
- $(selector).attr( 'title', this.l10n.widgetTooltip );
-
- $(document).on( 'mouseenter', selector, function () {
- self.preview.send( 'highlight-widget-control', $( this ).prop( 'id' ) );
- });
-
- // Open expand the widget control when shift+clicking the widget element
- $(document).on( 'click', selector, function ( e ) {
- if ( ! e.shiftKey ) {
- return;
- }
- e.preventDefault();
-
- self.preview.send( 'focus-widget-control', $( this ).prop( 'id' ) );
- });
+ l10n: {
+ widgetTooltip: ''
}
};
- $(function () {
- var settings = window._wpWidgetCustomizerPreviewSettings;
- if ( ! settings ) {
- return;
+ /**
+ * Init widgets preview.
+ *
+ * @since 4.5.0
+ */
+ self.init = function() {
+ var self = this;
+
+ self.preview = api.preview;
+ if ( api.selectiveRefresh ) {
+ self.addPartials();
}
- $.extend( api.WidgetCustomizerPreview, settings );
+ self.buildWidgetSelectors();
+ self.highlightControls();
- api.WidgetCustomizerPreview.init();
+ self.preview.bind( 'highlight-widget', self.highlightWidget );
+
+ api.preview.bind( 'active', function() {
+ self.highlightControls();
+ } );
+ };
+
+ if ( api.selectiveRefresh ) {
+
+ /**
+ * Partial representing a widget instance.
+ *
+ * @class
+ * @augments wp.customize.selectiveRefresh.Partial
+ * @since 4.5.0
+ */
+ self.WidgetPartial = api.selectiveRefresh.Partial.extend({
+
+ /**
+ * Constructor.
+ *
+ * @since 4.5.0
+ * @param {string} id - Partial ID.
+ * @param {Object} options
+ * @param {Object} options.params
+ */
+ initialize: function( id, options ) {
+ var partial = this, matches;
+ matches = id.match( /^widget\[(.+)]$/ );
+ if ( ! matches ) {
+ throw new Error( 'Illegal id for widget partial.' );
+ }
+
+ partial.widgetId = matches[1];
+ options = options || {};
+ options.params = _.extend(
+ {
+ /* Note that a selector of ('#' + partial.widgetId) is faster, but jQuery will only return the one result. */
+ selector: '[id="' + partial.widgetId + '"]', // Alternatively, '[data-customize-widget-id="' + partial.widgetId + '"]'
+ settings: [ self.getWidgetSettingId( partial.widgetId ) ],
+ containerInclusive: true
+ },
+ options.params || {}
+ );
+
+ api.selectiveRefresh.Partial.prototype.initialize.call( partial, id, options );
+ },
+
+ /**
+ * Send widget-updated message to parent so spinner will get removed from widget control.
+ *
+ * @inheritdoc
+ * @param {wp.customize.selectiveRefresh.Placement} placement
+ */
+ renderContent: function( placement ) {
+ var partial = this;
+ if ( api.selectiveRefresh.Partial.prototype.renderContent.call( partial, placement ) ) {
+ api.preview.send( 'widget-updated', partial.widgetId );
+ api.selectiveRefresh.trigger( 'widget-updated', partial );
+ }
+ }
+ });
+
+ /**
+ * Partial representing a widget area.
+ *
+ * @class
+ * @augments wp.customize.selectiveRefresh.Partial
+ * @since 4.5.0
+ */
+ self.SidebarPartial = api.selectiveRefresh.Partial.extend({
+
+ /**
+ * Constructor.
+ *
+ * @since 4.5.0
+ * @param {string} id - Partial ID.
+ * @param {Object} options
+ * @param {Object} options.params
+ */
+ initialize: function( id, options ) {
+ var partial = this, matches;
+ matches = id.match( /^sidebar\[(.+)]$/ );
+ if ( ! matches ) {
+ throw new Error( 'Illegal id for sidebar partial.' );
+ }
+ partial.sidebarId = matches[1];
+
+ options = options || {};
+ options.params = _.extend(
+ {
+ settings: [ 'sidebars_widgets[' + partial.sidebarId + ']' ]
+ },
+ options.params || {}
+ );
+
+ api.selectiveRefresh.Partial.prototype.initialize.call( partial, id, options );
+
+ if ( ! partial.params.sidebarArgs ) {
+ throw new Error( 'The sidebarArgs param was not provided.' );
+ }
+ if ( partial.params.settings.length > 1 ) {
+ throw new Error( 'Expected SidebarPartial to only have one associated setting' );
+ }
+ },
+
+ /**
+ * Set up the partial.
+ *
+ * @since 4.5.0
+ */
+ ready: function() {
+ var sidebarPartial = this;
+
+ // Watch for changes to the sidebar_widgets setting.
+ _.each( sidebarPartial.settings(), function( settingId ) {
+ api( settingId ).bind( _.bind( sidebarPartial.handleSettingChange, sidebarPartial ) );
+ } );
+
+ // Trigger an event for this sidebar being updated whenever a widget inside is rendered.
+ api.selectiveRefresh.bind( 'partial-content-rendered', function( placement ) {
+ var isAssignedWidgetPartial = (
+ placement.partial.extended( self.WidgetPartial ) &&
+ ( -1 !== _.indexOf( sidebarPartial.getWidgetIds(), placement.partial.widgetId ) )
+ );
+ if ( isAssignedWidgetPartial ) {
+ api.selectiveRefresh.trigger( 'sidebar-updated', sidebarPartial );
+ }
+ } );
+
+ // Make sure that a widget partial has a container in the DOM prior to a refresh.
+ api.bind( 'change', function( widgetSetting ) {
+ var widgetId, parsedId;
+ parsedId = self.parseWidgetSettingId( widgetSetting.id );
+ if ( ! parsedId ) {
+ return;
+ }
+ widgetId = parsedId.idBase;
+ if ( parsedId.number ) {
+ widgetId += '-' + String( parsedId.number );
+ }
+ if ( -1 !== _.indexOf( sidebarPartial.getWidgetIds(), widgetId ) ) {
+ sidebarPartial.ensureWidgetPlacementContainers( widgetId );
+ }
+ } );
+ },
+
+ /**
+ * Get the before/after boundary nodes for all instances of this sidebar (usually one).
+ *
+ * Note that TreeWalker is not implemented in IE8.
+ *
+ * @since 4.5.0
+ * @returns {Array.<{before: Comment, after: Comment, instanceNumber: number}>}
+ */
+ findDynamicSidebarBoundaryNodes: function() {
+ var partial = this, regExp, boundaryNodes = {}, recursiveCommentTraversal;
+ regExp = /^(dynamic_sidebar_before|dynamic_sidebar_after):(.+):(\d+)$/;
+ recursiveCommentTraversal = function( childNodes ) {
+ _.each( childNodes, function( node ) {
+ var matches;
+ if ( 8 === node.nodeType ) {
+ matches = node.nodeValue.match( regExp );
+ if ( ! matches || matches[2] !== partial.sidebarId ) {
+ return;
+ }
+ if ( _.isUndefined( boundaryNodes[ matches[3] ] ) ) {
+ boundaryNodes[ matches[3] ] = {
+ before: null,
+ after: null,
+ instanceNumber: parseInt( matches[3], 10 )
+ };
+ }
+ if ( 'dynamic_sidebar_before' === matches[1] ) {
+ boundaryNodes[ matches[3] ].before = node;
+ } else {
+ boundaryNodes[ matches[3] ].after = node;
+ }
+ } else if ( 1 === node.nodeType ) {
+ recursiveCommentTraversal( node.childNodes );
+ }
+ } );
+ };
+
+ recursiveCommentTraversal( document.body.childNodes );
+ return _.values( boundaryNodes );
+ },
+
+ /**
+ * Get the placements for this partial.
+ *
+ * @since 4.5.0
+ * @returns {Array}
+ */
+ placements: function() {
+ var partial = this;
+ return _.map( partial.findDynamicSidebarBoundaryNodes(), function( boundaryNodes ) {
+ return new api.selectiveRefresh.Placement( {
+ partial: partial,
+ container: null,
+ startNode: boundaryNodes.before,
+ endNode: boundaryNodes.after,
+ context: {
+ instanceNumber: boundaryNodes.instanceNumber
+ }
+ } );
+ } );
+ },
+
+ /**
+ * Get the list of widget IDs associated with this widget area.
+ *
+ * @since 4.5.0
+ *
+ * @returns {Array}
+ */
+ getWidgetIds: function() {
+ var sidebarPartial = this, settingId, widgetIds;
+ settingId = sidebarPartial.settings()[0];
+ if ( ! settingId ) {
+ throw new Error( 'Missing associated setting.' );
+ }
+ if ( ! api.has( settingId ) ) {
+ throw new Error( 'Setting does not exist.' );
+ }
+ widgetIds = api( settingId ).get();
+ if ( ! _.isArray( widgetIds ) ) {
+ throw new Error( 'Expected setting to be array of widget IDs' );
+ }
+ return widgetIds.slice( 0 );
+ },
+
+ /**
+ * Reflow widgets in the sidebar, ensuring they have the proper position in the DOM.
+ *
+ * @since 4.5.0
+ *
+ * @return {Array.} List of placements that were reflowed.
+ */
+ reflowWidgets: function() {
+ var sidebarPartial = this, sidebarPlacements, widgetIds, widgetPartials, sortedSidebarContainers = [];
+ widgetIds = sidebarPartial.getWidgetIds();
+ sidebarPlacements = sidebarPartial.placements();
+
+ widgetPartials = {};
+ _.each( widgetIds, function( widgetId ) {
+ var widgetPartial = api.selectiveRefresh.partial( 'widget[' + widgetId + ']' );
+ if ( widgetPartial ) {
+ widgetPartials[ widgetId ] = widgetPartial;
+ }
+ } );
+
+ _.each( sidebarPlacements, function( sidebarPlacement ) {
+ var sidebarWidgets = [], needsSort = false, thisPosition, lastPosition = -1;
+
+ // Gather list of widget partial containers in this sidebar, and determine if a sort is needed.
+ _.each( widgetPartials, function( widgetPartial ) {
+ _.each( widgetPartial.placements(), function( widgetPlacement ) {
+
+ if ( sidebarPlacement.context.instanceNumber === widgetPlacement.context.sidebar_instance_number ) {
+ thisPosition = widgetPlacement.container.index();
+ sidebarWidgets.push( {
+ partial: widgetPartial,
+ placement: widgetPlacement,
+ position: thisPosition
+ } );
+ if ( thisPosition < lastPosition ) {
+ needsSort = true;
+ }
+ lastPosition = thisPosition;
+ }
+ } );
+ } );
+
+ if ( needsSort ) {
+ _.each( sidebarWidgets, function( sidebarWidget ) {
+ sidebarPlacement.endNode.parentNode.insertBefore(
+ sidebarWidget.placement.container[0],
+ sidebarPlacement.endNode
+ );
+
+ // @todo Rename partial-placement-moved?
+ api.selectiveRefresh.trigger( 'partial-content-moved', sidebarWidget.placement );
+ } );
+
+ sortedSidebarContainers.push( sidebarPlacement );
+ }
+ } );
+
+ if ( sortedSidebarContainers.length > 0 ) {
+ api.selectiveRefresh.trigger( 'sidebar-updated', sidebarPartial );
+ }
+
+ return sortedSidebarContainers;
+ },
+
+ /**
+ * Make sure there is a widget instance container in this sidebar for the given widget ID.
+ *
+ * @since 4.5.0
+ *
+ * @param {string} widgetId
+ * @returns {wp.customize.selectiveRefresh.Partial} Widget instance partial.
+ */
+ ensureWidgetPlacementContainers: function( widgetId ) {
+ var sidebarPartial = this, widgetPartial, wasInserted = false, partialId = 'widget[' + widgetId + ']';
+ widgetPartial = api.selectiveRefresh.partial( partialId );
+ if ( ! widgetPartial ) {
+ widgetPartial = new self.WidgetPartial( partialId, {
+ params: {}
+ } );
+ api.selectiveRefresh.partial.add( widgetPartial.id, widgetPartial );
+ }
+
+ // Make sure that there is a container element for the widget in the sidebar, if at least a placeholder.
+ _.each( sidebarPartial.placements(), function( sidebarPlacement ) {
+ var foundWidgetPlacement, widgetContainerElement;
+
+ foundWidgetPlacement = _.find( widgetPartial.placements(), function( widgetPlacement ) {
+ return ( widgetPlacement.context.sidebar_instance_number === sidebarPlacement.context.instanceNumber );
+ } );
+ if ( foundWidgetPlacement ) {
+ return;
+ }
+
+ widgetContainerElement = $(
+ sidebarPartial.params.sidebarArgs.before_widget.replace( '%1$s', widgetId ).replace( '%2$s', 'widget' ) +
+ sidebarPartial.params.sidebarArgs.after_widget
+ );
+
+ widgetContainerElement.attr( 'data-customize-partial-id', widgetPartial.id );
+ widgetContainerElement.attr( 'data-customize-partial-type', 'widget' );
+ widgetContainerElement.attr( 'data-customize-widget-id', widgetId );
+
+ /*
+ * Make sure the widget container element has the customize-container context data.
+ * The sidebar_instance_number is used to disambiguate multiple instances of the
+ * same sidebar are rendered onto the template, and so the same widget is embedded
+ * multiple times.
+ */
+ widgetContainerElement.data( 'customize-partial-placement-context', {
+ 'sidebar_id': sidebarPartial.sidebarId,
+ 'sidebar_instance_number': sidebarPlacement.context.instanceNumber
+ } );
+
+ sidebarPlacement.endNode.parentNode.insertBefore( widgetContainerElement[0], sidebarPlacement.endNode );
+ wasInserted = true;
+ } );
+
+ if ( wasInserted ) {
+ sidebarPartial.reflowWidgets();
+ }
+
+ return widgetPartial;
+ },
+
+ /**
+ * Handle change to the sidebars_widgets[] setting.
+ *
+ * @since 4.5.0
+ *
+ * @param {Array} newWidgetIds New widget ids.
+ * @param {Array} oldWidgetIds Old widget ids.
+ */
+ handleSettingChange: function( newWidgetIds, oldWidgetIds ) {
+ var sidebarPartial = this, needsRefresh, widgetsRemoved, widgetsAdded, addedWidgetPartials = [];
+
+ needsRefresh = (
+ ( oldWidgetIds.length > 0 && 0 === newWidgetIds.length ) ||
+ ( newWidgetIds.length > 0 && 0 === oldWidgetIds.length )
+ );
+ if ( needsRefresh ) {
+ sidebarPartial.fallback();
+ return;
+ }
+
+ // Handle removal of widgets.
+ widgetsRemoved = _.difference( oldWidgetIds, newWidgetIds );
+ _.each( widgetsRemoved, function( removedWidgetId ) {
+ var widgetPartial = api.selectiveRefresh.partial( 'widget[' + removedWidgetId + ']' );
+ if ( widgetPartial ) {
+ _.each( widgetPartial.placements(), function( placement ) {
+ var isRemoved = (
+ placement.context.sidebar_id === sidebarPartial.sidebarId ||
+ ( placement.context.sidebar_args && placement.context.sidebar_args.id === sidebarPartial.sidebarId )
+ );
+ if ( isRemoved ) {
+ placement.container.remove();
+ }
+ } );
+ }
+ } );
+
+ // Handle insertion of widgets.
+ widgetsAdded = _.difference( newWidgetIds, oldWidgetIds );
+ _.each( widgetsAdded, function( addedWidgetId ) {
+ var widgetPartial = sidebarPartial.ensureWidgetPlacementContainers( addedWidgetId );
+ addedWidgetPartials.push( widgetPartial );
+ } );
+
+ _.each( addedWidgetPartials, function( widgetPartial ) {
+ widgetPartial.refresh();
+ } );
+
+ api.selectiveRefresh.trigger( 'sidebar-updated', sidebarPartial );
+ },
+
+ /**
+ * Note that the meat is handled in handleSettingChange because it has the context of which widgets were removed.
+ *
+ * @since 4.5.0
+ */
+ refresh: function() {
+ var partial = this, deferred = $.Deferred();
+
+ deferred.fail( function() {
+ partial.fallback();
+ } );
+
+ if ( 0 === partial.placements().length ) {
+ deferred.reject();
+ } else {
+ _.each( partial.reflowWidgets(), function( sidebarPlacement ) {
+ api.selectiveRefresh.trigger( 'partial-content-rendered', sidebarPlacement );
+ } );
+ deferred.resolve();
+ }
+
+ return deferred.promise();
+ }
+ });
+
+ api.selectiveRefresh.partialConstructor.sidebar = self.SidebarPartial;
+ api.selectiveRefresh.partialConstructor.widget = self.WidgetPartial;
+
+ /**
+ * Add partials for the registered widget areas (sidebars).
+ *
+ * @since 4.5.0
+ */
+ self.addPartials = function() {
+ _.each( self.registeredSidebars, function( registeredSidebar ) {
+ var partial, partialId = 'sidebar[' + registeredSidebar.id + ']';
+ partial = api.selectiveRefresh.partial( partialId );
+ if ( ! partial ) {
+ partial = new self.SidebarPartial( partialId, {
+ params: {
+ sidebarArgs: registeredSidebar
+ }
+ } );
+ api.selectiveRefresh.partial.add( partial.id, partial );
+ }
+ } );
+ };
+
+ }
+
+ /**
+ * Calculate the selector for the sidebar's widgets based on the registered sidebar's info.
+ *
+ * @since 3.9.0
+ */
+ self.buildWidgetSelectors = function() {
+ var self = this;
+
+ $.each( self.registeredSidebars, function( i, sidebar ) {
+ var widgetTpl = [
+ sidebar.before_widget.replace( '%1$s', '' ).replace( '%2$s', '' ),
+ sidebar.before_title,
+ sidebar.after_title,
+ sidebar.after_widget
+ ].join( '' ),
+ emptyWidget,
+ widgetSelector,
+ widgetClasses;
+
+ emptyWidget = $( widgetTpl );
+ widgetSelector = emptyWidget.prop( 'tagName' );
+ widgetClasses = emptyWidget.prop( 'className' );
+
+ // Prevent a rare case when before_widget, before_title, after_title and after_widget is empty.
+ if ( ! widgetClasses ) {
+ return;
+ }
+
+ widgetClasses = widgetClasses.replace( /^\s+|\s+$/g, '' );
+
+ if ( widgetClasses ) {
+ widgetSelector += '.' + widgetClasses.split( /\s+/ ).join( '.' );
+ }
+ self.widgetSelectors.push( widgetSelector );
+ });
+ };
+
+ /**
+ * Highlight the widget on widget updates or widget control mouse overs.
+ *
+ * @since 3.9.0
+ * @param {string} widgetId ID of the widget.
+ */
+ self.highlightWidget = function( widgetId ) {
+ var $body = $( document.body ),
+ $widget = $( '#' + widgetId );
+
+ $body.find( '.widget-customizer-highlighted-widget' ).removeClass( 'widget-customizer-highlighted-widget' );
+
+ $widget.addClass( 'widget-customizer-highlighted-widget' );
+ setTimeout( function() {
+ $widget.removeClass( 'widget-customizer-highlighted-widget' );
+ }, 500 );
+ };
+
+ /**
+ * Show a title and highlight widgets on hover. On shift+clicking
+ * focus the widget control.
+ *
+ * @since 3.9.0
+ */
+ self.highlightControls = function() {
+ var self = this,
+ selector = this.widgetSelectors.join( ',' );
+
+ $( selector ).attr( 'title', this.l10n.widgetTooltip );
+
+ $( document ).on( 'mouseenter', selector, function() {
+ self.preview.send( 'highlight-widget-control', $( this ).prop( 'id' ) );
+ });
+
+ // Open expand the widget control when shift+clicking the widget element
+ $( document ).on( 'click', selector, function( e ) {
+ if ( ! e.shiftKey ) {
+ return;
+ }
+ e.preventDefault();
+
+ self.preview.send( 'focus-widget-control', $( this ).prop( 'id' ) );
+ });
+ };
+
+ /**
+ * Parse a widget ID.
+ *
+ * @since 4.5.0
+ *
+ * @param {string} widgetId Widget ID.
+ * @returns {{idBase: string, number: number|null}}
+ */
+ self.parseWidgetId = function( widgetId ) {
+ var matches, parsed = {
+ idBase: '',
+ number: null
+ };
+
+ matches = widgetId.match( /^(.+)-(\d+)$/ );
+ if ( matches ) {
+ parsed.idBase = matches[1];
+ parsed.number = parseInt( matches[2], 10 );
+ } else {
+ parsed.idBase = widgetId; // Likely an old single widget.
+ }
+
+ return parsed;
+ };
+
+ /**
+ * Parse a widget setting ID.
+ *
+ * @since 4.5.0
+ *
+ * @param {string} settingId Widget setting ID.
+ * @returns {{idBase: string, number: number|null}|null}
+ */
+ self.parseWidgetSettingId = function( settingId ) {
+ var matches, parsed = {
+ idBase: '',
+ number: null
+ };
+
+ matches = settingId.match( /^widget_([^\[]+?)(?:\[(\d+)])?$/ );
+ if ( ! matches ) {
+ return null;
+ }
+ parsed.idBase = matches[1];
+ if ( matches[2] ) {
+ parsed.number = parseInt( matches[2], 10 );
+ }
+ return parsed;
+ };
+
+ /**
+ * Convert a widget ID into a Customizer setting ID.
+ *
+ * @since 4.5.0
+ *
+ * @param {string} widgetId Widget ID.
+ * @returns {string} settingId Setting ID.
+ */
+ self.getWidgetSettingId = function( widgetId ) {
+ var parsed = this.parseWidgetId( widgetId ), settingId;
+
+ settingId = 'widget_' + parsed.idBase;
+ if ( parsed.number ) {
+ settingId += '[' + String( parsed.number ) + ']';
+ }
+
+ return settingId;
+ };
+
+ api.bind( 'preview-ready', function() {
+ $.extend( self, _wpWidgetCustomizerPreviewSettings );
+ self.init();
});
-})( window.wp, jQuery );
+ return self;
+})( jQuery, _, wp, wp.customize );
diff --git a/wp-includes/js/customize-preview-widgets.min.js b/wp-includes/js/customize-preview-widgets.min.js
index 4ce0729805..923f20d086 100644
--- a/wp-includes/js/customize-preview-widgets.min.js
+++ b/wp-includes/js/customize-preview-widgets.min.js
@@ -1 +1 @@
-!function(a,b){if(a&&a.customize){var c=a.customize;c.WidgetCustomizerPreview={renderedSidebars:{},renderedWidgets:{},registeredSidebars:[],registeredWidgets:{},widgetSelectors:[],preview:null,l10n:{},init:function(){var a=this;this.preview=c.preview,this.buildWidgetSelectors(),this.highlightControls(),this.preview.bind("highlight-widget",a.highlightWidget)},buildWidgetSelectors:function(){var a=this;b.each(this.registeredSidebars,function(c,d){var e,f,g,h=[d.before_widget.replace("%1$s","").replace("%2$s",""),d.before_title,d.after_title,d.after_widget].join("");e=b(h),f=e.prop("tagName"),g=e.prop("className"),g&&(g=g.replace(/^\s+|\s+$/g,""),g&&(f+="."+g.split(/\s+/).join(".")),a.widgetSelectors.push(f))})},highlightWidget:function(a){var c=b(document.body),d=b("#"+a);c.find(".widget-customizer-highlighted-widget").removeClass("widget-customizer-highlighted-widget"),d.addClass("widget-customizer-highlighted-widget"),setTimeout(function(){d.removeClass("widget-customizer-highlighted-widget")},500)},highlightControls:function(){var a=this,c=this.widgetSelectors.join(",");b(c).attr("title",this.l10n.widgetTooltip),b(document).on("mouseenter",c,function(){a.preview.send("highlight-widget-control",b(this).prop("id"))}),b(document).on("click",c,function(c){c.shiftKey&&(c.preventDefault(),a.preview.send("focus-widget-control",b(this).prop("id")))})}},b(function(){var a=window._wpWidgetCustomizerPreviewSettings;a&&(b.extend(c.WidgetCustomizerPreview,a),c.WidgetCustomizerPreview.init())})}}(window.wp,jQuery);
\ No newline at end of file
+wp.customize.widgetsPreview=wp.customize.WidgetCustomizerPreview=function(a,b,c,d){var e;return e={renderedSidebars:{},renderedWidgets:{},registeredSidebars:[],registeredWidgets:{},widgetSelectors:[],preview:null,l10n:{widgetTooltip:""}},e.init=function(){var a=this;a.preview=d.preview,d.selectiveRefresh&&a.addPartials(),a.buildWidgetSelectors(),a.highlightControls(),a.preview.bind("highlight-widget",a.highlightWidget),d.preview.bind("active",function(){a.highlightControls()})},d.selectiveRefresh&&(e.WidgetPartial=d.selectiveRefresh.Partial.extend({initialize:function(a,c){var f,g=this;if(f=a.match(/^widget\[(.+)]$/),!f)throw new Error("Illegal id for widget partial.");g.widgetId=f[1],c=c||{},c.params=b.extend({selector:'[id="'+g.widgetId+'"]',settings:[e.getWidgetSettingId(g.widgetId)],containerInclusive:!0},c.params||{}),d.selectiveRefresh.Partial.prototype.initialize.call(g,a,c)},renderContent:function(a){var b=this;d.selectiveRefresh.Partial.prototype.renderContent.call(b,a)&&(d.preview.send("widget-updated",b.widgetId),d.selectiveRefresh.trigger("widget-updated",b))}}),e.SidebarPartial=d.selectiveRefresh.Partial.extend({initialize:function(a,c){var e,f=this;if(e=a.match(/^sidebar\[(.+)]$/),!e)throw new Error("Illegal id for sidebar partial.");if(f.sidebarId=e[1],c=c||{},c.params=b.extend({settings:["sidebars_widgets["+f.sidebarId+"]"]},c.params||{}),d.selectiveRefresh.Partial.prototype.initialize.call(f,a,c),!f.params.sidebarArgs)throw new Error("The sidebarArgs param was not provided.");if(f.params.settings.length>1)throw new Error("Expected SidebarPartial to only have one associated setting")},ready:function(){var a=this;b.each(a.settings(),function(c){d(c).bind(b.bind(a.handleSettingChange,a))}),d.selectiveRefresh.bind("partial-content-rendered",function(c){var f=c.partial.extended(e.WidgetPartial)&&-1!==b.indexOf(a.getWidgetIds(),c.partial.widgetId);f&&d.selectiveRefresh.trigger("sidebar-updated",a)}),d.bind("change",function(c){var d,f;f=e.parseWidgetSettingId(c.id),f&&(d=f.idBase,f.number&&(d+="-"+String(f.number)),-1!==b.indexOf(a.getWidgetIds(),d)&&a.ensureWidgetPlacementContainers(d))})},findDynamicSidebarBoundaryNodes:function(){var a,c,d=this,e={};return a=/^(dynamic_sidebar_before|dynamic_sidebar_after):(.+):(\d+)$/,c=function(f){b.each(f,function(f){var g;if(8===f.nodeType){if(g=f.nodeValue.match(a),!g||g[2]!==d.sidebarId)return;b.isUndefined(e[g[3]])&&(e[g[3]]={before:null,after:null,instanceNumber:parseInt(g[3],10)}),"dynamic_sidebar_before"===g[1]?e[g[3]].before=f:e[g[3]].after=f}else 1===f.nodeType&&c(f.childNodes)})},c(document.body.childNodes),b.values(e)},placements:function(){var a=this;return b.map(a.findDynamicSidebarBoundaryNodes(),function(b){return new d.selectiveRefresh.Placement({partial:a,container:null,startNode:b.before,endNode:b.after,context:{instanceNumber:b.instanceNumber}})})},getWidgetIds:function(){var a,c,e=this;if(a=e.settings()[0],!a)throw new Error("Missing associated setting.");if(!d.has(a))throw new Error("Setting does not exist.");if(c=d(a).get(),!b.isArray(c))throw new Error("Expected setting to be array of widget IDs");return c.slice(0)},reflowWidgets:function(){var a,c,e,f=this,g=[];return c=f.getWidgetIds(),a=f.placements(),e={},b.each(c,function(a){var b=d.selectiveRefresh.partial("widget["+a+"]");b&&(e[a]=b)}),b.each(a,function(a){var c,f=[],h=!1,i=-1;b.each(e,function(d){b.each(d.placements(),function(b){a.context.instanceNumber===b.context.sidebar_instance_number&&(c=b.container.index(),f.push({partial:d,placement:b,position:c}),i>c&&(h=!0),i=c)})}),h&&(b.each(f,function(b){a.endNode.parentNode.insertBefore(b.placement.container[0],a.endNode),d.selectiveRefresh.trigger("partial-content-moved",b.placement)}),g.push(a))}),g.length>0&&d.selectiveRefresh.trigger("sidebar-updated",f),g},ensureWidgetPlacementContainers:function(c){var f,g=this,h=!1,i="widget["+c+"]";return f=d.selectiveRefresh.partial(i),f||(f=new e.WidgetPartial(i,{params:{}}),d.selectiveRefresh.partial.add(f.id,f)),b.each(g.placements(),function(d){var e,i;e=b.find(f.placements(),function(a){return a.context.sidebar_instance_number===d.context.instanceNumber}),e||(i=a(g.params.sidebarArgs.before_widget.replace("%1$s",c).replace("%2$s","widget")+g.params.sidebarArgs.after_widget),i.attr("data-customize-partial-id",f.id),i.attr("data-customize-partial-type","widget"),i.attr("data-customize-widget-id",c),i.data("customize-partial-placement-context",{sidebar_id:g.sidebarId,sidebar_instance_number:d.context.instanceNumber}),d.endNode.parentNode.insertBefore(i[0],d.endNode),h=!0)}),h&&g.reflowWidgets(),f},handleSettingChange:function(a,c){var e,f,g,h=this,i=[];return(e=c.length>0&&0===a.length||a.length>0&&0===c.length)?void h.fallback():(f=b.difference(c,a),b.each(f,function(a){var c=d.selectiveRefresh.partial("widget["+a+"]");c&&b.each(c.placements(),function(a){var b=a.context.sidebar_id===h.sidebarId||a.context.sidebar_args&&a.context.sidebar_args.id===h.sidebarId;b&&a.container.remove()})}),g=b.difference(a,c),b.each(g,function(a){var b=h.ensureWidgetPlacementContainers(a);i.push(b)}),b.each(i,function(a){a.refresh()}),void d.selectiveRefresh.trigger("sidebar-updated",h))},refresh:function(){var c=this,e=a.Deferred();return e.fail(function(){c.fallback()}),0===c.placements().length?e.reject():(b.each(c.reflowWidgets(),function(a){d.selectiveRefresh.trigger("partial-content-rendered",a)}),e.resolve()),e.promise()}}),d.selectiveRefresh.partialConstructor.sidebar=e.SidebarPartial,d.selectiveRefresh.partialConstructor.widget=e.WidgetPartial,e.addPartials=function(){b.each(e.registeredSidebars,function(a){var b,c="sidebar["+a.id+"]";b=d.selectiveRefresh.partial(c),b||(b=new e.SidebarPartial(c,{params:{sidebarArgs:a}}),d.selectiveRefresh.partial.add(b.id,b))})}),e.buildWidgetSelectors=function(){var b=this;a.each(b.registeredSidebars,function(c,d){var e,f,g,h=[d.before_widget.replace("%1$s","").replace("%2$s",""),d.before_title,d.after_title,d.after_widget].join("");e=a(h),f=e.prop("tagName"),g=e.prop("className"),g&&(g=g.replace(/^\s+|\s+$/g,""),g&&(f+="."+g.split(/\s+/).join(".")),b.widgetSelectors.push(f))})},e.highlightWidget=function(b){var c=a(document.body),d=a("#"+b);c.find(".widget-customizer-highlighted-widget").removeClass("widget-customizer-highlighted-widget"),d.addClass("widget-customizer-highlighted-widget"),setTimeout(function(){d.removeClass("widget-customizer-highlighted-widget")},500)},e.highlightControls=function(){var b=this,c=this.widgetSelectors.join(",");a(c).attr("title",this.l10n.widgetTooltip),a(document).on("mouseenter",c,function(){b.preview.send("highlight-widget-control",a(this).prop("id"))}),a(document).on("click",c,function(c){c.shiftKey&&(c.preventDefault(),b.preview.send("focus-widget-control",a(this).prop("id")))})},e.parseWidgetId=function(a){var b,c={idBase:"",number:null};return b=a.match(/^(.+)-(\d+)$/),b?(c.idBase=b[1],c.number=parseInt(b[2],10)):c.idBase=a,c},e.parseWidgetSettingId=function(a){var b,c={idBase:"",number:null};return(b=a.match(/^widget_([^\[]+?)(?:\[(\d+)])?$/))?(c.idBase=b[1],b[2]&&(c.number=parseInt(b[2],10)),c):null},e.getWidgetSettingId=function(a){var b,c=this.parseWidgetId(a);return b="widget_"+c.idBase,c.number&&(b+="["+String(c.number)+"]"),b},d.bind("preview-ready",function(){a.extend(e,_wpWidgetCustomizerPreviewSettings),e.init()}),e}(jQuery,_,wp,wp.customize);
\ No newline at end of file
diff --git a/wp-includes/js/customize-selective-refresh.js b/wp-includes/js/customize-selective-refresh.js
new file mode 100644
index 0000000000..151adf829a
--- /dev/null
+++ b/wp-includes/js/customize-selective-refresh.js
@@ -0,0 +1,873 @@
+/* global jQuery, JSON, _customizePartialRefreshExports, console */
+
+wp.customize.selectiveRefresh = ( function( $, api ) {
+ 'use strict';
+ var self, Partial, Placement;
+
+ self = {
+ ready: $.Deferred(),
+ data: {
+ partials: {},
+ renderQueryVar: '',
+ l10n: {
+ shiftClickToEdit: ''
+ },
+ refreshBuffer: 250
+ },
+ currentRequest: null
+ };
+
+ _.extend( self, api.Events );
+
+ /**
+ * A Customizer Partial.
+ *
+ * A partial provides a rendering of one or more settings according to a template.
+ *
+ * @see PHP class WP_Customize_Partial.
+ *
+ * @class
+ * @augments wp.customize.Class
+ * @since 4.5.0
+ *
+ * @param {string} id Unique identifier for the control instance.
+ * @param {object} options Options hash for the control instance.
+ * @param {object} options.params
+ * @param {string} options.params.type Type of partial (e.g. nav_menu, widget, etc)
+ * @param {string} options.params.selector jQuery selector to find the container element in the page.
+ * @param {array} options.params.settings The IDs for the settings the partial relates to.
+ * @param {string} options.params.primarySetting The ID for the primary setting the partial renders.
+ * @param {bool} options.params.fallbackRefresh Whether to refresh the entire preview in case of a partial refresh failure.
+ */
+ Partial = self.Partial = api.Class.extend({
+
+ id: null,
+
+ /**
+ * Constructor.
+ *
+ * @since 4.5.0
+ *
+ * @param {string} id - Partial ID.
+ * @param {Object} options
+ * @param {Object} options.params
+ */
+ initialize: function( id, options ) {
+ var partial = this;
+ options = options || {};
+ partial.id = id;
+
+ partial.params = _.extend(
+ {
+ selector: null,
+ settings: [],
+ primarySetting: null,
+ containerInclusive: false,
+ fallbackRefresh: true // Note this needs to be false in a frontend editing context.
+ },
+ options.params || {}
+ );
+
+ partial.deferred = {};
+ partial.deferred.ready = $.Deferred();
+
+ partial.deferred.ready.done( function() {
+ partial.ready();
+ } );
+ },
+
+ /**
+ * Set up the partial.
+ *
+ * @since 4.5.0
+ */
+ ready: function() {
+ var partial = this;
+ _.each( _.pluck( partial.placements(), 'container' ), function( container ) {
+ $( container ).attr( 'title', self.data.l10n.shiftClickToEdit );
+ } );
+ $( document ).on( 'click', partial.params.selector, function( e ) {
+ if ( ! e.shiftKey ) {
+ return;
+ }
+ e.preventDefault();
+ _.each( partial.placements(), function( placement ) {
+ if ( $( placement.container ).is( e.currentTarget ) ) {
+ partial.showControl();
+ }
+ } );
+ } );
+ },
+
+ /**
+ * Find all placements for this partial int he document.
+ *
+ * @since 4.5.0
+ *
+ * @return {Array.}
+ */
+ placements: function() {
+ var partial = this, selector;
+
+ selector = partial.params.selector;
+ if ( selector ) {
+ selector += ', ';
+ }
+ selector += '[data-customize-partial-id="' + partial.id + '"]'; // @todo Consider injecting customize-partial-id-${id} classnames instead.
+
+ return $( selector ).map( function() {
+ var container = $( this ), context;
+
+ context = container.data( 'customize-partial-placement-context' );
+ if ( _.isString( context ) && '{' === context.substr( 0, 1 ) ) {
+ throw new Error( 'context JSON parse error' );
+ }
+
+ return new Placement( {
+ partial: partial,
+ container: container,
+ context: context
+ } );
+ } ).get();
+ },
+
+ /**
+ * Get list of setting IDs related to this partial.
+ *
+ * @since 4.5.0
+ *
+ * @return {String[]}
+ */
+ settings: function() {
+ var partial = this;
+ if ( partial.params.settings && 0 !== partial.params.settings.length ) {
+ return partial.params.settings;
+ } else if ( partial.params.primarySetting ) {
+ return [ partial.params.primarySetting ];
+ } else {
+ return [ partial.id ];
+ }
+ },
+
+ /**
+ * Return whether the setting is related to the partial.
+ *
+ * @since 4.5.0
+ *
+ * @param {wp.customize.Value|string} setting ID or object for setting.
+ * @return {boolean} Whether the setting is related to the partial.
+ */
+ isRelatedSetting: function( setting /*... newValue, oldValue */ ) {
+ var partial = this;
+ if ( _.isString( setting ) ) {
+ setting = api( setting );
+ }
+ if ( ! setting ) {
+ return false;
+ }
+ return -1 !== _.indexOf( partial.settings(), setting.id );
+ },
+
+ /**
+ * Show the control to modify this partial's setting(s).
+ *
+ * This may be overridden for inline editing.
+ *
+ * @since 4.5.0
+ */
+ showControl: function() {
+ var partial = this, settingId = partial.params.primarySetting;
+ if ( ! settingId ) {
+ settingId = _.first( partial.settings() );
+ }
+ api.preview.send( 'focus-control-for-setting', settingId );
+ },
+
+ /**
+ * Prepare container for selective refresh.
+ *
+ * @since 4.5.0
+ *
+ * @param {Placement} placement
+ */
+ preparePlacement: function( placement ) {
+ $( placement.container ).addClass( 'customize-partial-refreshing' );
+ },
+
+ /**
+ * Reference to the pending promise returned from self.requestPartial().
+ *
+ * @since 4.5.0
+ * @private
+ */
+ _pendingRefreshPromise: null,
+
+ /**
+ * Request the new partial and render it into the placements.
+ *
+ * @since 4.5.0
+ *
+ * @this {wp.customize.selectiveRefresh.Partial}
+ * @return {jQuery.Promise}
+ */
+ refresh: function() {
+ var partial = this, refreshPromise;
+
+ refreshPromise = self.requestPartial( partial );
+
+ if ( ! partial._pendingRefreshPromise ) {
+ _.each( partial.placements(), function( placement ) {
+ partial.preparePlacement( placement );
+ } );
+
+ refreshPromise.done( function( placements ) {
+ _.each( placements, function( placement ) {
+ partial.renderContent( placement );
+ } );
+ } );
+
+ refreshPromise.fail( function( data, placements ) {
+ partial.fallback( data, placements );
+ } );
+
+ // Allow new request when this one finishes.
+ partial._pendingRefreshPromise = refreshPromise;
+ refreshPromise.always( function() {
+ partial._pendingRefreshPromise = null;
+ } );
+ }
+
+ return refreshPromise;
+ },
+
+ /**
+ * Apply the addedContent in the placement to the document.
+ *
+ * Note the placement object will have its container and removedNodes
+ * properties updated.
+ *
+ * @since 4.5.0
+ *
+ * @param {Placement} placement
+ * @param {Element|jQuery} [placement.container] - This param will be empty if there was no element matching the selector.
+ * @param {string|object|boolean} placement.addedContent - Rendered HTML content, a data object for JS templates to render, or false if no render.
+ * @param {object} [placement.context] - Optional context information about the container.
+ * @returns {boolean} Whether the rendering was successful and the fallback was not invoked.
+ */
+ renderContent: function( placement ) {
+ var partial = this, content, newContainerElement, errorMessageElement;
+ if ( ! placement.container ) {
+ partial.fallback( new Error( 'no_container' ), [ placement ] );
+ return false;
+ }
+ placement.container = $( placement.container );
+ if ( false === placement.addedContent ) {
+ partial.fallback( new Error( 'missing_render' ), [ placement ] );
+ return false;
+ }
+
+ // Currently a subclass needs to override renderContent to handle partials returning data object.
+ if ( ! _.isString( placement.addedContent ) ) {
+ partial.fallback( new Error( 'non_string_content' ), [ placement ] );
+ return false;
+ }
+
+ /* jshint ignore:start */
+ self.orginalDocumentWrite = document.write;
+ document.write = function() {
+ throw new Error( self.data.l10n.badDocumentWrite );
+ };
+ /* jshint ignore:end */
+ try {
+ content = placement.addedContent;
+ if ( wp.emoji && wp.emoji.parse && ! $.contains( document.head, placement.container[0] ) ) {
+ content = wp.emoji.parse( content );
+ }
+
+ if ( partial.params.containerInclusive ) {
+
+ // Note that content may be an empty string, and in this case jQuery will just remove the oldContainer
+ newContainerElement = $( content );
+
+ // Merge the new context on top of the old context.
+ placement.context = _.extend(
+ placement.context,
+ newContainerElement.data( 'customize-partial-placement-context' ) || {}
+ );
+ newContainerElement.data( 'customize-partial-placement-context', placement.context );
+
+ placement.removedNodes = placement.container;
+ placement.container = newContainerElement;
+ placement.removedNodes.replaceWith( placement.container );
+ placement.container.attr( 'title', self.data.l10n.shiftClickToEdit );
+ } else {
+ placement.removedNodes = document.createDocumentFragment();
+ while ( placement.container[0].firstChild ) {
+ placement.removedNodes.appendChild( placement.container[0].firstChild );
+ }
+
+ placement.container.html( content );
+ }
+
+ placement.container.removeClass( 'customize-render-content-error' );
+ } catch ( error ) {
+ if ( 'undefined' !== typeof console && console.error ) {
+ console.error( partial.id, error );
+ }
+ placement.container.addClass( 'customize-render-content-error' );
+ errorMessageElement = placement.container.find( '.customize-render-content-error-message:first' );
+ if ( ! errorMessageElement.length ) {
+ errorMessageElement = $( '' );
+ placement.container.append( errorMessageElement );
+ }
+ errorMessageElement.text( self.data.l10n.errorMessageTpl.replace( '%s', error.message ) );
+ }
+ /* jshint ignore:start */
+ document.write = self.orginalDocumentWrite;
+ self.orginalDocumentWrite = null;
+ /* jshint ignore:end */
+
+ placement.container.removeClass( 'customize-partial-refreshing' );
+
+ // Prevent placement container from being being re-triggered as being rendered among nested partials.
+ placement.container.data( 'customize-partial-content-rendered', true );
+
+ /**
+ * Announce when a partial's placement has been rendered so that dynamic elements can be re-built.
+ */
+ self.trigger( 'partial-content-rendered', placement );
+ return true;
+ },
+
+ /**
+ * Handle fail to render partial.
+ *
+ * The first argument is either the failing jqXHR or an Error object, and the second argument is the array of containers.
+ *
+ * @since 4.5.0
+ */
+ fallback: function() {
+ var partial = this;
+ if ( partial.params.fallbackRefresh ) {
+ self.requestFullRefresh();
+ }
+ }
+ } );
+
+ /**
+ * A Placement for a Partial.
+ *
+ * A partial placement is the actual physical representation of a partial for a given context.
+ * It also may have information in relation to how a placement may have just changed.
+ * The placement is conceptually similar to a DOM Range or MutationRecord.
+ *
+ * @class
+ * @augments wp.customize.Class
+ * @since 4.5.0
+ */
+ self.Placement = Placement = api.Class.extend({
+
+ /**
+ * The partial with which the container is associated.
+ *
+ * @param {wp.customize.selectiveRefresh.Partial}
+ */
+ partial: null,
+
+ /**
+ * DOM element which contains the placement's contents.
+ *
+ * This will be null if the startNode and endNode do not point to the same
+ * DOM element, such as in the case of a sidebar partial.
+ * This container element itself will be replaced for partials that
+ * have containerInclusive param defined as true.
+ */
+ container: null,
+
+ /**
+ * DOM node for the initial boundary of the placement.
+ *
+ * This will normally be the same as endNode since most placements appear as elements.
+ * This is primarily useful for widget sidebars which do not have intrinsic containers, but
+ * for which an HTML comment is output before to mark the starting position.
+ */
+ startNode: null,
+
+ /**
+ * DOM node for the terminal boundary of the placement.
+ *
+ * This will normally be the same as startNode since most placements appear as elements.
+ * This is primarily useful for widget sidebars which do not have intrinsic containers, but
+ * for which an HTML comment is output before to mark the ending position.
+ */
+ endNode: null,
+
+ /**
+ * Context data.
+ *
+ * This provides information about the placement which is included in the request
+ * in order to render the partial properly.
+ *
+ * @param {object}
+ */
+ context: null,
+
+ /**
+ * The content for the partial when refreshed.
+ *
+ * @param {string}
+ */
+ addedContent: null,
+
+ /**
+ * DOM node(s) removed when the partial is refreshed.
+ *
+ * If the partial is containerInclusive, then the removedNodes will be
+ * the single Element that was the partial's former placement. If the
+ * partial is not containerInclusive, then the removedNodes will be a
+ * documentFragment containing the nodes removed.
+ *
+ * @param {Element|DocumentFragment}
+ */
+ removedNodes: null,
+
+ /**
+ * Constructor.
+ *
+ * @since 4.5.0
+ *
+ * @param {object} args
+ * @param {Partial} args.partial
+ * @param {jQuery|Element} [args.container]
+ * @param {Node} [args.startNode]
+ * @param {Node} [args.endNode]
+ * @param {object} [args.context]
+ * @param {string} [args.addedContent]
+ * @param {jQuery|DocumentFragment} [args.removedNodes]
+ */
+ initialize: function( args ) {
+ var placement = this;
+
+ args = _.extend( {}, args || {} );
+ if ( ! args.partial || ! args.partial.extended( Partial ) ) {
+ throw new Error( 'Missing partial' );
+ }
+ args.context = args.context || {};
+ if ( args.container ) {
+ args.container = $( args.container );
+ }
+
+ _.extend( placement, args );
+ }
+
+ });
+
+ /**
+ * Mapping of type names to Partial constructor subclasses.
+ *
+ * @since 4.5.0
+ *
+ * @type {Object.}
+ */
+ self.partialConstructor = {};
+
+ self.partial = new api.Values({ defaultConstructor: Partial });
+
+ /**
+ * Get the POST vars for a Customizer preview request.
+ *
+ * @since 4.5.0
+ * @see wp.customize.previewer.query()
+ *
+ * @return {object}
+ */
+ self.getCustomizeQuery = function() {
+ var dirtyCustomized = {};
+ api.each( function( value, key ) {
+ if ( value._dirty ) {
+ dirtyCustomized[ key ] = value();
+ }
+ } );
+
+ return {
+ wp_customize: 'on',
+ nonce: api.settings.nonce.preview,
+ theme: api.settings.theme.stylesheet,
+ customized: JSON.stringify( dirtyCustomized )
+ };
+ };
+
+ /**
+ * Currently-requested partials and their associated deferreds.
+ *
+ * @since 4.5.0
+ * @type {Object}
+ */
+ self._pendingPartialRequests = {};
+
+ /**
+ * Timeout ID for the current requesr, or null if no request is current.
+ *
+ * @since 4.5.0
+ * @type {number|null}
+ * @private
+ */
+ self._debouncedTimeoutId = null;
+
+ /**
+ * Current jqXHR for the request to the partials.
+ *
+ * @since 4.5.0
+ * @type {jQuery.jqXHR|null}
+ * @private
+ */
+ self._currentRequest = null;
+
+ /**
+ * Request full page refresh.
+ *
+ * When selective refresh is embedded in the context of frontend editing, this request
+ * must fail or else changes will be lost, unless transactions are implemented.
+ *
+ * @since 4.5.0
+ */
+ self.requestFullRefresh = function() {
+ api.preview.send( 'refresh' );
+ };
+
+ /**
+ * Request a re-rendering of a partial.
+ *
+ * @since 4.5.0
+ *
+ * @param {wp.customize.selectiveRefresh.Partial} partial
+ * @return {jQuery.Promise}
+ */
+ self.requestPartial = function( partial ) {
+ var partialRequest;
+
+ if ( self._debouncedTimeoutId ) {
+ clearTimeout( self._debouncedTimeoutId );
+ self._debouncedTimeoutId = null;
+ }
+ if ( self._currentRequest ) {
+ self._currentRequest.abort();
+ self._currentRequest = null;
+ }
+
+ partialRequest = self._pendingPartialRequests[ partial.id ];
+ if ( ! partialRequest || 'pending' !== partialRequest.deferred.state() ) {
+ partialRequest = {
+ deferred: $.Deferred(),
+ partial: partial
+ };
+ self._pendingPartialRequests[ partial.id ] = partialRequest;
+ }
+
+ // Prevent leaking partial into debounced timeout callback.
+ partial = null;
+
+ self._debouncedTimeoutId = setTimeout(
+ function() {
+ var data, partialPlacementContexts, partialsPlacements, request;
+
+ self._debouncedTimeoutId = null;
+ data = self.getCustomizeQuery();
+
+ /*
+ * It is key that the containers be fetched exactly at the point of the request being
+ * made, because the containers need to be mapped to responses by array indices.
+ */
+ partialsPlacements = {};
+
+ partialPlacementContexts = {};
+
+ _.each( self._pendingPartialRequests, function( pending, partialId ) {
+ partialsPlacements[ partialId ] = pending.partial.placements();
+ if ( ! self.partial.has( partialId ) ) {
+ pending.deferred.rejectWith( pending.partial, [ new Error( 'partial_removed' ), partialsPlacements[ partialId ] ] );
+ } else {
+ /*
+ * Note that this may in fact be an empty array. In that case, it is the responsibility
+ * of the Partial subclass instance to know where to inject the response, or else to
+ * just issue a refresh (default behavior). The data being returned with each container
+ * is the context information that may be needed to render certain partials, such as
+ * the contained sidebar for rendering widgets or what the nav menu args are for a menu.
+ */
+ partialPlacementContexts[ partialId ] = _.map( partialsPlacements[ partialId ], function( placement ) {
+ return placement.context || {};
+ } );
+ }
+ } );
+
+ data.partials = JSON.stringify( partialPlacementContexts );
+ data[ self.data.renderQueryVar ] = '1';
+
+ request = self._currentRequest = wp.ajax.send( null, {
+ data: data,
+ url: api.settings.url.self
+ } );
+
+ request.done( function( data ) {
+
+ /**
+ * Announce the data returned from a request to render partials.
+ *
+ * The data is filtered on the server via customize_render_partials_response
+ * so plugins can inject data from the server to be utilized
+ * on the client via this event. Plugins may use this filter
+ * to communicate script and style dependencies that need to get
+ * injected into the page to support the rendered partials.
+ * This is similar to the 'saved' event.
+ */
+ self.trigger( 'render-partials-response', data );
+
+ // Relay errors (warnings) captured during rendering and relay to console.
+ if ( data.errors && 'undefined' !== typeof console && console.warn ) {
+ _.each( data.errors, function( error ) {
+ console.warn( error );
+ } );
+ }
+
+ /*
+ * Note that data is an array of items that correspond to the array of
+ * containers that were submitted in the request. So we zip up the
+ * array of containers with the array of contents for those containers,
+ * and send them into .
+ */
+ _.each( self._pendingPartialRequests, function( pending, partialId ) {
+ var placementsContents;
+ if ( ! _.isArray( data.contents[ partialId ] ) ) {
+ pending.deferred.rejectWith( pending.partial, [ new Error( 'unrecognized_partial' ), partialsPlacements[ partialId ] ] );
+ } else {
+ placementsContents = _.map( data.contents[ partialId ], function( content, i ) {
+ var partialPlacement = partialsPlacements[ partialId ][ i ];
+ if ( partialPlacement ) {
+ partialPlacement.addedContent = content;
+ } else {
+ partialPlacement = new Placement( {
+ partial: pending.partial,
+ addedContent: content
+ } );
+ }
+ return partialPlacement;
+ } );
+ pending.deferred.resolveWith( pending.partial, [ placementsContents ] );
+ }
+ } );
+ self._pendingPartialRequests = {};
+ } );
+
+ request.fail( function( data, statusText ) {
+
+ /*
+ * Ignore failures caused by partial.currentRequest.abort()
+ * The pending deferreds will remain in self._pendingPartialRequests
+ * for re-use with the next request.
+ */
+ if ( 'abort' === statusText ) {
+ return;
+ }
+
+ _.each( self._pendingPartialRequests, function( pending, partialId ) {
+ pending.deferred.rejectWith( pending.partial, [ data, partialsPlacements[ partialId ] ] );
+ } );
+ self._pendingPartialRequests = {};
+ } );
+ },
+ self.data.refreshBuffer
+ );
+
+ return partialRequest.deferred.promise();
+ };
+
+ /**
+ * Add partials for any nav menu container elements in the document.
+ *
+ * This method may be called multiple times. Containers that already have been
+ * seen will be skipped.
+ *
+ * @since 4.5.0
+ *
+ * @param {jQuery|HTMLElement} [rootElement]
+ * @param {object} [options]
+ * @param {boolean=true} [options.triggerRendered]
+ */
+ self.addPartials = function( rootElement, options ) {
+ var containerElements;
+ if ( ! rootElement ) {
+ rootElement = document.documentElement;
+ }
+ rootElement = $( rootElement );
+ options = _.extend(
+ {
+ triggerRendered: true
+ },
+ options || {}
+ );
+
+ containerElements = rootElement.find( '[data-customize-partial-id]' );
+ if ( rootElement.is( '[data-customize-partial-id]' ) ) {
+ containerElements = containerElements.add( rootElement );
+ }
+ containerElements.each( function() {
+ var containerElement = $( this ), partial, id, Constructor, partialOptions, containerContext;
+ id = containerElement.data( 'customize-partial-id' );
+ if ( ! id ) {
+ return;
+ }
+ containerContext = containerElement.data( 'customize-partial-placement-context' ) || {};
+
+ partial = self.partial( id );
+ if ( ! partial ) {
+ partialOptions = containerElement.data( 'customize-partial-options' ) || {};
+ partialOptions.constructingContainerContext = containerElement.data( 'customize-partial-placement-context' ) || {};
+ Constructor = self.partialConstructor[ containerElement.data( 'customize-partial-type' ) ] || self.Partial;
+ partial = new Constructor( id, partialOptions );
+ self.partial.add( partial.id, partial );
+ }
+
+ /*
+ * Only trigger renders on (nested) partials that have been not been
+ * handled yet. An example where this would apply is a nav menu
+ * embedded inside of a custom menu widget. When the widget's title
+ * is updated, the entire widget will re-render and then the event
+ * will be triggered for the nested nav menu to do any initialization.
+ */
+ if ( options.triggerRendered && ! containerElement.data( 'customize-partial-content-rendered' ) ) {
+
+ /**
+ * Announce when a partial's nested placement has been re-rendered.
+ */
+ self.trigger( 'partial-content-rendered', new Placement( {
+ partial: partial,
+ context: containerContext,
+ container: containerElement
+ } ) );
+ }
+ containerElement.data( 'customize-partial-content-rendered', true );
+ } );
+ };
+
+ api.bind( 'preview-ready', function() {
+ var handleSettingChange, watchSettingChange, unwatchSettingChange;
+
+ // Polyfill for IE8 to support the document.head attribute.
+ if ( ! document.head ) {
+ document.head = $( 'head:first' )[0];
+ }
+
+ _.extend( self.data, _customizePartialRefreshExports );
+
+ // Create the partial JS models.
+ _.each( self.data.partials, function( data, id ) {
+ var Constructor, partial = self.partial( id );
+ if ( ! partial ) {
+ Constructor = self.partialConstructor[ data.type ] || self.Partial;
+ partial = new Constructor( id, { params: data } );
+ self.partial.add( id, partial );
+ } else {
+ _.extend( partial.params, data );
+ }
+ } );
+
+ /**
+ * Handle change to a setting.
+ *
+ * Note this is largely needed because adding a 'change' event handler to wp.customize
+ * will only include the changed setting object as an argument, not including the
+ * new value or the old value.
+ *
+ * @since 4.5.0
+ * @this {wp.customize.Setting}
+ *
+ * @param {*|null} newValue New value, or null if the setting was just removed.
+ * @param {*|null} oldValue Old value, or null if the setting was just added.
+ */
+ handleSettingChange = function( newValue, oldValue ) {
+ var setting = this;
+ self.partial.each( function( partial ) {
+ if ( partial.isRelatedSetting( setting, newValue, oldValue ) ) {
+ partial.refresh();
+ }
+ } );
+ };
+
+ /**
+ * Trigger the initial change for the added setting, and watch for changes.
+ *
+ * @since 4.5.0
+ * @this {wp.customize.Values}
+ *
+ * @param {wp.customize.Setting} setting
+ */
+ watchSettingChange = function( setting ) {
+ handleSettingChange.call( setting, setting(), null );
+ setting.bind( handleSettingChange );
+ };
+
+ /**
+ * Trigger the final change for the removed setting, and unwatch for changes.
+ *
+ * @since 4.5.0
+ * @this {wp.customize.Values}
+ *
+ * @param {wp.customize.Setting} setting
+ */
+ unwatchSettingChange = function( setting ) {
+ handleSettingChange.call( setting, null, setting() );
+ setting.unbind( handleSettingChange );
+ };
+
+ api.bind( 'add', watchSettingChange );
+ api.bind( 'remove', unwatchSettingChange );
+ api.each( function( setting ) {
+ setting.bind( handleSettingChange );
+ } );
+
+ // Add (dynamic) initial partials that are declared via data-* attributes.
+ self.addPartials( document.documentElement, {
+ triggerRendered: false
+ } );
+
+ // Add new dynamic partials when the document changes.
+ if ( 'undefined' !== typeof MutationObserver ) {
+ self.mutationObserver = new MutationObserver( function( mutations ) {
+ _.each( mutations, function( mutation ) {
+ self.addPartials( $( mutation.target ) );
+ } );
+ } );
+ self.mutationObserver.observe( document.documentElement, {
+ childList: true,
+ subtree: true
+ } );
+ }
+
+ /**
+ * Handle rendering of partials.
+ *
+ * @param {api.selectiveRefresh.Placement} placement
+ */
+ api.selectiveRefresh.bind( 'partial-content-rendered', function( placement ) {
+ if ( placement.container ) {
+ self.addPartials( placement.container );
+ }
+ } );
+
+ api.preview.bind( 'active', function() {
+
+ // Make all partials ready.
+ self.partial.each( function( partial ) {
+ partial.deferred.ready.resolve();
+ } );
+
+ // Make all partials added henceforth as ready upon add.
+ self.partial.bind( 'add', function( partial ) {
+ partial.deferred.ready.resolve();
+ } );
+ } );
+
+ } );
+
+ return self;
+}( jQuery, wp.customize ) );
diff --git a/wp-includes/js/customize-selective-refresh.min.js b/wp-includes/js/customize-selective-refresh.min.js
new file mode 100644
index 0000000000..d11373767f
--- /dev/null
+++ b/wp-includes/js/customize-selective-refresh.min.js
@@ -0,0 +1 @@
+wp.customize.selectiveRefresh=function(a,b){"use strict";var c,d,e;return c={ready:a.Deferred(),data:{partials:{},renderQueryVar:"",l10n:{shiftClickToEdit:""},refreshBuffer:250},currentRequest:null},_.extend(c,b.Events),d=c.Partial=b.Class.extend({id:null,initialize:function(b,c){var d=this;c=c||{},d.id=b,d.params=_.extend({selector:null,settings:[],primarySetting:null,containerInclusive:!1,fallbackRefresh:!0},c.params||{}),d.deferred={},d.deferred.ready=a.Deferred(),d.deferred.ready.done(function(){d.ready()})},ready:function(){var b=this;_.each(_.pluck(b.placements(),"container"),function(b){a(b).attr("title",c.data.l10n.shiftClickToEdit)}),a(document).on("click",b.params.selector,function(c){c.shiftKey&&(c.preventDefault(),_.each(b.placements(),function(d){a(d.container).is(c.currentTarget)&&b.showControl()}))})},placements:function(){var b,c=this;return b=c.params.selector,b&&(b+=", "),b+='[data-customize-partial-id="'+c.id+'"]',a(b).map(function(){var b,d=a(this);if(b=d.data("customize-partial-placement-context"),_.isString(b)&&"{"===b.substr(0,1))throw new Error("context JSON parse error");return new e({partial:c,container:d,context:b})}).get()},settings:function(){var a=this;return a.params.settings&&0!==a.params.settings.length?a.params.settings:a.params.primarySetting?[a.params.primarySetting]:[a.id]},isRelatedSetting:function(a){var c=this;return _.isString(a)&&(a=b(a)),a?-1!==_.indexOf(c.settings(),a.id):!1},showControl:function(){var a=this,c=a.params.primarySetting;c||(c=_.first(a.settings())),b.preview.send("focus-control-for-setting",c)},preparePlacement:function(b){a(b.container).addClass("customize-partial-refreshing")},_pendingRefreshPromise:null,refresh:function(){var a,b=this;return a=c.requestPartial(b),b._pendingRefreshPromise||(_.each(b.placements(),function(a){b.preparePlacement(a)}),a.done(function(a){_.each(a,function(a){b.renderContent(a)})}),a.fail(function(a,c){b.fallback(a,c)}),b._pendingRefreshPromise=a,a.always(function(){b._pendingRefreshPromise=null})),a},renderContent:function(b){var d,e,f,g=this;if(!b.container)return g.fallback(new Error("no_container"),[b]),!1;if(b.container=a(b.container),!1===b.addedContent)return g.fallback(new Error("missing_render"),[b]),!1;if(!_.isString(b.addedContent))return g.fallback(new Error("non_string_content"),[b]),!1;c.orginalDocumentWrite=document.write,document.write=function(){throw new Error(c.data.l10n.badDocumentWrite)};try{if(d=b.addedContent,wp.emoji&&wp.emoji.parse&&!a.contains(document.head,b.container[0])&&(d=wp.emoji.parse(d)),g.params.containerInclusive)e=a(d),b.context=_.extend(b.context,e.data("customize-partial-placement-context")||{}),e.data("customize-partial-placement-context",b.context),b.removedNodes=b.container,b.container=e,b.removedNodes.replaceWith(b.container),b.container.attr("title",c.data.l10n.shiftClickToEdit);else{for(b.removedNodes=document.createDocumentFragment();b.container[0].firstChild;)b.removedNodes.appendChild(b.container[0].firstChild);b.container.html(d)}b.container.removeClass("customize-render-content-error")}catch(h){"undefined"!=typeof console&&console.error&&console.error(g.id,h),b.container.addClass("customize-render-content-error"),f=b.container.find(".customize-render-content-error-message:first"),f.length||(f=a(''),b.container.append(f)),f.text(c.data.l10n.errorMessageTpl.replace("%s",h.message))}return document.write=c.orginalDocumentWrite,c.orginalDocumentWrite=null,b.container.removeClass("customize-partial-refreshing"),b.container.data("customize-partial-content-rendered",!0),c.trigger("partial-content-rendered",b),!0},fallback:function(){var a=this;a.params.fallbackRefresh&&c.requestFullRefresh()}}),c.Placement=e=b.Class.extend({partial:null,container:null,startNode:null,endNode:null,context:null,addedContent:null,removedNodes:null,initialize:function(b){var c=this;if(b=_.extend({},b||{}),!b.partial||!b.partial.extended(d))throw new Error("Missing partial");b.context=b.context||{},b.container&&(b.container=a(b.container)),_.extend(c,b)}}),c.partialConstructor={},c.partial=new b.Values({defaultConstructor:d}),c.getCustomizeQuery=function(){var a={};return b.each(function(b,c){b._dirty&&(a[c]=b())}),{wp_customize:"on",nonce:b.settings.nonce.preview,theme:b.settings.theme.stylesheet,customized:JSON.stringify(a)}},c._pendingPartialRequests={},c._debouncedTimeoutId=null,c._currentRequest=null,c.requestFullRefresh=function(){b.preview.send("refresh")},c.requestPartial=function(d){var f;return c._debouncedTimeoutId&&(clearTimeout(c._debouncedTimeoutId),c._debouncedTimeoutId=null),c._currentRequest&&(c._currentRequest.abort(),c._currentRequest=null),f=c._pendingPartialRequests[d.id],f&&"pending"===f.deferred.state()||(f={deferred:a.Deferred(),partial:d},c._pendingPartialRequests[d.id]=f),d=null,c._debouncedTimeoutId=setTimeout(function(){var a,d,f,g;c._debouncedTimeoutId=null,a=c.getCustomizeQuery(),f={},d={},_.each(c._pendingPartialRequests,function(a,b){f[b]=a.partial.placements(),c.partial.has(b)?d[b]=_.map(f[b],function(a){return a.context||{}}):a.deferred.rejectWith(a.partial,[new Error("partial_removed"),f[b]])}),a.partials=JSON.stringify(d),a[c.data.renderQueryVar]="1",g=c._currentRequest=wp.ajax.send(null,{data:a,url:b.settings.url.self}),g.done(function(a){c.trigger("render-partials-response",a),a.errors&&"undefined"!=typeof console&&console.warn&&_.each(a.errors,function(a){console.warn(a)}),_.each(c._pendingPartialRequests,function(b,c){var d;_.isArray(a.contents[c])?(d=_.map(a.contents[c],function(a,d){var g=f[c][d];return g?g.addedContent=a:g=new e({partial:b.partial,addedContent:a}),g}),b.deferred.resolveWith(b.partial,[d])):b.deferred.rejectWith(b.partial,[new Error("unrecognized_partial"),f[c]])}),c._pendingPartialRequests={}}),g.fail(function(a,b){"abort"!==b&&(_.each(c._pendingPartialRequests,function(b,c){b.deferred.rejectWith(b.partial,[a,f[c]])}),c._pendingPartialRequests={})})},c.data.refreshBuffer),f.deferred.promise()},c.addPartials=function(b,d){var f;b||(b=document.documentElement),b=a(b),d=_.extend({triggerRendered:!0},d||{}),f=b.find("[data-customize-partial-id]"),b.is("[data-customize-partial-id]")&&(f=f.add(b)),f.each(function(){var b,f,g,h,i,j=a(this);f=j.data("customize-partial-id"),f&&(i=j.data("customize-partial-placement-context")||{},b=c.partial(f),b||(h=j.data("customize-partial-options")||{},h.constructingContainerContext=j.data("customize-partial-placement-context")||{},g=c.partialConstructor[j.data("customize-partial-type")]||c.Partial,b=new g(f,h),c.partial.add(b.id,b)),d.triggerRendered&&!j.data("customize-partial-content-rendered")&&c.trigger("partial-content-rendered",new e({partial:b,context:i,container:j})),j.data("customize-partial-content-rendered",!0))})},b.bind("preview-ready",function(){var d,e,f;document.head||(document.head=a("head:first")[0]),_.extend(c.data,_customizePartialRefreshExports),_.each(c.data.partials,function(a,b){var d,e=c.partial(b);e?_.extend(e.params,a):(d=c.partialConstructor[a.type]||c.Partial,e=new d(b,{params:a}),c.partial.add(b,e))}),d=function(a,b){var d=this;c.partial.each(function(c){c.isRelatedSetting(d,a,b)&&c.refresh()})},e=function(a){d.call(a,a(),null),a.bind(d)},f=function(a){d.call(a,null,a()),a.unbind(d)},b.bind("add",e),b.bind("remove",f),b.each(function(a){a.bind(d)}),c.addPartials(document.documentElement,{triggerRendered:!1}),"undefined"!=typeof MutationObserver&&(c.mutationObserver=new MutationObserver(function(b){_.each(b,function(b){c.addPartials(a(b.target))})}),c.mutationObserver.observe(document.documentElement,{childList:!0,subtree:!0})),b.selectiveRefresh.bind("partial-content-rendered",function(a){a.container&&c.addPartials(a.container)}),b.preview.bind("active",function(){c.partial.each(function(a){a.deferred.ready.resolve()}),c.partial.bind("add",function(a){a.deferred.ready.resolve()})})}),c}(jQuery,wp.customize);
\ No newline at end of file
diff --git a/wp-includes/script-loader.php b/wp-includes/script-loader.php
index 1a9d259103..01be0f5608 100644
--- a/wp-includes/script-loader.php
+++ b/wp-includes/script-loader.php
@@ -447,6 +447,7 @@ function wp_default_scripts( &$scripts ) {
// Used for overriding the file types allowed in plupload.
'allowedFiles' => __( 'Allowed Files' ),
) );
+ $scripts->add( 'customize-selective-refresh', "/wp-includes/js/customize-selective-refresh$suffix.js", array( 'jquery', 'wp-util', 'customize-preview' ), false, 1 );
$scripts->add( 'customize-widgets', "/wp-admin/js/customize-widgets$suffix.js", array( 'jquery', 'jquery-ui-sortable', 'jquery-ui-droppable', 'wp-backbone', 'customize-controls' ), false, 1 );
$scripts->add( 'customize-preview-widgets', "/wp-includes/js/customize-preview-widgets$suffix.js", array( 'jquery', 'wp-util', 'customize-preview' ), false, 1 );
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 69798d7287..5baee7b603 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -4,7 +4,7 @@
*
* @global string $wp_version
*/
-$wp_version = '4.5-alpha-36585';
+$wp_version = '4.5-alpha-36586';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.