| | |
| | |
| | |
| |
|
| | |
| | (function( wp, $ ){ |
| |
|
| | if ( ! wp || ! wp.customize ) { return; } |
| |
|
| | |
| | var api = wp.customize, |
| | l10n; |
| |
|
| | |
| | |
| | |
| | api.Widgets = api.Widgets || {}; |
| | api.Widgets.savedWidgetIds = {}; |
| |
|
| | |
| | api.Widgets.data = _wpCustomizeWidgetsSettings || {}; |
| | l10n = api.Widgets.data.l10n; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | api.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: null, |
| | params: [], |
| | width: null, |
| | height: null, |
| | search_matched: true |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | api.Widgets.WidgetCollection = Backbone.Collection.extend({ |
| | model: api.Widgets.WidgetModel, |
| |
|
| | |
| | |
| | doSearch: function( value ) { |
| |
|
| | |
| | |
| | if ( this.terms === value ) { |
| | return; |
| | } |
| |
|
| | |
| | this.terms = value; |
| |
|
| | |
| | if ( this.terms.length > 0 ) { |
| | this.search( this.terms ); |
| | } |
| |
|
| | |
| | if ( this.terms === '' ) { |
| | this.each( function ( widget ) { |
| | widget.set( 'search_matched', true ); |
| | } ); |
| | } |
| | }, |
| |
|
| | |
| | |
| | search: function( term ) { |
| | var match, haystack; |
| |
|
| | |
| | term = term.replace( /[-\/\\^$*+?.()|[\]{}]/g, '\\$&' ); |
| |
|
| | |
| | |
| | term = term.replace( / /g, ')(?=.*' ); |
| | match = new RegExp( '^(?=.*' + term + ').+', 'i' ); |
| |
|
| | this.each( function ( data ) { |
| | haystack = [ data.get( 'name' ), data.get( 'description' ) ].join( ' ' ); |
| | data.set( 'search_matched', match.test( haystack ) ); |
| | } ); |
| | } |
| | }); |
| | api.Widgets.availableWidgets = new api.Widgets.WidgetCollection( api.Widgets.data.availableWidgets ); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | api.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: false |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | api.Widgets.SidebarCollection = Backbone.Collection.extend({ |
| | model: api.Widgets.SidebarModel |
| | }); |
| | api.Widgets.registeredSidebars = new api.Widgets.SidebarCollection( api.Widgets.data.registeredSidebars ); |
| |
|
| | api.Widgets.AvailableWidgetsPanelView = wp.Backbone.View.extend({ |
| |
|
| | el: '#available-widgets', |
| |
|
| | events: { |
| | 'input #widgets-search': 'search', |
| | 'focus .widget-tpl' : 'focus', |
| | 'click .widget-tpl' : '_submit', |
| | 'keypress .widget-tpl' : '_submit', |
| | 'keydown' : 'keyboardAccessible' |
| | }, |
| |
|
| | |
| | selected: null, |
| |
|
| | |
| | currentSidebarControl: null, |
| | $search: null, |
| | $clearResults: null, |
| | searchMatchesCount: null, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | initialize: function() { |
| | var self = this; |
| |
|
| | this.$search = $( '#widgets-search' ); |
| |
|
| | this.$clearResults = this.$el.find( '.clear-results' ); |
| |
|
| | _.bindAll( this, 'close' ); |
| |
|
| | this.listenTo( this.collection, 'change', this.updateList ); |
| |
|
| | this.updateList(); |
| |
|
| | |
| | this.searchMatchesCount = this.collection.length; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | $( '#customize-controls, #available-widgets .customize-section-title' ).on( 'click keydown', function( e ) { |
| | var isAddNewBtn = $( e.target ).is( '.add-new-widget, .add-new-widget *' ); |
| | if ( $( 'body' ).hasClass( 'adding-widget' ) && ! isAddNewBtn ) { |
| | self.close(); |
| | } |
| | } ); |
| |
|
| | |
| | this.$clearResults.on( 'click', function() { |
| | self.$search.val( '' ).trigger( 'focus' ).trigger( 'input' ); |
| | } ); |
| |
|
| | |
| | api.previewer.bind( 'url', this.close ); |
| | }, |
| |
|
| | |
| | |
| | |
| | search: _.debounce( function( event ) { |
| | var firstVisible; |
| |
|
| | this.collection.doSearch( event.target.value ); |
| | |
| | this.updateSearchMatchesCount(); |
| | |
| | this.announceSearchMatches(); |
| |
|
| | |
| | if ( this.selected && ! this.selected.is( ':visible' ) ) { |
| | this.selected.removeClass( 'selected' ); |
| | this.selected = null; |
| | } |
| |
|
| | |
| | if ( this.selected && ! event.target.value ) { |
| | this.selected.removeClass( 'selected' ); |
| | this.selected = null; |
| | } |
| |
|
| | |
| | if ( ! this.selected && event.target.value ) { |
| | firstVisible = this.$el.find( '> .widget-tpl:visible:first' ); |
| | if ( firstVisible.length ) { |
| | this.select( firstVisible ); |
| | } |
| | } |
| |
|
| | |
| | if ( '' !== event.target.value ) { |
| | this.$clearResults.addClass( 'is-visible' ); |
| | } else if ( '' === event.target.value ) { |
| | this.$clearResults.removeClass( 'is-visible' ); |
| | } |
| |
|
| | |
| | if ( ! this.searchMatchesCount ) { |
| | this.$el.addClass( 'no-widgets-found' ); |
| | } else { |
| | this.$el.removeClass( 'no-widgets-found' ); |
| | } |
| | }, 500 ), |
| |
|
| | |
| | |
| | |
| | updateSearchMatchesCount: function() { |
| | this.searchMatchesCount = this.collection.where({ search_matched: true }).length; |
| | }, |
| |
|
| | |
| | |
| | |
| | announceSearchMatches: function() { |
| | var message = l10n.widgetsFound.replace( '%d', this.searchMatchesCount ) ; |
| |
|
| | if ( ! this.searchMatchesCount ) { |
| | message = l10n.noWidgetsFound; |
| | } |
| |
|
| | wp.a11y.speak( message ); |
| | }, |
| |
|
| | |
| | |
| | |
| | updateList: function() { |
| | this.collection.each( function( widget ) { |
| | var widgetTpl = $( '#widget-tpl-' + widget.id ); |
| | widgetTpl.toggle( widget.get( 'search_matched' ) && ! widget.get( 'is_disabled' ) ); |
| | if ( widget.get( 'is_disabled' ) && widgetTpl.is( this.selected ) ) { |
| | this.selected = null; |
| | } |
| | } ); |
| | }, |
| |
|
| | |
| | |
| | |
| | select: function( widgetTpl ) { |
| | this.selected = $( widgetTpl ); |
| | this.selected.siblings( '.widget-tpl' ).removeClass( 'selected' ); |
| | this.selected.addClass( 'selected' ); |
| | }, |
| |
|
| | |
| | |
| | |
| | focus: function( event ) { |
| | this.select( $( event.currentTarget ) ); |
| | }, |
| |
|
| | |
| | |
| | |
| | _submit: function( event ) { |
| | |
| | if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) { |
| | return; |
| | } |
| |
|
| | this.submit( $( event.currentTarget ) ); |
| | }, |
| |
|
| | |
| | |
| | |
| | submit: function( widgetTpl ) { |
| | var widgetId, widget, widgetFormControl; |
| |
|
| | if ( ! widgetTpl ) { |
| | widgetTpl = this.selected; |
| | } |
| |
|
| | if ( ! widgetTpl || ! this.currentSidebarControl ) { |
| | return; |
| | } |
| |
|
| | this.select( widgetTpl ); |
| |
|
| | widgetId = $( this.selected ).data( 'widget-id' ); |
| | widget = this.collection.findWhere( { id: widgetId } ); |
| | if ( ! widget ) { |
| | return; |
| | } |
| |
|
| | widgetFormControl = this.currentSidebarControl.addWidget( widget.get( 'id_base' ) ); |
| | if ( widgetFormControl ) { |
| | widgetFormControl.focus(); |
| | } |
| |
|
| | this.close(); |
| | }, |
| |
|
| | |
| | |
| | |
| | open: function( sidebarControl ) { |
| | this.currentSidebarControl = sidebarControl; |
| |
|
| | |
| | _( this.currentSidebarControl.getWidgetFormControls() ).each( function( control ) { |
| | if ( control.params.is_wide ) { |
| | control.collapseForm(); |
| | } |
| | } ); |
| |
|
| | if ( api.section.has( 'publish_settings' ) ) { |
| | api.section( 'publish_settings' ).collapse(); |
| | } |
| |
|
| | $( 'body' ).addClass( 'adding-widget' ); |
| |
|
| | this.$el.find( '.selected' ).removeClass( 'selected' ); |
| |
|
| | |
| | this.collection.doSearch( '' ); |
| |
|
| | if ( ! api.settings.browser.mobile ) { |
| | this.$search.trigger( 'focus' ); |
| | } |
| | }, |
| |
|
| | |
| | |
| | |
| | close: function( options ) { |
| | options = options || {}; |
| |
|
| | if ( options.returnFocus && this.currentSidebarControl ) { |
| | this.currentSidebarControl.container.find( '.add-new-widget' ).focus(); |
| | } |
| |
|
| | this.currentSidebarControl = null; |
| | this.selected = null; |
| |
|
| | $( 'body' ).removeClass( 'adding-widget' ); |
| |
|
| | this.$search.val( '' ).trigger( 'input' ); |
| | }, |
| |
|
| | |
| | |
| | |
| | keyboardAccessible: function( event ) { |
| | var isEnter = ( event.which === 13 ), |
| | isEsc = ( event.which === 27 ), |
| | isDown = ( event.which === 40 ), |
| | isUp = ( event.which === 38 ), |
| | isTab = ( event.which === 9 ), |
| | isShift = ( event.shiftKey ), |
| | selected = null, |
| | firstVisible = this.$el.find( '> .widget-tpl:visible:first' ), |
| | lastVisible = this.$el.find( '> .widget-tpl:visible:last' ), |
| | isSearchFocused = $( event.target ).is( this.$search ), |
| | isLastWidgetFocused = $( event.target ).is( '.widget-tpl:visible:last' ); |
| |
|
| | if ( isDown || isUp ) { |
| | if ( isDown ) { |
| | if ( isSearchFocused ) { |
| | selected = firstVisible; |
| | } else if ( this.selected && this.selected.nextAll( '.widget-tpl:visible' ).length !== 0 ) { |
| | selected = this.selected.nextAll( '.widget-tpl:visible:first' ); |
| | } |
| | } else if ( isUp ) { |
| | if ( isSearchFocused ) { |
| | selected = lastVisible; |
| | } else if ( this.selected && this.selected.prevAll( '.widget-tpl:visible' ).length !== 0 ) { |
| | selected = this.selected.prevAll( '.widget-tpl:visible:first' ); |
| | } |
| | } |
| |
|
| | this.select( selected ); |
| |
|
| | if ( selected ) { |
| | selected.trigger( 'focus' ); |
| | } else { |
| | this.$search.trigger( 'focus' ); |
| | } |
| |
|
| | return; |
| | } |
| |
|
| | |
| | if ( isEnter && ! this.$search.val() ) { |
| | return; |
| | } |
| |
|
| | if ( isEnter ) { |
| | this.submit(); |
| | } else if ( isEsc ) { |
| | this.close( { returnFocus: true } ); |
| | } |
| |
|
| | if ( this.currentSidebarControl && isTab && ( isShift && isSearchFocused || ! isShift && isLastWidgetFocused ) ) { |
| | this.currentSidebarControl.container.find( '.add-new-widget' ).focus(); |
| | event.preventDefault(); |
| | } |
| | } |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | api.Widgets.formSyncHandlers = { |
| |
|
| | |
| | |
| | |
| | |
| | |
| | rss: function( e, widget, newForm ) { |
| | var oldWidgetError = widget.find( '.widget-error:first' ), |
| | newWidgetError = $( '<div>' + newForm + '</div>' ).find( '.widget-error:first' ); |
| |
|
| | if ( oldWidgetError.length && newWidgetError.length ) { |
| | oldWidgetError.replaceWith( newWidgetError ); |
| | } else if ( oldWidgetError.length ) { |
| | oldWidgetError.remove(); |
| | } else if ( newWidgetError.length ) { |
| | widget.find( '.widget-content:first' ).prepend( newWidgetError ); |
| | } |
| | } |
| | }; |
| |
|
| | api.Widgets.WidgetControl = api.Control.extend({ |
| | defaultExpandedArguments: { |
| | duration: 'fast', |
| | completeCallback: $.noop |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | initialize: function( id, options ) { |
| | var control = this; |
| |
|
| | control.widgetControlEmbedded = false; |
| | control.widgetContentEmbedded = false; |
| | control.expanded = new api.Value( false ); |
| | control.expandedArgumentsQueue = []; |
| | control.expanded.bind( function( expanded ) { |
| | var args = control.expandedArgumentsQueue.shift(); |
| | args = $.extend( {}, control.defaultExpandedArguments, args ); |
| | control.onChangeExpanded( expanded, args ); |
| | }); |
| | control.altNotice = true; |
| |
|
| | api.Control.prototype.initialize.call( control, id, options ); |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | ready: function() { |
| | var control = this; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | if ( ! control.section() ) { |
| | control.embedWidgetControl(); |
| | } else { |
| | api.section( control.section(), function( section ) { |
| | var onExpanded = function( isExpanded ) { |
| | if ( isExpanded ) { |
| | control.embedWidgetControl(); |
| | section.expanded.unbind( onExpanded ); |
| | } |
| | }; |
| | if ( section.expanded() ) { |
| | onExpanded( true ); |
| | } else { |
| | section.expanded.bind( onExpanded ); |
| | } |
| | } ); |
| | } |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | embedWidgetControl: function() { |
| | var control = this, widgetControl; |
| |
|
| | if ( control.widgetControlEmbedded ) { |
| | return; |
| | } |
| | control.widgetControlEmbedded = true; |
| |
|
| | widgetControl = $( control.params.widget_control ); |
| | control.container.append( widgetControl ); |
| |
|
| | control._setupModel(); |
| | control._setupWideWidget(); |
| | control._setupControlToggle(); |
| |
|
| | control._setupWidgetTitle(); |
| | control._setupReorderUI(); |
| | control._setupHighlightEffects(); |
| | control._setupUpdateUI(); |
| | control._setupRemoveUI(); |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | embedWidgetContent: function() { |
| | var control = this, widgetContent; |
| |
|
| | control.embedWidgetControl(); |
| | if ( control.widgetContentEmbedded ) { |
| | return; |
| | } |
| | control.widgetContentEmbedded = true; |
| |
|
| | |
| | control.notifications.container = control.getNotificationsContainerElement(); |
| | control.notifications.render(); |
| |
|
| | widgetContent = $( control.params.widget_content ); |
| | control.container.find( '.widget-content:first' ).append( widgetContent ); |
| |
|
| | |
| | |
| | |
| | |
| | $( document ).trigger( 'widget-added', [ control.container.find( '.widget:first' ) ] ); |
| |
|
| | }, |
| |
|
| | |
| | |
| | |
| | _setupModel: function() { |
| | var self = this, rememberSavedWidgetId; |
| |
|
| | |
| | rememberSavedWidgetId = function() { |
| | api.Widgets.savedWidgetIds[self.params.widget_id] = true; |
| | }; |
| | api.bind( 'ready', rememberSavedWidgetId ); |
| | api.bind( 'saved', rememberSavedWidgetId ); |
| |
|
| | this._updateCount = 0; |
| | this.isWidgetUpdating = false; |
| | this.liveUpdateMode = true; |
| |
|
| | |
| | this.setting.bind( function( to, from ) { |
| | if ( ! _( from ).isEqual( to ) && ! self.isWidgetUpdating ) { |
| | self.updateWidget( { instance: to } ); |
| | } |
| | } ); |
| | }, |
| |
|
| | |
| | |
| | |
| | _setupWideWidget: function() { |
| | var self = this, $widgetInside, $widgetForm, $customizeSidebar, |
| | $themeControlsContainer, positionWidget; |
| |
|
| | if ( ! this.params.is_wide || $( window ).width() <= 640 ) { |
| | return; |
| | } |
| |
|
| | $widgetInside = this.container.find( '.widget-inside' ); |
| | $widgetForm = $widgetInside.find( '> .form' ); |
| | $customizeSidebar = $( '.wp-full-overlay-sidebar-content:first' ); |
| | this.container.addClass( 'wide-widget-control' ); |
| |
|
| | this.container.find( '.form:first' ).css( { |
| | 'max-width': this.params.width, |
| | 'min-height': this.params.height |
| | } ); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | positionWidget = function() { |
| | var offsetTop = self.container.offset().top, |
| | windowHeight = $( window ).height(), |
| | formHeight = $widgetForm.outerHeight(), |
| | top; |
| | $widgetInside.css( 'max-height', windowHeight ); |
| | top = Math.max( |
| | 0, |
| | Math.min( |
| | Math.max( offsetTop, 0 ), |
| | windowHeight - formHeight |
| | ) |
| | ); |
| | $widgetInside.css( 'top', top ); |
| | }; |
| |
|
| | $themeControlsContainer = $( '#customize-theme-controls' ); |
| | this.container.on( 'expand', function() { |
| | positionWidget(); |
| | $customizeSidebar.on( 'scroll', positionWidget ); |
| | $( window ).on( 'resize', positionWidget ); |
| | $themeControlsContainer.on( 'expanded collapsed', positionWidget ); |
| | } ); |
| | this.container.on( 'collapsed', function() { |
| | $customizeSidebar.off( 'scroll', positionWidget ); |
| | $( window ).off( 'resize', positionWidget ); |
| | $themeControlsContainer.off( 'expanded collapsed', positionWidget ); |
| | } ); |
| |
|
| | |
| | api.each( function( setting ) { |
| | if ( 0 === setting.id.indexOf( 'sidebars_widgets[' ) ) { |
| | setting.bind( function() { |
| | if ( self.container.hasClass( 'expanded' ) ) { |
| | positionWidget(); |
| | } |
| | } ); |
| | } |
| | } ); |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | _setupControlToggle: function() { |
| | var self = this, $closeBtn; |
| |
|
| | this.container.find( '.widget-top' ).on( 'click', function( e ) { |
| | e.preventDefault(); |
| | var sidebarWidgetsControl = self.getSidebarWidgetsControl(); |
| | if ( sidebarWidgetsControl.isReordering ) { |
| | return; |
| | } |
| | self.expanded( ! self.expanded() ); |
| | } ); |
| |
|
| | $closeBtn = this.container.find( '.widget-control-close' ); |
| | $closeBtn.on( 'click', function() { |
| | self.collapse(); |
| | self.container.find( '.widget-top .widget-action:first' ).focus(); |
| | } ); |
| | }, |
| |
|
| | |
| | |
| | |
| | _setupWidgetTitle: function() { |
| | var self = this, updateTitle; |
| |
|
| | updateTitle = function() { |
| | var title = self.setting().title, |
| | inWidgetTitle = self.container.find( '.in-widget-title' ); |
| |
|
| | if ( title ) { |
| | inWidgetTitle.text( ': ' + title ); |
| | } else { |
| | inWidgetTitle.text( '' ); |
| | } |
| | }; |
| | this.setting.bind( updateTitle ); |
| | updateTitle(); |
| | }, |
| |
|
| | |
| | |
| | |
| | _setupReorderUI: function() { |
| | var self = this, selectSidebarItem, $moveWidgetArea, |
| | $reorderNav, updateAvailableSidebars, template; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | selectSidebarItem = function( li ) { |
| | li.siblings( '.selected' ).removeClass( 'selected' ); |
| | li.addClass( 'selected' ); |
| | var isSelfSidebar = ( li.data( 'id' ) === self.params.sidebar_id ); |
| | self.container.find( '.move-widget-btn' ).prop( 'disabled', isSelfSidebar ); |
| | }; |
| |
|
| | |
| | |
| | |
| | this.container.find( '.widget-title-action' ).after( $( api.Widgets.data.tpl.widgetReorderNav ) ); |
| |
|
| |
|
| | template = _.template( api.Widgets.data.tpl.moveWidgetArea ); |
| | $moveWidgetArea = $( template( { |
| | sidebars: _( api.Widgets.registeredSidebars.toArray() ).pluck( 'attributes' ) |
| | } ) |
| | ); |
| | this.container.find( '.widget-top' ).after( $moveWidgetArea ); |
| |
|
| | |
| | |
| | |
| | updateAvailableSidebars = function() { |
| | var $sidebarItems = $moveWidgetArea.find( 'li' ), selfSidebarItem, |
| | renderedSidebarCount = 0; |
| |
|
| | selfSidebarItem = $sidebarItems.filter( function(){ |
| | return $( this ).data( 'id' ) === self.params.sidebar_id; |
| | } ); |
| |
|
| | $sidebarItems.each( function() { |
| | var li = $( this ), |
| | sidebarId, sidebar, sidebarIsRendered; |
| |
|
| | sidebarId = li.data( 'id' ); |
| | sidebar = api.Widgets.registeredSidebars.get( sidebarId ); |
| | sidebarIsRendered = sidebar.get( 'is_rendered' ); |
| |
|
| | li.toggle( sidebarIsRendered ); |
| |
|
| | if ( sidebarIsRendered ) { |
| | renderedSidebarCount += 1; |
| | } |
| |
|
| | if ( li.hasClass( 'selected' ) && ! sidebarIsRendered ) { |
| | selectSidebarItem( selfSidebarItem ); |
| | } |
| | } ); |
| |
|
| | if ( renderedSidebarCount > 1 ) { |
| | self.container.find( '.move-widget' ).show(); |
| | } else { |
| | self.container.find( '.move-widget' ).hide(); |
| | } |
| | }; |
| |
|
| | updateAvailableSidebars(); |
| | api.Widgets.registeredSidebars.on( 'change:is_rendered', updateAvailableSidebars ); |
| |
|
| | |
| | |
| | |
| | $reorderNav = this.container.find( '.widget-reorder-nav' ); |
| | $reorderNav.find( '.move-widget, .move-widget-down, .move-widget-up' ).each( function() { |
| | $( this ).prepend( self.container.find( '.widget-title' ).text() + ': ' ); |
| | } ).on( 'click keypress', function( event ) { |
| | if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) { |
| | return; |
| | } |
| | $( this ).trigger( 'focus' ); |
| |
|
| | if ( $( this ).is( '.move-widget' ) ) { |
| | self.toggleWidgetMoveArea(); |
| | } else { |
| | var isMoveDown = $( this ).is( '.move-widget-down' ), |
| | isMoveUp = $( this ).is( '.move-widget-up' ), |
| | i = self.getWidgetSidebarPosition(); |
| |
|
| | if ( ( isMoveUp && i === 0 ) || ( isMoveDown && i === self.getSidebarWidgetsControl().setting().length - 1 ) ) { |
| | return; |
| | } |
| |
|
| | if ( isMoveUp ) { |
| | self.moveUp(); |
| | wp.a11y.speak( l10n.widgetMovedUp ); |
| | } else { |
| | self.moveDown(); |
| | wp.a11y.speak( l10n.widgetMovedDown ); |
| | } |
| |
|
| | $( this ).trigger( 'focus' ); |
| | } |
| | } ); |
| |
|
| | |
| | |
| | |
| | this.container.find( '.widget-area-select' ).on( 'click keypress', 'li', function( event ) { |
| | if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) { |
| | return; |
| | } |
| | event.preventDefault(); |
| | selectSidebarItem( $( this ) ); |
| | } ); |
| |
|
| | |
| | |
| | |
| | this.container.find( '.move-widget-btn' ).click( function() { |
| | self.getSidebarWidgetsControl().toggleReordering( false ); |
| |
|
| | var oldSidebarId = self.params.sidebar_id, |
| | newSidebarId = self.container.find( '.widget-area-select li.selected' ).data( 'id' ), |
| | oldSidebarWidgetsSetting, newSidebarWidgetsSetting, |
| | oldSidebarWidgetIds, newSidebarWidgetIds, i; |
| |
|
| | oldSidebarWidgetsSetting = api( 'sidebars_widgets[' + oldSidebarId + ']' ); |
| | newSidebarWidgetsSetting = api( 'sidebars_widgets[' + newSidebarId + ']' ); |
| | oldSidebarWidgetIds = Array.prototype.slice.call( oldSidebarWidgetsSetting() ); |
| | newSidebarWidgetIds = Array.prototype.slice.call( newSidebarWidgetsSetting() ); |
| |
|
| | i = self.getWidgetSidebarPosition(); |
| | oldSidebarWidgetIds.splice( i, 1 ); |
| | newSidebarWidgetIds.push( self.params.widget_id ); |
| |
|
| | oldSidebarWidgetsSetting( oldSidebarWidgetIds ); |
| | newSidebarWidgetsSetting( newSidebarWidgetIds ); |
| |
|
| | self.focus(); |
| | } ); |
| | }, |
| |
|
| | |
| | |
| | |
| | _setupHighlightEffects: function() { |
| | var self = this; |
| |
|
| | |
| | this.container.on( 'mouseenter click', function() { |
| | self.setting.previewer.send( 'highlight-widget', self.params.widget_id ); |
| | } ); |
| |
|
| | |
| | this.setting.bind( function() { |
| | self.setting.previewer.send( 'highlight-widget', self.params.widget_id ); |
| | } ); |
| | }, |
| |
|
| | |
| | |
| | |
| | _setupUpdateUI: function() { |
| | var self = this, $widgetRoot, $widgetContent, |
| | $saveBtn, updateWidgetDebounced, formSyncHandler; |
| |
|
| | $widgetRoot = this.container.find( '.widget:first' ); |
| | $widgetContent = $widgetRoot.find( '.widget-content:first' ); |
| |
|
| | |
| | $saveBtn = this.container.find( '.widget-control-save' ); |
| | $saveBtn.val( l10n.saveBtnLabel ); |
| | $saveBtn.attr( 'title', l10n.saveBtnTooltip ); |
| | $saveBtn.removeClass( 'button-primary' ); |
| | $saveBtn.on( 'click', function( e ) { |
| | e.preventDefault(); |
| | self.updateWidget( { disable_form: true } ); |
| | } ); |
| |
|
| | updateWidgetDebounced = _.debounce( function() { |
| | self.updateWidget(); |
| | }, 250 ); |
| |
|
| | |
| | $widgetContent.on( 'keydown', 'input', function( e ) { |
| | if ( 13 === e.which ) { |
| | e.preventDefault(); |
| | self.updateWidget( { ignoreActiveElement: true } ); |
| | } |
| | } ); |
| |
|
| | |
| | $widgetContent.on( 'change input propertychange', ':input', function( e ) { |
| | if ( ! self.liveUpdateMode ) { |
| | return; |
| | } |
| | if ( e.type === 'change' || ( this.checkValidity && this.checkValidity() ) ) { |
| | updateWidgetDebounced(); |
| | } |
| | } ); |
| |
|
| | |
| | this.setting.previewer.channel.bind( 'synced', function() { |
| | self.container.removeClass( 'previewer-loading' ); |
| | } ); |
| |
|
| | api.previewer.bind( 'widget-updated', function( updatedWidgetId ) { |
| | if ( updatedWidgetId === self.params.widget_id ) { |
| | self.container.removeClass( 'previewer-loading' ); |
| | } |
| | } ); |
| |
|
| | formSyncHandler = api.Widgets.formSyncHandlers[ this.params.widget_id_base ]; |
| | if ( formSyncHandler ) { |
| | $( document ).on( 'widget-synced', function( e, widget ) { |
| | if ( $widgetRoot.is( widget ) ) { |
| | formSyncHandler.apply( document, arguments ); |
| | } |
| | } ); |
| | } |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | onChangeActive: function ( active, args ) { |
| | |
| | this.container.toggleClass( 'widget-rendered', active ); |
| | if ( args.completeCallback ) { |
| | args.completeCallback(); |
| | } |
| | }, |
| |
|
| | |
| | |
| | |
| | _setupRemoveUI: function() { |
| | var self = this, $removeBtn, replaceDeleteWithRemove; |
| |
|
| | |
| | $removeBtn = this.container.find( '.widget-control-remove' ); |
| | $removeBtn.on( 'click', function() { |
| | |
| | var $adjacentFocusTarget; |
| | if ( self.container.next().is( '.customize-control-widget_form' ) ) { |
| | $adjacentFocusTarget = self.container.next().find( '.widget-action:first' ); |
| | } else if ( self.container.prev().is( '.customize-control-widget_form' ) ) { |
| | $adjacentFocusTarget = self.container.prev().find( '.widget-action:first' ); |
| | } else { |
| | $adjacentFocusTarget = self.container.next( '.customize-control-sidebar_widgets' ).find( '.add-new-widget:first' ); |
| | } |
| |
|
| | self.container.slideUp( function() { |
| | var sidebarsWidgetsControl = api.Widgets.getSidebarWidgetControlContainingWidget( self.params.widget_id ), |
| | sidebarWidgetIds, i; |
| |
|
| | if ( ! sidebarsWidgetsControl ) { |
| | return; |
| | } |
| |
|
| | sidebarWidgetIds = sidebarsWidgetsControl.setting().slice(); |
| | i = _.indexOf( sidebarWidgetIds, self.params.widget_id ); |
| | if ( -1 === i ) { |
| | return; |
| | } |
| |
|
| | sidebarWidgetIds.splice( i, 1 ); |
| | sidebarsWidgetsControl.setting( sidebarWidgetIds ); |
| |
|
| | $adjacentFocusTarget.focus(); |
| | } ); |
| | } ); |
| |
|
| | replaceDeleteWithRemove = function() { |
| | $removeBtn.text( l10n.removeBtnLabel ); |
| | $removeBtn.attr( 'title', l10n.removeBtnTooltip ); |
| | }; |
| |
|
| | if ( this.params.is_new ) { |
| | api.bind( 'saved', replaceDeleteWithRemove ); |
| | } else { |
| | replaceDeleteWithRemove(); |
| | } |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | _getInputs: function( container ) { |
| | return $( container ).find( ':input[name]' ); |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | _getInputsSignature: function( inputs ) { |
| | var inputsSignatures = _( inputs ).map( function( input ) { |
| | var $input = $( input ), signatureParts; |
| |
|
| | if ( $input.is( ':checkbox, :radio' ) ) { |
| | signatureParts = [ $input.attr( 'id' ), $input.attr( 'name' ), $input.prop( 'value' ) ]; |
| | } else { |
| | signatureParts = [ $input.attr( 'id' ), $input.attr( 'name' ) ]; |
| | } |
| |
|
| | return signatureParts.join( ',' ); |
| | } ); |
| |
|
| | return inputsSignatures.join( ';' ); |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | _getInputState: function( input ) { |
| | input = $( input ); |
| | if ( input.is( ':radio, :checkbox' ) ) { |
| | return input.prop( 'checked' ); |
| | } else if ( input.is( 'select[multiple]' ) ) { |
| | return input.find( 'option:selected' ).map( function () { |
| | return $( this ).val(); |
| | } ).get(); |
| | } else { |
| | return input.val(); |
| | } |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | _setInputState: function ( input, state ) { |
| | input = $( input ); |
| | if ( input.is( ':radio, :checkbox' ) ) { |
| | input.prop( 'checked', state ); |
| | } else if ( input.is( 'select[multiple]' ) ) { |
| | if ( ! Array.isArray( state ) ) { |
| | state = []; |
| | } else { |
| | |
| | state = _.map( state, function ( value ) { |
| | return String( value ); |
| | } ); |
| | } |
| | input.find( 'option' ).each( function () { |
| | $( this ).prop( 'selected', -1 !== _.indexOf( state, String( this.value ) ) ); |
| | } ); |
| | } else { |
| | input.val( state ); |
| | } |
| | }, |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | getSidebarWidgetsControl: function() { |
| | var settingId, sidebarWidgetsControl; |
| |
|
| | settingId = 'sidebars_widgets[' + this.params.sidebar_id + ']'; |
| | sidebarWidgetsControl = api.control( settingId ); |
| |
|
| | if ( ! sidebarWidgetsControl ) { |
| | return; |
| | } |
| |
|
| | return sidebarWidgetsControl; |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | updateWidget: function( args ) { |
| | var self = this, instanceOverride, completeCallback, $widgetRoot, $widgetContent, |
| | updateNumber, params, data, $inputs, processing, jqxhr, isChanged; |
| |
|
| | |
| | self.embedWidgetContent(); |
| |
|
| | args = $.extend( { |
| | instance: null, |
| | complete: null, |
| | ignoreActiveElement: false |
| | }, args ); |
| |
|
| | instanceOverride = args.instance; |
| | completeCallback = args.complete; |
| |
|
| | this._updateCount += 1; |
| | updateNumber = this._updateCount; |
| |
|
| | $widgetRoot = this.container.find( '.widget:first' ); |
| | $widgetContent = $widgetRoot.find( '.widget-content:first' ); |
| |
|
| | |
| | $widgetContent.find( '.widget-error' ).remove(); |
| |
|
| | this.container.addClass( 'widget-form-loading' ); |
| | this.container.addClass( 'previewer-loading' ); |
| | processing = api.state( 'processing' ); |
| | processing( processing() + 1 ); |
| |
|
| | if ( ! this.liveUpdateMode ) { |
| | this.container.addClass( 'widget-form-disabled' ); |
| | } |
| |
|
| | params = {}; |
| | params.action = 'update-widget'; |
| | params.wp_customize = 'on'; |
| | params.nonce = api.settings.nonce['update-widget']; |
| | params.customize_theme = api.settings.theme.stylesheet; |
| | params.customized = wp.customize.previewer.query().customized; |
| |
|
| | data = $.param( params ); |
| | $inputs = this._getInputs( $widgetContent ); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | $inputs.each( function() { |
| | $( this ).data( 'state' + updateNumber, self._getInputState( this ) ); |
| | } ); |
| |
|
| | if ( instanceOverride ) { |
| | data += '&' + $.param( { 'sanitized_widget_setting': JSON.stringify( instanceOverride ) } ); |
| | } else { |
| | data += '&' + $inputs.serialize(); |
| | } |
| | data += '&' + $widgetContent.find( '~ :input' ).serialize(); |
| |
|
| | if ( this._previousUpdateRequest ) { |
| | this._previousUpdateRequest.abort(); |
| | } |
| | jqxhr = $.post( wp.ajax.settings.url, data ); |
| | this._previousUpdateRequest = jqxhr; |
| |
|
| | jqxhr.done( function( r ) { |
| | var message, sanitizedForm, $sanitizedInputs, hasSameInputsInResponse, |
| | isLiveUpdateAborted = false; |
| |
|
| | |
| | if ( '0' === r ) { |
| | api.previewer.preview.iframe.hide(); |
| | api.previewer.login().done( function() { |
| | self.updateWidget( args ); |
| | api.previewer.preview.iframe.show(); |
| | } ); |
| | return; |
| | } |
| |
|
| | |
| | if ( '-1' === r ) { |
| | api.previewer.cheatin(); |
| | return; |
| | } |
| |
|
| | if ( r.success ) { |
| | sanitizedForm = $( '<div>' + r.data.form + '</div>' ); |
| | $sanitizedInputs = self._getInputs( sanitizedForm ); |
| | hasSameInputsInResponse = self._getInputsSignature( $inputs ) === self._getInputsSignature( $sanitizedInputs ); |
| |
|
| | |
| | if ( hasSameInputsInResponse && ! self.liveUpdateMode ) { |
| | self.liveUpdateMode = true; |
| | self.container.removeClass( 'widget-form-disabled' ); |
| | self.container.find( 'input[name="savewidget"]' ).hide(); |
| | } |
| |
|
| | |
| | if ( hasSameInputsInResponse && self.liveUpdateMode ) { |
| | $inputs.each( function( i ) { |
| | var $input = $( this ), |
| | $sanitizedInput = $( $sanitizedInputs[i] ), |
| | submittedState, sanitizedState, canUpdateState; |
| |
|
| | submittedState = $input.data( 'state' + updateNumber ); |
| | sanitizedState = self._getInputState( $sanitizedInput ); |
| | $input.data( 'sanitized', sanitizedState ); |
| |
|
| | canUpdateState = ( ! _.isEqual( submittedState, sanitizedState ) && ( args.ignoreActiveElement || ! $input.is( document.activeElement ) ) ); |
| | if ( canUpdateState ) { |
| | self._setInputState( $input, sanitizedState ); |
| | } |
| | } ); |
| |
|
| | $( document ).trigger( 'widget-synced', [ $widgetRoot, r.data.form ] ); |
| |
|
| | |
| | } else if ( self.liveUpdateMode ) { |
| | self.liveUpdateMode = false; |
| | self.container.find( 'input[name="savewidget"]' ).show(); |
| | isLiveUpdateAborted = true; |
| |
|
| | |
| | } else { |
| | $widgetContent.html( r.data.form ); |
| |
|
| | self.container.removeClass( 'widget-form-disabled' ); |
| |
|
| | $( document ).trigger( 'widget-updated', [ $widgetRoot ] ); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | isChanged = ! isLiveUpdateAborted && ! _( self.setting() ).isEqual( r.data.instance ); |
| | if ( isChanged ) { |
| | self.isWidgetUpdating = true; |
| | self.setting( r.data.instance ); |
| | self.isWidgetUpdating = false; |
| | } else { |
| | |
| | self.container.removeClass( 'previewer-loading' ); |
| | } |
| |
|
| | if ( completeCallback ) { |
| | completeCallback.call( self, null, { noChange: ! isChanged, ajaxFinished: true } ); |
| | } |
| | } else { |
| | |
| | message = l10n.error; |
| |
|
| | if ( r.data && r.data.message ) { |
| | message = r.data.message; |
| | } |
| |
|
| | if ( completeCallback ) { |
| | completeCallback.call( self, message ); |
| | } else { |
| | $widgetContent.prepend( '<p class="widget-error"><strong>' + message + '</strong></p>' ); |
| | } |
| | } |
| | } ); |
| |
|
| | jqxhr.fail( function( jqXHR, textStatus ) { |
| | if ( completeCallback ) { |
| | completeCallback.call( self, textStatus ); |
| | } |
| | } ); |
| |
|
| | jqxhr.always( function() { |
| | self.container.removeClass( 'widget-form-loading' ); |
| |
|
| | $inputs.each( function() { |
| | $( this ).removeData( 'state' + updateNumber ); |
| | } ); |
| |
|
| | processing( processing() - 1 ); |
| | } ); |
| | }, |
| |
|
| | |
| | |
| | |
| | expandControlSection: function() { |
| | api.Control.prototype.expand.call( this ); |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | _toggleExpanded: api.Section.prototype._toggleExpanded, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | expand: api.Section.prototype.expand, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | expandForm: function() { |
| | this.expand(); |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | collapse: api.Section.prototype.collapse, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | collapseForm: function() { |
| | this.collapse(); |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | toggleForm: function( showOrHide ) { |
| | if ( typeof showOrHide === 'undefined' ) { |
| | showOrHide = ! this.expanded(); |
| | } |
| | this.expanded( showOrHide ); |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | onChangeExpanded: function ( expanded, args ) { |
| | var self = this, $widget, $inside, complete, prevComplete, expandControl, $toggleBtn; |
| |
|
| | self.embedWidgetControl(); |
| | if ( expanded ) { |
| | self.embedWidgetContent(); |
| | } |
| |
|
| | |
| | if ( args.unchanged ) { |
| | if ( expanded ) { |
| | api.Control.prototype.expand.call( self, { |
| | completeCallback: args.completeCallback |
| | }); |
| | } |
| | return; |
| | } |
| |
|
| | $widget = this.container.find( 'div.widget:first' ); |
| | $inside = $widget.find( '.widget-inside:first' ); |
| | $toggleBtn = this.container.find( '.widget-top button.widget-action' ); |
| |
|
| | expandControl = function() { |
| |
|
| | |
| | api.control.each( function( otherControl ) { |
| | if ( self.params.type === otherControl.params.type && self !== otherControl ) { |
| | otherControl.collapse(); |
| | } |
| | } ); |
| |
|
| | complete = function() { |
| | self.container.removeClass( 'expanding' ); |
| | self.container.addClass( 'expanded' ); |
| | $widget.addClass( 'open' ); |
| | $toggleBtn.attr( 'aria-expanded', 'true' ); |
| | self.container.trigger( 'expanded' ); |
| | }; |
| | if ( args.completeCallback ) { |
| | prevComplete = complete; |
| | complete = function () { |
| | prevComplete(); |
| | args.completeCallback(); |
| | }; |
| | } |
| |
|
| | if ( self.params.is_wide ) { |
| | $inside.fadeIn( args.duration, complete ); |
| | } else { |
| | $inside.slideDown( args.duration, complete ); |
| | } |
| |
|
| | self.container.trigger( 'expand' ); |
| | self.container.addClass( 'expanding' ); |
| | }; |
| |
|
| | if ( $toggleBtn.attr( 'aria-expanded' ) === 'false' ) { |
| | if ( api.section.has( self.section() ) ) { |
| | api.section( self.section() ).expand( { |
| | completeCallback: expandControl |
| | } ); |
| | } else { |
| | expandControl(); |
| | } |
| | } else { |
| | complete = function() { |
| | self.container.removeClass( 'collapsing' ); |
| | self.container.removeClass( 'expanded' ); |
| | $widget.removeClass( 'open' ); |
| | $toggleBtn.attr( 'aria-expanded', 'false' ); |
| | self.container.trigger( 'collapsed' ); |
| | }; |
| | if ( args.completeCallback ) { |
| | prevComplete = complete; |
| | complete = function () { |
| | prevComplete(); |
| | args.completeCallback(); |
| | }; |
| | } |
| |
|
| | self.container.trigger( 'collapse' ); |
| | self.container.addClass( 'collapsing' ); |
| |
|
| | if ( self.params.is_wide ) { |
| | $inside.fadeOut( args.duration, complete ); |
| | } else { |
| | $inside.slideUp( args.duration, function() { |
| | $widget.css( { width:'', margin:'' } ); |
| | complete(); |
| | } ); |
| | } |
| | } |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | getWidgetSidebarPosition: function() { |
| | var sidebarWidgetIds, position; |
| |
|
| | sidebarWidgetIds = this.getSidebarWidgetsControl().setting(); |
| | position = _.indexOf( sidebarWidgetIds, this.params.widget_id ); |
| |
|
| | if ( position === -1 ) { |
| | return; |
| | } |
| |
|
| | return position; |
| | }, |
| |
|
| | |
| | |
| | |
| | moveUp: function() { |
| | this._moveWidgetByOne( -1 ); |
| | }, |
| |
|
| | |
| | |
| | |
| | moveDown: function() { |
| | this._moveWidgetByOne( 1 ); |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | _moveWidgetByOne: function( offset ) { |
| | var i, sidebarWidgetsSetting, sidebarWidgetIds, adjacentWidgetId; |
| |
|
| | i = this.getWidgetSidebarPosition(); |
| |
|
| | sidebarWidgetsSetting = this.getSidebarWidgetsControl().setting; |
| | sidebarWidgetIds = Array.prototype.slice.call( sidebarWidgetsSetting() ); |
| | adjacentWidgetId = sidebarWidgetIds[i + offset]; |
| | sidebarWidgetIds[i + offset] = this.params.widget_id; |
| | sidebarWidgetIds[i] = adjacentWidgetId; |
| |
|
| | sidebarWidgetsSetting( sidebarWidgetIds ); |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | toggleWidgetMoveArea: function( showOrHide ) { |
| | var self = this, $moveWidgetArea; |
| |
|
| | $moveWidgetArea = this.container.find( '.move-widget-area' ); |
| |
|
| | if ( typeof showOrHide === 'undefined' ) { |
| | showOrHide = ! $moveWidgetArea.hasClass( 'active' ); |
| | } |
| |
|
| | if ( showOrHide ) { |
| | |
| | $moveWidgetArea.find( '.selected' ).removeClass( 'selected' ); |
| |
|
| | $moveWidgetArea.find( 'li' ).filter( function() { |
| | return $( this ).data( 'id' ) === self.params.sidebar_id; |
| | } ).addClass( 'selected' ); |
| |
|
| | this.container.find( '.move-widget-btn' ).prop( 'disabled', true ); |
| | } |
| |
|
| | $moveWidgetArea.toggleClass( 'active', showOrHide ); |
| | }, |
| |
|
| | |
| | |
| | |
| | highlightSectionAndControl: function() { |
| | var $target; |
| |
|
| | if ( this.container.is( ':hidden' ) ) { |
| | $target = this.container.closest( '.control-section' ); |
| | } else { |
| | $target = this.container; |
| | } |
| |
|
| | $( '.highlighted' ).removeClass( 'highlighted' ); |
| | $target.addClass( 'highlighted' ); |
| |
|
| | setTimeout( function() { |
| | $target.removeClass( 'highlighted' ); |
| | }, 500 ); |
| | } |
| | } ); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | api.Widgets.WidgetsPanel = api.Panel.extend({ |
| |
|
| | |
| | |
| | |
| | |
| | |
| | ready: function () { |
| | var panel = this; |
| |
|
| | api.Panel.prototype.ready.call( panel ); |
| |
|
| | panel.deferred.embedded.done(function() { |
| | var panelMetaContainer, noticeContainer, updateNotice, getActiveSectionCount, shouldShowNotice; |
| | panelMetaContainer = panel.container.find( '.panel-meta' ); |
| |
|
| | |
| | noticeContainer = $( '<div></div>', { |
| | 'class': 'no-widget-areas-rendered-notice', |
| | 'role': 'alert' |
| | }); |
| | panelMetaContainer.append( noticeContainer ); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | getActiveSectionCount = function() { |
| | return _.filter( panel.sections(), function( section ) { |
| | return 'sidebar' === section.params.type && section.active(); |
| | } ).length; |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | shouldShowNotice = function() { |
| | var activeSectionCount = getActiveSectionCount(); |
| | if ( 0 === activeSectionCount ) { |
| | return true; |
| | } else { |
| | return activeSectionCount !== api.Widgets.data.registeredSidebars.length; |
| | } |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | updateNotice = function() { |
| | var activeSectionCount = getActiveSectionCount(), someRenderedMessage, nonRenderedAreaCount, registeredAreaCount; |
| | noticeContainer.empty(); |
| |
|
| | registeredAreaCount = api.Widgets.data.registeredSidebars.length; |
| | if ( activeSectionCount !== registeredAreaCount ) { |
| |
|
| | if ( 0 !== activeSectionCount ) { |
| | nonRenderedAreaCount = registeredAreaCount - activeSectionCount; |
| | someRenderedMessage = l10n.someAreasShown[ nonRenderedAreaCount ]; |
| | } else { |
| | someRenderedMessage = l10n.noAreasShown; |
| | } |
| | if ( someRenderedMessage ) { |
| | noticeContainer.append( $( '<p></p>', { |
| | text: someRenderedMessage |
| | } ) ); |
| | } |
| |
|
| | noticeContainer.append( $( '<p></p>', { |
| | text: l10n.navigatePreview |
| | } ) ); |
| | } |
| | }; |
| | updateNotice(); |
| |
|
| | |
| | |
| | |
| | |
| | noticeContainer.toggle( shouldShowNotice() ); |
| | api.previewer.deferred.active.done( function () { |
| | noticeContainer.toggle( shouldShowNotice() ); |
| | }); |
| | api.bind( 'pane-contents-reflowed', function() { |
| | var duration = ( 'resolved' === api.previewer.deferred.active.state() ) ? 'fast' : 0; |
| | updateNotice(); |
| | if ( shouldShowNotice() ) { |
| | noticeContainer.slideDown( duration ); |
| | } else { |
| | noticeContainer.slideUp( duration ); |
| | } |
| | }); |
| | }); |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | isContextuallyActive: function() { |
| | var panel = this; |
| | return panel.active(); |
| | } |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | api.Widgets.SidebarSection = api.Section.extend({ |
| |
|
| | |
| | |
| | |
| | |
| | |
| | ready: function () { |
| | var section = this, registeredSidebar; |
| | api.Section.prototype.ready.call( this ); |
| | registeredSidebar = api.Widgets.registeredSidebars.get( section.params.sidebarId ); |
| | section.active.bind( function ( active ) { |
| | registeredSidebar.set( 'is_rendered', active ); |
| | }); |
| | registeredSidebar.set( 'is_rendered', section.active() ); |
| | } |
| | }); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | api.Widgets.SidebarControl = api.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 self = this; |
| |
|
| | this.setting.bind( function( newWidgetIds, oldWidgetIds ) { |
| | var widgetFormControls, removedWidgetIds, priority; |
| |
|
| | removedWidgetIds = _( oldWidgetIds ).difference( newWidgetIds ); |
| |
|
| | |
| | newWidgetIds = _( newWidgetIds ).filter( function( newWidgetId ) { |
| | var parsedWidgetId = parseWidgetId( newWidgetId ); |
| |
|
| | return !! api.Widgets.availableWidgets.findWhere( { id_base: parsedWidgetId.id_base } ); |
| | } ); |
| |
|
| | widgetFormControls = _( newWidgetIds ).map( function( widgetId ) { |
| | var widgetFormControl = api.Widgets.getWidgetFormControlForWidget( widgetId ); |
| |
|
| | if ( ! widgetFormControl ) { |
| | widgetFormControl = self.addWidget( widgetId ); |
| | } |
| |
|
| | return widgetFormControl; |
| | } ); |
| |
|
| | |
| | widgetFormControls.sort( function( a, b ) { |
| | var aIndex = _.indexOf( newWidgetIds, a.params.widget_id ), |
| | bIndex = _.indexOf( newWidgetIds, b.params.widget_id ); |
| | return aIndex - bIndex; |
| | }); |
| |
|
| | priority = 0; |
| | _( widgetFormControls ).each( function ( control ) { |
| | control.priority( priority ); |
| | control.section( self.section() ); |
| | priority += 1; |
| | }); |
| | self.priority( priority ); |
| |
|
| | |
| | self._applyCardinalOrderClassNames(); |
| |
|
| | |
| | _( widgetFormControls ).each( function( widgetFormControl ) { |
| | widgetFormControl.params.sidebar_id = self.params.sidebar_id; |
| | } ); |
| |
|
| | |
| | _( removedWidgetIds ).each( function( removedWidgetId ) { |
| |
|
| | |
| | |
| | setTimeout( function() { |
| | var removedControl, wasDraggedToAnotherSidebar, inactiveWidgets, removedIdBase, |
| | widget, isPresentInAnotherSidebar = false; |
| |
|
| | |
| | api.each( function( otherSetting ) { |
| | if ( otherSetting.id === self.setting.id || 0 !== otherSetting.id.indexOf( 'sidebars_widgets[' ) || otherSetting.id === 'sidebars_widgets[wp_inactive_widgets]' ) { |
| | return; |
| | } |
| |
|
| | var otherSidebarWidgets = otherSetting(), i; |
| |
|
| | i = _.indexOf( otherSidebarWidgets, removedWidgetId ); |
| | if ( -1 !== i ) { |
| | isPresentInAnotherSidebar = true; |
| | } |
| | } ); |
| |
|
| | |
| | if ( isPresentInAnotherSidebar ) { |
| | return; |
| | } |
| |
|
| | removedControl = api.Widgets.getWidgetFormControlForWidget( removedWidgetId ); |
| |
|
| | |
| | wasDraggedToAnotherSidebar = removedControl && $.contains( document, removedControl.container[0] ) && ! $.contains( self.$sectionContent[0], removedControl.container[0] ); |
| |
|
| | |
| | if ( removedControl && ! wasDraggedToAnotherSidebar ) { |
| | api.control.remove( removedControl.id ); |
| | removedControl.container.remove(); |
| | } |
| |
|
| | |
| | |
| | if ( api.Widgets.savedWidgetIds[removedWidgetId] ) { |
| | inactiveWidgets = api.value( 'sidebars_widgets[wp_inactive_widgets]' )().slice(); |
| | inactiveWidgets.push( removedWidgetId ); |
| | api.value( 'sidebars_widgets[wp_inactive_widgets]' )( _( inactiveWidgets ).unique() ); |
| | } |
| |
|
| | |
| | removedIdBase = parseWidgetId( removedWidgetId ).id_base; |
| | widget = api.Widgets.availableWidgets.findWhere( { id_base: removedIdBase } ); |
| | if ( widget && ! widget.get( 'is_multi' ) ) { |
| | widget.set( 'is_disabled', false ); |
| | } |
| | } ); |
| |
|
| | } ); |
| | } ); |
| | }, |
| |
|
| | |
| | |
| | |
| | _setupSortable: function() { |
| | var self = this; |
| |
|
| | this.isReordering = false; |
| |
|
| | |
| | |
| | |
| | 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 widgetContainerIds = self.$sectionContent.sortable( 'toArray' ), widgetIds; |
| |
|
| | widgetIds = $.map( widgetContainerIds, function( widgetContainerId ) { |
| | return $( '#' + widgetContainerId ).find( ':input[name=widget-id]' ).val(); |
| | } ); |
| |
|
| | self.setting( widgetIds ); |
| | } |
| | } ); |
| |
|
| | |
| | |
| | |
| | |
| | this.$controlSection.find( '.accordion-section-title' ).droppable({ |
| | accept: '.customize-control-widget_form', |
| | over: function() { |
| | var section = api.section( self.section.get() ); |
| | section.expand({ |
| | allowMultiple: true, |
| | completeCallback: function () { |
| | |
| | api.section.each( function ( otherSection ) { |
| | if ( otherSection.container.find( '.customize-control-sidebar_widgets' ).length ) { |
| | otherSection.container.find( '.accordion-section-content:first' ).sortable( 'refreshPositions' ); |
| | } |
| | } ); |
| | } |
| | }); |
| | } |
| | }); |
| |
|
| | |
| | |
| | |
| | this.container.find( '.reorder-toggle' ).on( 'click', function() { |
| | self.toggleReordering( ! self.isReordering ); |
| | } ); |
| | }, |
| |
|
| | |
| | |
| | |
| | _setupAddition: function() { |
| | var self = this; |
| |
|
| | this.container.find( '.add-new-widget' ).on( 'click', function() { |
| | var addNewWidgetBtn = $( this ); |
| |
|
| | if ( self.$sectionContent.hasClass( 'reordering' ) ) { |
| | return; |
| | } |
| |
|
| | if ( ! $( 'body' ).hasClass( 'adding-widget' ) ) { |
| | addNewWidgetBtn.attr( 'aria-expanded', 'true' ); |
| | api.Widgets.availableWidgetsPanel.open( self ); |
| | } else { |
| | addNewWidgetBtn.attr( 'aria-expanded', 'false' ); |
| | api.Widgets.availableWidgetsPanel.close(); |
| | } |
| | } ); |
| | }, |
| |
|
| | |
| | |
| | |
| | _applyCardinalOrderClassNames: function() { |
| | var widgetControls = []; |
| | _.each( this.setting(), function ( widgetId ) { |
| | var widgetControl = api.Widgets.getWidgetFormControlForWidget( widgetId ); |
| | if ( widgetControl ) { |
| | widgetControls.push( widgetControl ); |
| | } |
| | }); |
| |
|
| | if ( 0 === widgetControls.length || ( 1 === api.Widgets.registeredSidebars.length && widgetControls.length <= 1 ) ) { |
| | this.container.find( '.reorder-toggle' ).hide(); |
| | return; |
| | } else { |
| | this.container.find( '.reorder-toggle' ).show(); |
| | } |
| |
|
| | $( widgetControls ).each( function () { |
| | $( this.container ) |
| | .removeClass( 'first-widget' ) |
| | .removeClass( 'last-widget' ) |
| | .find( '.move-widget-down, .move-widget-up' ).prop( 'tabIndex', 0 ); |
| | }); |
| |
|
| | _.first( widgetControls ).container |
| | .addClass( 'first-widget' ) |
| | .find( '.move-widget-up' ).prop( 'tabIndex', -1 ); |
| |
|
| | _.last( widgetControls ).container |
| | .addClass( 'last-widget' ) |
| | .find( '.move-widget-down' ).prop( 'tabIndex', -1 ); |
| | }, |
| |
|
| |
|
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | toggleReordering: function( showOrHide ) { |
| | var addNewWidgetBtn = this.$sectionContent.find( '.add-new-widget' ), |
| | reorderBtn = this.container.find( '.reorder-toggle' ), |
| | widgetsTitle = this.$sectionContent.find( '.widget-title' ); |
| |
|
| | showOrHide = Boolean( showOrHide ); |
| |
|
| | if ( showOrHide === this.$sectionContent.hasClass( 'reordering' ) ) { |
| | return; |
| | } |
| |
|
| | this.isReordering = showOrHide; |
| | this.$sectionContent.toggleClass( 'reordering', showOrHide ); |
| |
|
| | if ( showOrHide ) { |
| | _( this.getWidgetFormControls() ).each( function( formControl ) { |
| | formControl.collapse(); |
| | } ); |
| |
|
| | addNewWidgetBtn.attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); |
| | reorderBtn.attr( 'aria-label', l10n.reorderLabelOff ); |
| | wp.a11y.speak( l10n.reorderModeOn ); |
| | |
| | widgetsTitle.attr( 'aria-hidden', 'true' ); |
| | } else { |
| | addNewWidgetBtn.removeAttr( 'tabindex aria-hidden' ); |
| | reorderBtn.attr( 'aria-label', l10n.reorderLabelOn ); |
| | wp.a11y.speak( l10n.reorderModeOff ); |
| | widgetsTitle.attr( 'aria-hidden', 'false' ); |
| | } |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | getWidgetFormControls: function() { |
| | var formControls = []; |
| |
|
| | _( this.setting() ).each( function( widgetId ) { |
| | var settingId = widgetIdToSettingId( widgetId ), |
| | formControl = api.control( settingId ); |
| | if ( formControl ) { |
| | formControls.push( formControl ); |
| | } |
| | } ); |
| |
|
| | return formControls; |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | addWidget: function( widgetId ) { |
| | var self = this, controlHtml, $widget, controlType = 'widget_form', controlContainer, controlConstructor, |
| | parsedWidgetId = parseWidgetId( widgetId ), |
| | widgetNumber = parsedWidgetId.number, |
| | widgetIdBase = parsedWidgetId.id_base, |
| | widget = api.Widgets.availableWidgets.findWhere( {id_base: widgetIdBase} ), |
| | settingId, isExistingWidget, widgetFormControl, sidebarWidgets, settingArgs, setting; |
| |
|
| | if ( ! widget ) { |
| | return false; |
| | } |
| |
|
| | if ( widgetNumber && ! widget.get( 'is_multi' ) ) { |
| | return false; |
| | } |
| |
|
| | |
| | if ( widget.get( 'is_multi' ) && ! widgetNumber ) { |
| | widget.set( 'multi_number', widget.get( 'multi_number' ) + 1 ); |
| | widgetNumber = widget.get( 'multi_number' ); |
| | } |
| |
|
| | controlHtml = $( '#widget-tpl-' + widget.get( 'id' ) ).html().trim(); |
| | if ( widget.get( 'is_multi' ) ) { |
| | controlHtml = controlHtml.replace( /<[^<>]+>/g, function( m ) { |
| | return m.replace( /__i__|%i%/g, widgetNumber ); |
| | } ); |
| | } else { |
| | widget.set( 'is_disabled', true ); |
| | } |
| |
|
| | $widget = $( controlHtml ); |
| |
|
| | controlContainer = $( '<li/>' ) |
| | .addClass( 'customize-control' ) |
| | .addClass( 'customize-control-' + controlType ) |
| | .append( $widget ); |
| |
|
| | |
| | controlContainer.find( '> .widget-icon' ).remove(); |
| |
|
| | if ( widget.get( 'is_multi' ) ) { |
| | controlContainer.find( 'input[name="widget_number"]' ).val( widgetNumber ); |
| | controlContainer.find( 'input[name="multi_number"]' ).val( widgetNumber ); |
| | } |
| |
|
| | widgetId = controlContainer.find( '[name="widget-id"]' ).val(); |
| |
|
| | controlContainer.hide(); |
| |
|
| | settingId = 'widget_' + widget.get( 'id_base' ); |
| | if ( widget.get( 'is_multi' ) ) { |
| | settingId += '[' + widgetNumber + ']'; |
| | } |
| | controlContainer.attr( 'id', 'customize-control-' + settingId.replace( /\]/g, '' ).replace( /\[/g, '-' ) ); |
| |
|
| | |
| | isExistingWidget = api.has( settingId ); |
| | if ( ! isExistingWidget ) { |
| | settingArgs = { |
| | transport: api.Widgets.data.selectiveRefreshableWidgets[ widget.get( 'id_base' ) ] ? 'postMessage' : 'refresh', |
| | previewer: this.setting.previewer |
| | }; |
| | setting = api.create( settingId, settingId, '', settingArgs ); |
| | setting.set( {} ); |
| | } |
| |
|
| | controlConstructor = api.controlConstructor[controlType]; |
| | widgetFormControl = new controlConstructor( settingId, { |
| | settings: { |
| | 'default': settingId |
| | }, |
| | content: controlContainer, |
| | sidebar_id: self.params.sidebar_id, |
| | widget_id: widgetId, |
| | widget_id_base: widget.get( 'id_base' ), |
| | type: controlType, |
| | is_new: ! isExistingWidget, |
| | width: widget.get( 'width' ), |
| | height: widget.get( 'height' ), |
| | is_wide: widget.get( 'is_wide' ) |
| | } ); |
| | api.control.add( widgetFormControl ); |
| |
|
| | |
| | api.each( function( otherSetting ) { |
| | if ( otherSetting.id === self.setting.id ) { |
| | return; |
| | } |
| |
|
| | if ( 0 !== otherSetting.id.indexOf( 'sidebars_widgets[' ) ) { |
| | return; |
| | } |
| |
|
| | var otherSidebarWidgets = otherSetting().slice(), |
| | i = _.indexOf( otherSidebarWidgets, widgetId ); |
| |
|
| | if ( -1 !== i ) { |
| | otherSidebarWidgets.splice( i ); |
| | otherSetting( otherSidebarWidgets ); |
| | } |
| | } ); |
| |
|
| | |
| | sidebarWidgets = this.setting().slice(); |
| | if ( -1 === _.indexOf( sidebarWidgets, widgetId ) ) { |
| | sidebarWidgets.push( widgetId ); |
| | this.setting( sidebarWidgets ); |
| | } |
| |
|
| | controlContainer.slideDown( function() { |
| | if ( isExistingWidget ) { |
| | widgetFormControl.updateWidget( { |
| | instance: widgetFormControl.setting() |
| | } ); |
| | } |
| | } ); |
| |
|
| | return widgetFormControl; |
| | } |
| | } ); |
| |
|
| | |
| | $.extend( api.panelConstructor, { |
| | widgets: api.Widgets.WidgetsPanel |
| | }); |
| | $.extend( api.sectionConstructor, { |
| | sidebar: api.Widgets.SidebarSection |
| | }); |
| | $.extend( api.controlConstructor, { |
| | widget_form: api.Widgets.WidgetControl, |
| | sidebar_widgets: api.Widgets.SidebarControl |
| | }); |
| |
|
| | |
| | |
| | |
| | api.bind( 'ready', function() { |
| | |
| | api.Widgets.availableWidgetsPanel = new api.Widgets.AvailableWidgetsPanelView({ |
| | collection: api.Widgets.availableWidgets |
| | }); |
| |
|
| | |
| | api.previewer.bind( 'highlight-widget-control', api.Widgets.highlightWidgetFormControl ); |
| |
|
| | |
| | api.previewer.bind( 'focus-widget-control', api.Widgets.focusWidgetFormControl ); |
| | } ); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | api.Widgets.highlightWidgetFormControl = function( widgetId ) { |
| | var control = api.Widgets.getWidgetFormControlForWidget( widgetId ); |
| |
|
| | if ( control ) { |
| | control.highlightSectionAndControl(); |
| | } |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | api.Widgets.focusWidgetFormControl = function( widgetId ) { |
| | var control = api.Widgets.getWidgetFormControlForWidget( widgetId ); |
| |
|
| | if ( control ) { |
| | control.focus(); |
| | } |
| | }, |
| |
|
| | |
| | |
| | |
| | |
| | |
| | api.Widgets.getSidebarWidgetControlContainingWidget = function( widgetId ) { |
| | var foundControl = null; |
| |
|
| | |
| | api.control.each( function( control ) { |
| | if ( control.params.type === 'sidebar_widgets' && -1 !== _.indexOf( control.setting(), widgetId ) ) { |
| | foundControl = control; |
| | } |
| | } ); |
| |
|
| | return foundControl; |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | api.Widgets.getWidgetFormControlForWidget = function( widgetId ) { |
| | var foundControl = null; |
| |
|
| | |
| | api.control.each( function( control ) { |
| | if ( control.params.type === 'widget_form' && control.params.widget_id === widgetId ) { |
| | foundControl = control; |
| | } |
| | } ); |
| |
|
| | return foundControl; |
| | }; |
| |
|
| | |
| | |
| | |
| | $( document ).on( 'widget-added', function( event, widgetContainer ) { |
| | var parsedWidgetId, widgetControl, navMenuSelect, editMenuButton; |
| | parsedWidgetId = parseWidgetId( widgetContainer.find( '> .widget-inside > .form > .widget-id' ).val() ); |
| | if ( 'nav_menu' !== parsedWidgetId.id_base ) { |
| | return; |
| | } |
| | widgetControl = api.control( 'widget_nav_menu[' + String( parsedWidgetId.number ) + ']' ); |
| | if ( ! widgetControl ) { |
| | return; |
| | } |
| | navMenuSelect = widgetContainer.find( 'select[name*="nav_menu"]' ); |
| | editMenuButton = widgetContainer.find( '.edit-selected-nav-menu > button' ); |
| | if ( 0 === navMenuSelect.length || 0 === editMenuButton.length ) { |
| | return; |
| | } |
| | navMenuSelect.on( 'change', function() { |
| | if ( api.section.has( 'nav_menu[' + navMenuSelect.val() + ']' ) ) { |
| | editMenuButton.parent().show(); |
| | } else { |
| | editMenuButton.parent().hide(); |
| | } |
| | }); |
| | editMenuButton.on( 'click', function() { |
| | var section = api.section( 'nav_menu[' + navMenuSelect.val() + ']' ); |
| | if ( section ) { |
| | focusConstructWithBreadcrumb( section, widgetControl ); |
| | } |
| | } ); |
| | } ); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | function focusConstructWithBreadcrumb( focusConstruct, returnConstruct ) { |
| | focusConstruct.focus(); |
| | function onceCollapsed( isExpanded ) { |
| | if ( ! isExpanded ) { |
| | focusConstruct.expanded.unbind( onceCollapsed ); |
| | returnConstruct.focus(); |
| | } |
| | } |
| | focusConstruct.expanded.bind( onceCollapsed ); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | function parseWidgetId( widgetId ) { |
| | var matches, parsed = { |
| | number: null, |
| | id_base: null |
| | }; |
| |
|
| | matches = widgetId.match( /^(.+)-(\d+)$/ ); |
| | if ( matches ) { |
| | parsed.id_base = matches[1]; |
| | parsed.number = parseInt( matches[2], 10 ); |
| | } else { |
| | |
| | parsed.id_base = widgetId; |
| | } |
| |
|
| | return parsed; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | function widgetIdToSettingId( widgetId ) { |
| | var parsed = parseWidgetId( widgetId ), settingId; |
| |
|
| | settingId = 'widget_' + parsed.id_base; |
| | if ( parsed.number ) { |
| | settingId += '[' + parsed.number + ']'; |
| | } |
| |
|
| | return settingId; |
| | } |
| |
|
| | })( window.wp, jQuery ); |
| |
|