diff options
Diffstat (limited to 'plugins/jetpack/modules/widgets/search')
4 files changed, 528 insertions, 0 deletions
diff --git a/plugins/jetpack/modules/widgets/search/css/search-widget-admin-ui.css b/plugins/jetpack/modules/widgets/search/css/search-widget-admin-ui.css new file mode 100644 index 00000000..a3313f05 --- /dev/null +++ b/plugins/jetpack/modules/widgets/search/css/search-widget-admin-ui.css @@ -0,0 +1,87 @@ +.jetpack-search-filters-widget__filter { + background: #f9f9f9; + border: 1px solid #dfdfdf; + padding: 0 12px; + margin-bottom: 12px; + cursor: move; +} + +.jetpack-search-filters-widget__controls { + text-align: right; +} + +.jetpack-search-filters-widget .jetpack-search-filters-widget__sort-controls-enabled { + margin-left: 24px; +} + +.jetpack-search-filters-widget__controls .delete { + color: #a00; +} + +.jetpack-search-filters-widget.hide-filters .jetpack-search-filters-widget__filter { + display: none; +} + +.button.jetpack-search-filters-widget__add-filter { + margin-bottom: 10px; +} + +/* Assume that taxonomy select is the default selected. Other controls should be hidden here. */ +.jetpack-search-filters-widget__post-type-select { + display: none; +} + +.jetpack-search-filters-widget__date-histogram-select { + display: none; +} + +.jetpack-search-filters-widget__filter-placeholder { + border: 1px #555 dashed; + background-color: #eee; + height: 286px; + margin-bottom: 12px; +} + +/* When post type is selected, remove the other controls */ +.jetpack-search-filters-widget__filter.is-post_type .jetpack-search-filters-widget__taxonomy-select { + display: none; +} + +/* When date is selected, remove the other controls */ +.jetpack-search-filters-widget__filter.is-date_histogram .jetpack-search-filters-widget__date-histogram-select { + display: inline; +} + +.jetpack-search-filters-widget__filter.is-date_histogram .jetpack-search-filters-widget__taxonomy-select { + display: none; +} + +.jetpack-search-filters-widget.hide-post-types .jetpack-search-filters-widget__post-types-select { + display: none; +} + +.jetpack-search-filters-help:before { + display: inline-block; + position: relative; + font-family: dashicons; + font-size: 20px; + top: 5px; + line-height: 1px; + content:"\f223"; +} +.jetpack-search-filters-help { + padding: 5px 5px 15px 0; +} + +.jetpack-search-filters-widget__post-types-select label { + display: block; + margin-bottom: 4px; +} + +.jetpack-search-filters-widget__post-types-select input[type="checkbox"] { + margin-left: 24px; +} + +body.no-js .jetpack-search-filters-widget__add-filter-wrapper { + display: none; +} diff --git a/plugins/jetpack/modules/widgets/search/css/search-widget-frontend.css b/plugins/jetpack/modules/widgets/search/css/search-widget-frontend.css new file mode 100644 index 00000000..58c7cf3e --- /dev/null +++ b/plugins/jetpack/modules/widgets/search/css/search-widget-frontend.css @@ -0,0 +1,66 @@ +.jetpack-search-filters-widget__sub-heading { + font-size: inherit; + font-weight: bold; + margin: 0 0 .5em; + padding: 0; +} + +/* The first heading after the form */ +.jetpack-search-form + .jetpack-search-filters-widget__sub-heading { + margin-top: 1.5em; + margin-bottom: 0.5em !important; +} + +.jetpack-search-filters-widget__clear { + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +.jetpack-search-sort-wrapper { + margin-top: 1em; + margin-bottom: 1.5em; +} + +.jetpack-search-sort-wrapper label { + display: inherit; +} + +.widget_search .jetpack-search-filters-widget__filter-list input[type="checkbox"] { + width: auto; + height: auto; +} + +ul.jetpack-search-filters-widget__filter-list li { + border: none; + padding: 0; + list-style: none; +} + +ul.jetpack-search-filters-widget__filter-list li a { + text-decoration: none; +} + +ul.jetpack-search-filters-widget__filter-list li a:hover { + box-shadow: none; +} + +ul.jetpack-search-filters-widget__filter-list li label { + font-weight: inherit; + display: inherit; +} + +.jetpack-search-filters-widget__filter-list { + list-style: none; +} + +ul.jetpack-search-filters-widget__filter-list { + margin-bottom: 1.5em; +} + +body.search .jetpack-search-form input[name="s"]::placeholder { + color: transparent; +} + +body.search .jetpack-search-form input[name="s"].show-placeholder::placeholder { + color: inherit; +} diff --git a/plugins/jetpack/modules/widgets/search/js/search-widget-admin.js b/plugins/jetpack/modules/widgets/search/js/search-widget-admin.js new file mode 100644 index 00000000..5840a408 --- /dev/null +++ b/plugins/jetpack/modules/widgets/search/js/search-widget-admin.js @@ -0,0 +1,360 @@ +/* globals jetpack_search_filter_admin, jQuery, analytics */ + +( function( $, args ) { + var defaultFilterCount = ( 'undefined' !== typeof args && args.defaultFilterCount ) ? + args.defaultFilterCount : + 5; // Just in case we couldn't find the defaultFiltercount arg + + $( document ).ready( function() { + setListeners(); + + window.JetpackSearch = window.JetpackSearch || {}; + window.JetpackSearch.addFilter = addFilter; + + // Initialize Tracks + if ( 'undefined' !== typeof analytics && args.tracksUserData ) { + analytics.initialize( args.tracksUserData.userid, args.tracksUserData.username ); + } + } ); + + function generateFilterTitlePlaceholder( container ) { + var placeholder = null, + isModified = null, + isMonth = null, + type = container.find( '.filter-select' ).val(); + + if ( 'taxonomy' === type ) { + placeholder = container.find('.taxonomy-select option:selected').text().trim(); + } else if ( 'date_histogram' === type && args && args.i18n ) { + isModified = ( -1 !== container.find( '.date-field-select' ).val().indexOf( 'modified' ) ); + isMonth = ( 'month' === container.find( '.date-interval-select' ).val() ); + + if ( isMonth ) { + placeholder = isModified ? + args.i18n.monthUpdated : + args.i18n.month; + } else { + placeholder = isModified ? + args.i18n.yearUpdated : + args.i18n.year; + } + } else { + placeholder = container.find('.filter-select option:selected').text().trim(); + } + + $( container ).find('.jetpack-search-filters-widget__title input').prop( 'placeholder', placeholder ); + } + + var addFilter = function( filtersContainer, args ) { + var template = _.template( + filtersContainer + .closest( '.jetpack-search-filters-widget' ) + .find( '.jetpack-search-filters-widget__filter-template' ) + .html() + ); + generateFilterTitlePlaceholder( filtersContainer.append( template( args ) ) ); + }; + + var setListeners = function( widget ) { + widget = ( 'undefined' === typeof widget ) ? + $( '.jetpack-search-filters-widget' ): + widget; + + var getContainer = function( el ) { + return $( el ).closest('.jetpack-search-filters-widget__filter'); + }; + + widget.on( 'change', '.filter-select', function() { + var select = $( this ), + selectVal = select.val(), + eventArgs = { + is_customizer: args.tracksEventData.is_customizer + }; + + eventArgs.type = selectVal; + + select + .closest( '.jetpack-search-filters-widget__filter' ) + .attr( 'class', 'jetpack-search-filters-widget__filter' ) + .addClass( 'is-' + selectVal ); + + generateFilterTitlePlaceholder( getContainer( this ) ); + + trackAndBumpMCStats( 'changed_filter_type', eventArgs ); + } ); + + // enable showing sort controls only if showing search box is enabled + widget.on( 'change', '.jetpack-search-filters-widget__search-box-enabled', function() { + var checkbox = $( this ), + checkboxVal = checkbox.is(':checked'), + filterParent = checkbox.closest( '.jetpack-search-filters-widget' ), + sortControl = filterParent.find( '.jetpack-search-filters-widget__sort-controls-enabled' ); + + filterParent.toggleClass( 'hide-post-types' ); + + if ( checkboxVal ) { + sortControl.removeAttr( 'disabled' ); + trackAndBumpMCStats( 'enabled_search_box', args.tracksEventData ); + } else { + sortControl.prop( 'checked', false ); + sortControl.prop( 'disabled', true ); + trackAndBumpMCStats( 'disabled_search_box', args.tracksEventData ); + } + } ); + + widget.on( 'change', '.jetpack-search-filters-widget__sort-controls-enabled', function() { + if ( $( this ).is( ':checked' ) ) { + trackAndBumpMCStats( 'enabled_sort_controls', args.tracksEventData ); + } else { + trackAndBumpMCStats( 'disabled_sort_controls', args.tracksEventData ); + } + } ); + + widget.on( 'click', '.jetpack-search-filters-widget__post-types-select input[type="checkbox"]', function( e ) { + var t = $( this ); + var siblingsChecked = t.closest( '.jetpack-search-filters-widget' ) + .find( '.jetpack-search-filters-widget__post-types-select input[type="checkbox"]:checked' ); + + if ( 0 === siblingsChecked.length ) { + e.preventDefault(); + e.stopPropagation(); + + trackAndBumpMCStats( 'attempted_no_post_types', args.tracksEventData ); + } + } ); + + widget.on( 'change', '.jetpack-search-filters-widget__post-types-select input[type="checkbox"]', function() { + var t = $( this ); + var eventArgs = { + is_customizer: args.tracksEventData.is_customizer, + post_type: t.val() + }; + + if ( wp && wp.customize ) { + wp.customize.state( 'saved' ).set( false ); + } + + if ( t.is( ':checked' ) ) { + trackAndBumpMCStats( 'added_post_type', eventArgs ); + } else { + trackAndBumpMCStats( 'removed_post_type', eventArgs ); + } + } ); + + widget.on( 'change', '.jetpack-search-filters-widget__sort-order', function() { + var eventArgs = { + is_customizer: args.tracksEventData.is_customizer + }; + + eventArgs.order = $( this ).val(); + + if ( wp && wp.customize ) { + wp.customize.state( 'saved' ).set( false ); + } + + trackAndBumpMCStats( 'changed_sort_order', eventArgs ); + } ); + + widget.on( 'change', '.jetpack-search-filters-widget__taxonomy-select select', function() { + var eventArgs = { + is_customizer: args.tracksEventData.is_customizer + }; + + eventArgs.taxonomy = $( this ).val(); + + generateFilterTitlePlaceholder( getContainer( this ) ); + + if ( wp && wp.customize ) { + wp.customize.state( 'saved' ).set( false ); + } + + trackAndBumpMCStats( 'changed_taxonomy', eventArgs ); + } ); + + widget.on( 'change', 'select.date-field-select', function() { + var eventArgs = { + is_customizer: args.tracksEventData.is_customizer + }; + + eventArgs.field = $( this ).val(); + + generateFilterTitlePlaceholder( getContainer( this ) ); + + if ( wp && wp.customize ) { + wp.customize.state( 'saved' ).set( false ); + } + + trackAndBumpMCStats( 'changed_date_field', eventArgs ); + } ); + + widget.on( 'change', 'select.date-interval-select', function() { + var eventArgs = { + is_customizer: args.tracksEventData.is_customizer + }; + + eventArgs.interval = $( this ).val(); + + generateFilterTitlePlaceholder( getContainer( this ) ); + + if ( wp && wp.customize ) { + wp.customize.state( 'saved' ).set( false ); + } + + trackAndBumpMCStats( 'changed_date_interval', eventArgs ); + } ); + + widget.on( 'change', 'input.filter-count', function() { + var eventArgs = { + is_customizer: args.tracksEventData.is_customizer + }; + + eventArgs.count = $( this ).val(); + + if ( wp && wp.customize ) { + wp.customize.state( 'saved' ).set( false ); + } + + trackAndBumpMCStats( 'changed_filter_count', eventArgs ); + } ); + + // add filter button + widget.on( 'click', '.jetpack-search-filters-widget__add-filter', function( e ) { + e.preventDefault(); + + var filtersContainer = $( this ) + .closest( '.jetpack-search-filters-widget' ) + .find( '.jetpack-search-filters-widget__filters' ); + + addFilter( filtersContainer, { + type: 'taxonomy', + taxonomy: '', + post_type: '', + field: '', + interval: '', + count: defaultFilterCount, + name_placeholder: '', + name: '' + } ); + + if ( wp && wp.customize ) { + wp.customize.state( 'saved' ).set( false ); + } + + // Trigger change event to let legacy widget admin know the widget state is "dirty" + filtersContainer + .find( '.jetpack-search-filters-widget__filter' ) + .find( 'input, textarea, select' ) + .change(); + + trackAndBumpMCStats( 'added_filter', args.tracksEventData ); + } ); + + widget.on( 'click', '.jetpack-search-filters-widget__controls .delete', function( e ) { + e.preventDefault(); + var filter = $( this ).closest( '.jetpack-search-filters-widget__filter' ), + eventArgs = { + is_customizer: args.tracksEventData.is_customizer + }; + + eventArgs.type = filter.find( '.filter-select' ).val(); + + switch ( eventArgs.type ) { + case 'taxonomy': + eventArgs.taxonomy = filter.find( '.jetpack-search-filters-widget__taxonomy-select select' ).val(); + break; + case 'date_histogram': + eventArgs.dateField = filter.find( '.jetpack-search-filters-widget__date-histogram-select:first select' ).val(); + eventArgs.dateInterval = filter.find( '.jetpack-search-filters-widget__date-histogram-select:nth-child( 2 ) select' ).val(); + break; + } + + eventArgs.filterCount = filter.find( '.filter-count' ).val(); + + trackAndBumpMCStats( 'deleted_filter', eventArgs ); + + filter.find( 'input, textarea, select' ).change(); + filter.remove(); + + if ( wp && wp.customize ) { + wp.customize.state( 'saved' ).set( false ); + } + } ); + + // make the filters sortable + $( '.jetpack-search-filters-widget__filters' ).sortable( { + placeholder: 'jetpack-search-filters-widget__filter-placeholder', + axis: 'y', + revert: true, + cancel: 'input,textarea,button,select,option,.jetpack-search-filters-widget__controls a', + change: function() { + if ( wp && wp.customize ) { + wp.customize.state( 'saved' ).set( false ); + } + }, + update: function( e, ui ) { + $( ui.item ).find( 'input, textarea, select' ).change(); + } + } ) + .disableSelection(); + }; + + // When widgets are updated, remove and re-add listeners + $( document ).on( 'widget-updated widget-added', function( e, widget ) { + widget = $( widget ); + + var id = widget.attr( 'id' ), + isJetpackSearch = ( id && ( -1 !== id.indexOf( 'jetpack-search-filters' ) ) ); + + if ( ! isJetpackSearch ) { + return; + } + + // Intentionally not tracking widget additions and updates here as these events + // seem noisy in the customizer. We'll track those via PHP. + + widget.off( 'change', '.filter-select' ); + widget.off( 'click', '.jetpack-search-filters-widget__controls .delete' ); + widget.off( 'change', '.jetpack-search-filters-widget__use-filters' ); + widget.off( 'change', '.jetpack-search-filters-widget__search-box-enabled' ); + widget.off( 'change', '.jetpack-search-filters-widget__sort-controls-enabled' ); + widget.off( 'change', '.jetpack-search-filters-widget__sort-controls-enabled' ); + widget.off( 'change', '.jetpack-search-filters-widget__post-type-selector' ); + widget.off( 'change', '.jetpack-search-filters-widget__sort-order' ); + widget.off( 'change', '.jetpack-search-filters-widget__taxonomy-select' ); + widget.off( 'change', '.jetpack-search-filters-widget__date-histogram-select:first select' ); + widget.off( 'change', '.jetpack-search-filters-widget__date-histogram-select:eq(1) select' ); + widget.off( 'click', '.jetpack-search-filters-widget__post-types-select input[type="checkbox"]' ); + widget.off( 'click', '.jetpack-search-filters-widget__add-filter'); + + setListeners( widget ); + } ); + + /** + * This function will fire both a Tracks and MC stat. + * + * Tracks: Will be prefixed by 'jetpack_widget_search_' and use underscores. + * MC: Will not be prefixed, and will use dashes. + * + * Logic borrowed from `idc-notice.js`. + * + * @param eventName string + * @param extraProps object + */ + function trackAndBumpMCStats( eventName, extraProps ) { + if ( 'undefined' === typeof extraProps || 'object' !== typeof extraProps ) { + extraProps = {}; + } + + if ( eventName && eventName.length && 'undefined' !== typeof analytics && analytics.tracks && analytics.mc ) { + // Format for Tracks + eventName = eventName.replace( /-/g, '_' ); + eventName = eventName.indexOf( 'jetpack_widget_search_' ) !== 0 ? 'jetpack_widget_search_' + eventName : eventName; + analytics.tracks.recordEvent( eventName, extraProps ); + + // Now format for MC stats + eventName = eventName.replace( 'jetpack_widget_search_', '' ); + eventName = eventName.replace( /_/g, '-' ); + analytics.mc.bumpStat( 'jetpack-search-widget', eventName ); + } + } +} )( jQuery, jetpack_search_filter_admin ); diff --git a/plugins/jetpack/modules/widgets/search/js/search-widget.js b/plugins/jetpack/modules/widgets/search/js/search-widget.js new file mode 100644 index 00000000..8d1c4775 --- /dev/null +++ b/plugins/jetpack/modules/widgets/search/js/search-widget.js @@ -0,0 +1,15 @@ +jQuery( document ).ready( function() { + var filter_list = jQuery( '.jetpack-search-filters-widget__filter-list' ); + + filter_list.on( 'click', 'a', function() { + var checkbox = jQuery( this ).siblings( 'input[type="checkbox"]' ); + checkbox.prop( 'checked', ! checkbox.prop( 'checked' ) ); + } ); + + filter_list.find( 'input[type="checkbox"]' ).prop( 'disabled', false ).css( 'cursor', 'inherit' ).on( 'click', function() { + var anchor = jQuery( this ).siblings( 'a' ); + if ( anchor.length ) { + window.location.href = anchor.prop( 'href' ); + } + } ); +} ); |