(function () { 'use strict'; (function ($) { $(function () { init_vue(); init_custom_js(); }); function init_vue() { Vue.config.devtools = true; Vue.component('v-select', VueSelect.VueSelect); Vue.filter('i18n', function (str) { return FWP.__(str); }); // Defaults mixin var builder_defaults = { methods: { defaultLayout: function defaultLayout() { return { items: [this.defaultRow()], settings: this.getDefaultSettings('layout') }; }, defaultRow: function defaultRow() { return { type: 'row', items: [this.defaultCol()], settings: this.getDefaultSettings('row') }; }, defaultCol: function defaultCol() { return { type: 'col', items: [], settings: this.getDefaultSettings('col') }; }, defaultItem: function defaultItem(source) { return { type: 'item', source: source, settings: this.getDefaultSettings('item', source) }; }, mergeSettings: function mergeSettings(settings, type, source) { var defaults = this.getDefaultSettings(type, source); var default_keys = Object.keys(defaults); var setting_keys = Object.keys(settings); // Automatically inject new settings var missing_keys = default_keys.filter(function (name) { return !setting_keys.includes(name); }); missing_keys.forEach(function (name, index) { Vue.set(settings, name, defaults[name]); }); return settings; }, getSettingsMeta: function getSettingsMeta() { var settings = { num_columns: { type: 'number', title: FWP.__('Number of grid columns '), defaultValue: 1 }, grid_gap: { type: 'number', title: FWP.__('Spacing between results'), defaultValue: 10 }, no_results_text: { type: 'textarea', title: FWP.__('No results text') }, text_style: { type: 'text-style', title: FWP.__('Text style'), tab: 'style', defaultValue: { align: '', bold: false, italic: false } }, text_color: { type: 'color', title: FWP.__('Text color'), tab: 'style' }, font_size: { type: 'slider', title: FWP.__('Font size'), tab: 'style', defaultValue: { unit: 'px', size: 0 } }, background_color: { type: 'color', title: FWP.__('Background color'), tab: 'style' }, border: { type: 'border', title: FWP.__('Border'), tab: 'style', defaultValue: { style: 'none', color: '', width: { unit: 'px', top: 0, right: 0, bottom: 0, left: 0 } }, children: { style: { type: 'select', title: FWP.__('Border style'), choices: { 'none': FWP.__('None'), 'solid': FWP.__('Solid'), 'dashed': FWP.__('Dashed'), 'dotted': FWP.__('Dotted'), 'double': FWP.__('Double') } }, color: { type: 'color', title: FWP.__('Border color') }, width: { type: 'utrbl', title: FWP.__('Border width') } } }, button_text: { type: 'text', title: FWP.__('Button text') }, button_text_color: { type: 'color', title: FWP.__('Button text color') }, button_color: { type: 'color', title: FWP.__('Button color') }, button_padding: { type: 'utrbl', title: FWP.__('Button padding'), defaultValue: { unit: 'px', top: 0, right: 0, bottom: 0, left: 0 } }, separator: { type: 'text', title: FWP.__('Separator'), defaultValue: ', ' }, custom_css: { type: 'textarea', title: FWP.__('Custom CSS'), tab: 'style' }, grid_template_columns: { type: 'text', title: FWP.__('Column widths'), defaultValue: '1fr' }, content: { type: 'textarea', title: FWP.__('Content') }, image_size: { type: 'select', title: FWP.__('Image size'), defaultValue: 'thumbnail', choices: FWP.image_sizes, v_show: [ { type: 'source', value: 'featured_image' } ] }, author_field: { type: 'select', title: FWP.__('Author field'), defaultValue: 'display_name', choices: { 'display_name': FWP.__('Display name'), 'user_login': FWP.__('User login'), 'ID': FWP.__('User ID') } }, field_type: { type: 'select', title: FWP.__('Field type'), defaultValue: 'text', choices: { 'text': 'Text', 'date': 'Date', 'number': 'Number' } }, date_format: { type: 'text', title: FWP.__('Date format'), defaultValue: 'F j, Y', v_show: [ { type: 'field_type', value: 'date' }, { type: 'source', value: 'post_date' }, { type: 'source', value: 'post_modified' } ] }, input_format: { type: 'text', title: FWP.__('Input format'), defaultValue: 'Y-m-d', v_show: [ { type: 'field_type', value: 'date' }, { type: 'source', value: 'post_date' }, { type: 'source', value: 'post_modified' } ] }, number_format: { type: 'select', title: FWP.__('Number format'), choices: { '': FWP.__('None'), 'n': '1234', 'n.n': '1234.5', 'n.nn': '1234.56', 'n,n': '1,234', 'n,n.n': '1,234.5', 'n,n.nn': '1,234.56' }, v_show: [ { type: 'field_type', value: 'number' } ] }, link: { type: 'link', title: FWP.__('Link'), defaultValue: { type: 'none', href: '', target: '' }, children: { type: { type: 'select', title: FWP.__('Link type'), choices: { 'none': FWP.__('None'), 'post': FWP.__('Post URL'), 'custom': FWP.__('Custom URL') } } } }, prefix: { type: 'text', title: FWP.__('Prefix') }, suffix: { type: 'text', title: FWP.__('Suffix') }, is_hidden: { type: 'checkbox', defaultValue: false, suffix: FWP.__('Hide item?') }, padding: { type: 'utrbl', title: FWP.__('Padding'), defaultValue: { unit: 'px', top: 0, right: 0, bottom: 0, left: 0 }, tab: 'style' }, name: { type: 'text', title: FWP.__('Unique name'), notes: '(Required) unique element name, without spaces' }, css_class: { type: 'text', title: FWP.__('CSS class'), tab: 'style' } }; settings.button_border = this.$root.cloneObj(settings.border); settings.button_border.title = FWP.__('Button border'); settings.button_border.tab = 'basic'; settings.term_link = this.$root.cloneObj(settings.link); settings.term_link.children.type.choices = { 'none': FWP.__('None'), 'term': FWP.__('Term URL'), 'custom': FWP.__('Custom URL') }; return settings; }, getDefaultFields: function getDefaultFields(type, source) { var fields = []; if ('layout' == type) { fields.push('num_columns', 'grid_gap', 'no_results_text'); } if ('row' == type) { fields.push('grid_template_columns'); } if ('item' == type) { if ('html' == source) { fields.push('content'); } if ('featured_image' == source) { fields.push('image_size', 'link'); } if ('button' == source) { fields.push('button_text', 'button_text_color', 'button_color', 'button_padding', 'button_border', 'link'); } if ('post_date' == source || 'post_modified' == source) { fields.push('date_format'); } if ('post_title' == source) { fields.push('link'); } if ('post_author' == source) { fields.push('author_field'); } if (0 === source.indexOf('cf/')) { fields.push('field_type', 'date_format', 'input_format', 'number_format', 'link'); } if (0 === source.indexOf('woo/')) { fields.push('field_type', 'date_format', 'input_format', 'number_format'); } if (0 === source.indexOf('tax/')) { fields.push('separator', 'term_link'); } if (!['html', 'button', 'featured_image'].includes(source)) { fields.push('prefix', 'suffix'); } } fields.push('border', 'background_color', 'padding', 'text_color', 'text_style', 'font_size', 'name', 'css_class'); if ('layout' == type) { fields.push('custom_css'); } if ('item' == type) { fields.push('is_hidden'); } return fields; }, getDefaultSettings: function getDefaultSettings(type, source) { var settings = {}; var settings_meta = this.getSettingsMeta(); var fields = this.getDefaultFields(type, source); fields.forEach(function (name) { var defaultValue = settings_meta[name].defaultValue || ''; if ('name' == name) { defaultValue = 'el-' + Math.random().toString(36).substring(7); } settings[name] = defaultValue; }); return settings; } } }; /* ================ query builder ================ */ Vue.component('query-builder', { props: { query_obj: { type: Object, required: true }, template: { type: Object, required: true } }, template: "\n
\n

Which results should be in the listing?

\n\n
\n {{ 'Fetch' | i18n }}\n \n \n\n {{ 'and show' | i18n }}\n \n {{ 'per page' | i18n }}\n
\n\n
\n {{ 'Sort by' | i18n }}\n
\n\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n\n
\n {{ 'Narrow results by' | i18n }}\n
\n\n
\n \n \n \n \n \n\n \n\n \n\n \n
\n Type a value, then press \"Enter\" to add it\n
\n \n\n \n
\n\n
\n {{ 'Add query sort' | i18n }}\n {{ 'Add query filter' | i18n }}\n {{ 'Convert to query args' | i18n }}\n
\n
\n ", methods: { addTag: function addTag(newTag, value) { value.push(newTag); }, getPlaceholder: function getPlaceholder(ref) { var key = ref.key; return ('tax/' == key.substr(0, 4)) ? FWP.__('Enter term slugs') : FWP.__('Enter values'); }, maybeShowValue: function maybeShowValue(compare) { return !['EXISTS', 'NOT EXISTS', 'EMPTY', 'NOT EMPTY'].includes(compare); }, showCompare: function showCompare(option, ref) { var key = ref.key; var type = ref.type; if ('tax/' == key.substr(0, 4)) { if (!['IN', 'NOT IN', 'EXISTS', 'NOT EXISTS'].includes(option)) { return false; } } else if (['ID', 'post_author', 'post_status', 'post_name'].includes(key)) { if (option != 'IN' && option != 'NOT IN') { return false; } } else if ('DATE' == type || 'post_date' == key || 'post_modified' == key) { if (!['>', '>=', '<', '<='].includes(option)) { return false; } } else if ('CHAR' == type) { if (['>', '>=', '<', '<='].includes(option)) { return false; } } return true; }, addSortCriteria: function addSortCriteria() { this.query_obj.orderby.push({ key: 'title', order: 'ASC', type: 'CHAR' }); }, addFilterCriteria: function addFilterCriteria() { this.query_obj.filters.push({ key: 'ID', value: [], compare: 'IN', type: 'CHAR' }); }, deleteSortCriteria: function deleteSortCriteria(index) { Vue.delete(this.query_obj.orderby, index); }, deleteFilterCriteria: function deleteFilterCriteria(index) { Vue.delete(this.query_obj.filters, index); } } }); Vue.component('fselect', { data: function data() { return { prev_key: '' }; }, props: ['row'], template: "\n \n ", mounted: function mounted() { fSelect(this.$el); }, /** * fSelects won't refresh when deleting, so we need to * manually reload() the changed elements */ beforeUpdate: function beforeUpdate() { this.prev_key = this.$el.getAttribute('data-key'); }, updated: function updated() { if (this.row.key != this.prev_key) { this.$el.fselect.reload(); } } }); /* ================ layout builder ================ */ Vue.component('builder', { props: { layout: Object }, template: "\n
\n
\n

How should an individual result appear?

\n
\n \n \n \n \n
\n
\n \n
\n " }); Vue.component('setting-wrap', { mixins: [builder_defaults], props: ['settings', 'name', 'source', 'tab'], template: "\n
\n
\n {{ title }}\n
\n
\n
\n
\n
\n ", computed: { getSettingComponent: function getSettingComponent() { return 'setting-' + this.type; }, isVisible: function isVisible() { var ret = true; var self = this; if ('undefined' === typeof this.meta.tab) { this.meta.tab = 'basic'; } if (this.meta.tab !== this.tab) { ret = false; } else if ('undefined' !== typeof this.meta.v_show) { ret = false; this.meta.v_show.forEach(function (cond, index) { var type = cond.type; var setting_val = ('source' == type) ? self[type] : self.settings[type]; var cond_value = cond.value || ''; var cond_compare = cond.compare || '=='; var is_match = ('==' == cond_compare) ? setting_val == cond_value : setting_val != cond_value; if (is_match) { ret = true; } }); } return ret; } }, created: function created() { this.settings_meta = this.getSettingsMeta(); this.meta = this.settings_meta[this.name]; this.type = this.meta.type; this.title = this.meta.title; } }); Vue.component('setting-text', { props: ['settings', 'name', 'meta'], template: '' }); Vue.component('setting-number', { props: ['settings', 'name', 'meta'], template: '' }); Vue.component('setting-textarea', { props: ['settings', 'name', 'meta'], template: '' }); Vue.component('setting-slider', { props: ['settings', 'name', 'meta'], template: "\n
\n \n \n
\n ", computed: { fontSizeLabel: function fontSizeLabel() { var val = this.settings[this.name]; return (0 === val.size) ? 'none' : val.size + val.unit; } } }); Vue.component('setting-color', { props: ['settings', 'name', 'meta'], template: "\n
\n
\n \n \n
\n X\n
", mounted: function mounted() { var self = this; var $canvas = self.$el.getElementsByClassName('color-canvas')[0]; var $preview = self.$el.getElementsByClassName('color-preview')[0]; var $input = self.$el.getElementsByClassName('color-input')[0]; var $clear = self.$el.getElementsByClassName('color-clear')[0]; $preview.style.backgroundColor = $input.value; var picker = new Picker({ parent: $canvas, popup: 'left', alpha: false, onDone: function onDone(color) { var hex = color.hex().substr(0, 7); self.settings[self.name] = hex; $preview.style.backgroundColor = hex; } }); picker.onOpen = function(color) { picker.setColor($input.value); }; $clear.addEventListener('click', function() { self.settings[self.name] = ''; $preview.style.backgroundColor = ''; }); } }); Vue.component('setting-link', { props: ['settings', 'name', 'meta'], template: "\n
\n \n \n\n
\n \n
\n
\n \n {{ 'Open in new tab?' | i18n }}\n
\n
\n " }); Vue.component('setting-border', { props: ['settings', 'name', 'meta'], template: "\n
\n \n \n\n
\n
\n\n \n \n\n
\n\n \n \n
\n
\n " }); Vue.component('setting-checkbox', { props: ['settings', 'name', 'meta'], template: "\n
\n {{ meta.suffix }}\n
\n " }); Vue.component('setting-select', { props: ['settings', 'name', 'meta'], template: "\n \n " }); Vue.component('setting-utrbl', { props: ['settings', 'name', 'meta'], template: "\n
\n
unit
\n
top
\n
right
\n
bottom
\n
left
\n
\n " }); Vue.component('setting-text-style', { props: ['settings', 'name', 'meta'], template: "\n
\n \n \n \n \n \n
\n ", methods: { toggleChoice: function toggleChoice(opt, val) { var old_val = this.settings[this.name][opt]; if ('undefined' !== typeof val) { this.settings[this.name][opt] = (val !== old_val) ? val : ''; } else { this.settings[this.name][opt] = ! old_val; } }, isActive: function isActive(opt, val) { var new_val = ('undefined' !== typeof val) ? val : true; return this.settings[this.name][opt] === new_val; } } }); Vue.component('builder-settings', { mixins: [builder_defaults], props: { layout: Object }, data: function data() { return { title: '', type: 'layout', settings: this.layout.settings, source: '', active_tab: 'basic' } }, template: "\n
\n

\n \n {{ settingTitle }}\n

\n
\n
\n {{ 'Basic' | i18n }}\n {{ 'Style' | i18n }}\n
\n \n \n
\n
\n ", computed: { settingTitle: function settingTitle() { return ('' === this.title) ? FWP.__('Settings') : this.title; }, settingsFields: function settingsFields() { return this.getDefaultFields(this.type, this.source); } }, methods: { uniqueKey: function uniqueKey() { // method to prevent caching return Math.floor(Math.random() * 999999); }, isActiveTab: function isActiveTab(which) { return (this.active_tab === which) ? 'active' : ''; }, setActiveTab: function setActiveTab(which) { this.active_tab = which; } }, created: function created() { var self = this; this.$root.$on('edit-layout', function () { self.title = ''; self.type = 'layout'; self.settings = self.mergeSettings(self.layout.settings, self.type); self.source = ''; }); this.$root.$on('edit-row', function (ref, num) { var settings = ref.settings; self.title = FWP.__('Row') + ' ' + num; self.type = 'row'; self.settings = self.mergeSettings(settings, self.type); self.source = ''; }); this.$root.$on('edit-col', function (ref, num) { var settings = ref.settings; self.title = FWP.__('Column') + ' ' + num; self.type = 'col'; self.settings = self.mergeSettings(settings, self.type); self.source = ''; }); this.$root.$on('edit-item', function (ref) { var source = ref.source; var settings = ref.settings; self.title = FWP.layout_data[source]; self.type = 'item'; self.settings = self.mergeSettings(settings, self.type, source); self.source = source; }); } }); Vue.component('builder-row', { mixins: [builder_defaults], props: { row: Object, rows: Array, index: Number, is_child: Boolean }, template: "\n
\n
\n \n \n \n \n
\n
\n \n \n
\n
\n ", computed: { classIsChild: function classIsChild() { return this.is_child ? 'is-child' : 'not-child'; } }, methods: { addRow: function addRow() { this.rows.splice(this.index + 1, 0, this.defaultRow()); if (1 < this.rows.length) { this.$root.$emit('edit-row', this.rows[this.index + 1], this.index + 2); } else { this.$root.$emit('edit-layout'); } }, addCol: function addCol() { var len = this.row.items.push(this.defaultCol()); this.$root.$emit('edit-col', this.row.items[len - 1], len); var grid_str = '1fr '.repeat(this.row.items.length).trim(); this.row.settings.grid_template_columns = grid_str; }, editRow: function editRow() { this.$root.$emit('edit-row', this.row, this.index + 1); }, deleteRow: function deleteRow() { Vue.delete(this.rows, this.index); this.$root.$emit('edit-layout'); // Add default row if (this.rows.length < 1) { if (! this.is_child) { this.addRow(); } } } } }); Vue.component('builder-col', { mixins: [builder_defaults], props: { col: Object, cols: Array, index: Number }, data: function data() { return { adding_item: false } }, template: "\n
\n \n \n
\n \n \n
\n
\n \n
\n \n \n \n \n
\n
\n
+
\n
\n
\n
\n
\n ", methods: { addItem: function addItem() { this.adding_item = ! this.adding_item; }, editCol: function editCol() { this.$root.$emit('edit-col', this.col, this.index + 1); this.adding_item = false; }, deleteCol: function deleteCol() { // Remove the column this.cols.splice(this.index, 1); // Show the "Layout" settings this.$root.$emit('edit-layout'); // Add default column if (this.cols.length < 1) { this.cols.push(this.defaultCol()); } // Adjust the row's `grid_template_columns` string var grid_str = '1fr '.repeat(this.cols.length).trim(); this.$parent.row.settings.grid_template_columns = grid_str; }, away: function away() { this.adding_item = false; } } }); Vue.component('col-resizer', { props: { cols: Array, index: Number }, data: function data() { return { isResizing: false } }, template: '
', computed: { classNames: function classNames() { return [ 'resizer', this.isResizing ? 'is-resizing' : '' ]; } }, methods: { onMouseDown: function onMouseDown(ref) { var this$1$1 = this; var resizer = ref.target; var initialPageX = ref.pageX; ref.pageY; if (! resizer.classList.contains('resizer')) { return; } var self = this; var pane = resizer.parentElement; var row_inner = pane.parentElement; var initialPaneWidth = pane.offsetWidth; var resize = function (initialSize, offset) { if ( offset === void 0 ) offset = 0; var containerWidth = row_inner.clientWidth; var paneWidth = initialSize + offset; var width = ((paneWidth / containerWidth) * 100).toFixed(1) + '%'; var gridColumns = this$1$1.$parent.$parent.row.settings.grid_template_columns.split(' '); gridColumns[this$1$1.index] = width; this$1$1.$parent.$parent.row.settings.grid_template_columns = gridColumns.join(' '); }; // This adds is-resizing class to container self.isResizing = true; var onMouseMove = function (ref) { var pageX = ref.pageX; ref.pageY; resize(initialPaneWidth, pageX - initialPageX); }; var onMouseUp = function () { // Run resize one more time to set computed width/height. resize(pane.clientWidth); // This removes is-resizing class to container self.isResizing = false; window.removeEventListener('mousemove', onMouseMove); window.removeEventListener('mouseup', onMouseUp); }; window.addEventListener('mousemove', onMouseMove); window.addEventListener('mouseup', onMouseUp); } } }); Vue.component('builder-item', { props: { item: Object, items: Array, index: Number }, template: "\n
\n
\n \n
\n
\n \n \n
\n
\n ", methods: { editItem: function editItem() { this.$root.$emit('edit-item', this.item); }, deleteItem: function deleteItem() { this.items.splice(this.index, 1); this.$root.$emit('edit-layout'); } } }); Vue.component('popover', { mixins: [builder_defaults], props: { col: Object }, data: function data() { return { keywords: '' } }, template: "\n
\n
\n \n
\n
\n \n
\n
\n \n ", methods: { handleBlur: function handleBlur(e) { if (!e.currentTarget.contains(e.relatedTarget)) { this.$parent.adding_item = false; } }, isMatch: function isMatch(label) { var bool = ('' == this.keywords) ? true : false; if (false === bool) { var needle = this.keywords.toLowerCase(); var haystack = label.toLowerCase(); if (haystack.includes(needle)) { bool = true; } } return bool; }, saveItem: function saveItem(source) { if ('row' == source) { var len = this.col.items.push(this.defaultRow()); this.$root.$emit('edit-row', this.col.items[len - 1], len); } else { var len$1 = this.col.items.push(this.defaultItem(source)); this.$root.$emit('edit-item', this.col.items[len$1 - 1]); } this.$parent.adding_item = false; } }, mounted: function mounted() { this.$refs.keywords.focus(); } }); /* ================ facets / templates ================ */ Vue.component('facets', { props: ['facets'], template: "\n \n \n
\n
\n {{ facet.label }}\n \n
\n
{{ facet.name }}
\n
{{ facet.type }}
\n
\n
{{ getRowCount(facet.name) }}
\n
\n
\n
\n
\n
Copy shortcode
\n
Duplicate
\n
Delete
\n
\n
\n
\n \n
\n ", methods: { getSource: function getSource(source) { return FWP.layout_data[source] || '-'; }, getRowCount: function getRowCount(facet_name) { if (this.$root.is_indexing) { return '...'; } return this.$root.row_counts[facet_name] || '-'; } } }); Vue.component('templates', { props: ['templates'], template: "\n \n \n
\n
\n {{ template.label }}\n \n
\n
{{ template.name }}
\n
{{ getDisplayMode(index) }}
\n
{{ getPostTypes(index) }}
\n
\n
\n
\n
\n
Copy shortcode
\n
Duplicate
\n
Delete
\n
\n
\n
\n \n
\n ", methods: { getDisplayMode: function getDisplayMode(index) { var template = this.templates[index]; return ('undefined' !== typeof template.modes) ? template.modes.display : 'advanced'; }, getPostTypes: function getPostTypes(index) { var template = this.templates[index]; if ('undefined' !== typeof template.modes) { if ('visual' == template.modes.query) { var post_types = template.query_obj.post_type; if (0 === post_types.length) { return ''; } else { return post_types.map(function (type) { return type.label; }).join(', '); } } } return ''; } } }); Vue.component('facet-edit', { data: function data() { return { facet: {} } }, created: function created() { this.facet = this.$root.editing; }, methods: { setName: function setName(e) { this.facet.name = this.$root.sanitizeName(e.target.innerHTML); }, unlock: function unlock() { Vue.delete(this.facet, '_code'); } }, template: "\n
\n
\n This facet is registered in code. Click to allow edits:\n \n
\n
\n
\n
{{ 'Label' | i18n }}
\n
\n \n \n \n {{ 'Copy shortcode' | i18n }}\n \n
\n
\n
\n
{{ 'Facet type' | i18n }}
\n
\n \n \n
\n
\n
\n
{{ 'Data source' | i18n }}
\n
\n \n
\n
\n \n
\n
\n " }); Vue.component('template-edit', { mixins: [builder_defaults], data: function data() { return { template: {}, tab: 'display' } }, created: function created() { this.template = this.$root.editing; // Set defaults for the layout builder if (! this.template.layout) { Vue.set(this.template, 'layout', this.defaultLayout()); } // Set defaults for the query builder if (! this.template.query_obj) { Vue.set(this.template, 'query_obj', { post_type: [], posts_per_page: 10, orderby: [], filters: [] }); } // Set the modes if (! this.template.modes) { Vue.set(this.template, 'modes', { display: ('' !== this.template.template) ? 'advanced' : 'visual', query: ('' !== this.template.query) ? 'advanced' : 'visual' }); } }, methods: { setName: function setName(e) { this.template.name = this.$root.sanitizeName(e.target.innerHTML); }, isMode: function isMode(mode) { return this.template.modes[this.tab] === mode; }, switchMode: function switchMode() { var now = this.template.modes[this.tab]; this.template.modes[this.tab] = ('visual' === now) ? 'advanced' : 'visual'; }, unlock: function unlock() { Vue.delete(this.template, '_code'); } }, template: "\n
\n
\n This template is registered in code. Click to allow edits:\n \n
\n
\n
\n \n \n \n {{ 'Copy shortcode' | i18n }}\n \n
\n\n \n\n
\n {{ 'Display' | i18n }}\n {{ 'Query' | i18n }}\n
\n\n
\n
\n \n
\n
\n

{{ 'Display Code' | i18n }} {{ 'Help' | i18n }}

\n \n
\n
\n\n
\n
\n \n
\n
\n

{{ 'Query Arguments' | i18n }} {{ 'Help' | i18n }}

\n \n
\n
\n
\n
\n " }); Vue.component('facet-types', { props: ['facet', 'selected', 'types'], template: "\n \n " }); Vue.component('facet-settings', { props: ['facet'], template: '', methods: { getFields: function getFields(aliases) { var output = []; $.each(aliases, function(name) { output = output.concat(FWP.facet_fields[name].names); }); return output; } }, computed: { // dynamic component so the data bindings (e.g. v-model) get compiled dynComponent: function dynComponent() { return { template: '
' + this.settingsHtml + '
', props: ['facet'] } }, settingsHtml: function settingsHtml() { var self = this; var facet_obj = FWP.facet_types[self.facet.type]; var aliases = facet_obj.fields; // Support for settings_html() in < 3.9 if ('undefined' === typeof aliases) { if ('undefined' !== typeof FWP.clone[self.facet.type]) { FWP.facet_fields[self.facet.type + '_fields'] = { names: [], html: FWP.clone[self.facet.type] }; var $html = $(FWP.clone[self.facet.type]); $.each($html.nodes[0].children, function(chunk) { $(chunk).find('input, textarea, select, [setting-name]').each(function() { var $el = $(this); var setting_name = $el.attr('setting-name'); if (null === setting_name) { setting_name = $el.attr('class').split(' ')[0].replace(/-/g, '_').substr(6); } FWP.facet_fields[self.facet.type + '_fields'].names.push(setting_name); }); }); aliases = [self.facet.type + '_fields']; } } // Get the actual fields by parsing the aliases (groups) var fields = self.getFields(aliases); var html = ''; // Add UI-dependant fields if ('undefined' !== typeof facet_obj.ui_fields) { if ('undefined' !== typeof self.facet.ui_type && '' != self.facet.ui_type) { var ui_fields = facet_obj.ui_fields[self.facet.ui_type]; aliases = aliases.concat(ui_fields); fields = fields.concat(this.getFields(ui_fields)); } } var combined = ['label', 'name', 'type', 'source', '_code'].concat(fields); // Remove irrelevant settings $.each(Object.keys(self.facet), function(setting_name) { if (-1 == combined.indexOf(setting_name)) { Vue.delete(self.facet, setting_name); } }); // Add new settings $.each(aliases, function(alias_name) { var $parsed = $(FWP.facet_fields[alias_name].html); $.each(FWP.facet_fields[alias_name].names, function(setting_name) { var name_dashed = setting_name.replace(/_/g, '-'); var $input = $parsed.find('.facet-' + name_dashed); var val = $input.val(); if (0 < $input.len()) { $input.attr('v-model', 'facet.' + setting_name); if ('undefined' === typeof self.facet[setting_name]) { if ($input.is('[type=checkbox]')) { val = $input.nodes[0].checked ? 'yes' : 'no'; } if ('[]' === val) { val = []; } } else { val = self.facet[setting_name]; Vue.delete(self.facet, setting_name); } Vue.set(self.facet, setting_name, val); } }); // Update the documentFragment HTML to include the "v-model" $.each($parsed.nodes[0].children, function(el) { html += el.outerHTML; }); }); return html; } }, watch: { 'facet.type': function(val) { if ('search' == val || 'pager' == val || 'reset' == val || 'sort' == val) { Vue.delete(this.facet, 'source'); } } } }); Vue.component('data-sources', { props: { facet: Object, settingName: { type: String, default: 'source' } }, template: "\n \n ", computed: { className: function className() { return 'facet-' + this.settingName.replace(/_/g, '-'); } }, mounted: function mounted() { fSelect(this.$el); } }); Vue.component('facet-names', { props: { facet: Object, setting: String }, template: "\n \n ", computed: { className: function className() { return 'facet-' + this.setting.replace(/_/g, '-'); } }, methods: { bindSelectedClass: function bindSelectedClass(name) { return this.facet[this.setting].includes(name) ? 'selected' : ''; } }, created: function created() { if ('undefined' === typeof this.facet[this.setting]) { this.facet[this.setting] = []; } }, mounted: function mounted() { fSelect(this.$el, { 'placeholder': 'Choose facets' }); } }); Vue.component('ui-type', { props: { facet: Object }, created: function created() { this.ui_fields = FWP.facet_types[this.facet.type].ui_fields || []; this.sorted = Object.keys(this.ui_fields).reverse(); }, template: "\n \n " }); Vue.component('sort-options', { props: { facet: Object }, template: "\n
\n
\n
\n \n \n\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n 1\">\n
\n
\n
\n 0\">\n \n
\n
\n\n
\n {{ 'Add sort' | i18n }}\n
\n
\n ", methods: { addSort: function addSort() { this.facet.sort_options.push({ label: 'New option', name: 'new_option', orderby: [{ key: 'title', order: 'ASC', type: 'CHAR' }] }); }, addSortField: function addSortField(opts, index) { opts.splice(index + 1, 0, { key: 'title', order: 'ASC', type: 'CHAR' }); }, moveUp: function moveUp(opts, index) { opts.splice(index -1, 0, opts.splice(index, 1)[0]); }, removeItem: function removeItem(row, index) { Vue.delete(row, index); }, setName: function setName(row, e) { row.name = this.$root.sanitizeName(e.target.innerHTML); } } }); // Vue instance FWP.vue = new Vue({ el: '#app', data: { app: FWP.data, editing: {}, editing_facet: false, editing_template: false, row_counts: {}, active_tab: 'facets', active_subnav: 'general', is_support_loaded: false, is_name_editable: false, is_rebuild_open: false, is_indexing: false, timeout: null }, methods: { addItem: function addItem(type) { if ('facet' == type) { var len = this.app.facets.push({ 'name': 'new_facet', 'label': 'New Facet', 'type': 'checkboxes', 'source': 'post_type' }); this.editItem('facet', this.app.facets[len-1]); } else { var len$1 = this.app.templates.push({ 'name': 'new_template', 'label': 'New Template', 'query': '', 'template': '' }); this.editItem('template', this.app.templates[len$1-1]); } }, duplicateItem: function duplicateItem(type, index) { var facet = this.cloneObj(this.app[type + 's'][index]); facet.label += ' (copy)'; facet.name += '_copy'; this.app[type + 's'].splice(index+1, 0, facet); this.editItem(type, facet); }, editItem: function editItem(type, data) { this['editing_' + type] = true; this.editing = data; window.scrollTo(0, 0); }, doneEditing: function doneEditing() { this.editing_template = false; this.editing_facet = false; this.editing = {}; }, tabClick: function tabClick(which) { this.doneEditing(); this.active_tab = which; if ('support' === which) { this.is_support_loaded = true; } }, getItemLabel: function getItemLabel() { return this.editing.label; }, deleteItem: function deleteItem(type, index) { this.app[type + 's'].splice(index, 1); }, saveChanges: function saveChanges() { window.setStatus('load', FWP.__('Saving') + '...'); var data = JSON.parse(JSON.stringify(FWP.data)); // Remove code-based facets and templates data.facets = data.facets.filter(function (obj) { return 'undefined' === typeof obj['_code']; }); data.templates = data.templates.filter(function (obj) { return 'undefined' === typeof obj['_code']; }); // Settings save hook data = FWP.hooks.applyFilters('facetwp/save_settings', { action: 'facetwp_save_settings', nonce: FWP.nonce, data: data }); $.post(ajaxurl, data, { done: function (ref) { var code = ref.code; var message = ref.message; var code = ('success' == code) ? 'ok' : code; window.setStatus(code, message); }, fail: function (err) { window.setStatus('error', err); } }); }, rebuildAction: function rebuildAction() { this.is_indexing ? this.cancelReindex() : this.rebuildIndex(); }, rebuildIndex: function rebuildIndex() { var self = this; if (this.is_indexing) { return; } this.is_indexing = true; $.post(ajaxurl, { action: 'facetwp_rebuild_index', nonce: FWP.nonce }); window.setStatus('load', FWP.__('Indexing') + '... 0%'); this.timeout = setTimeout(function () { self.getProgress(); }, 5000); }, cancelReindex: function cancelReindex() { var self = this; $.post(ajaxurl, { action: 'facetwp_get_info', type: 'cancel_reindex', nonce: FWP.nonce }, { done: function (ref) { var message = ref.message; self.is_indexing = false; clearTimeout(self.timeout); window.setStatus('error', message); } }); }, getProgress: function getProgress() { var self = this; var isNumeric = function (obj) { return !Array.isArray(obj) && (obj - parseFloat(obj) + 1) >= 0; }; $.post(ajaxurl, { action: 'facetwp_heartbeat', nonce: FWP.nonce }, { done: function (data) { if ('-1' == data.pct) { self.is_indexing = false; if (data.rows.length < 1) { window.setStatus('error', FWP.__('The index table is empty')); } else { window.setStatus('ok', FWP.__('Indexing complete')); // Update the row counts $.each(data.rows, function(count, facet_name) { Vue.set(self.row_counts, facet_name, count); }); } } else if (isNumeric(data.pct)) { window.setStatus('load', FWP.__('Indexing') + '... ' + data.pct + '%'); self.is_indexing = true; self.timeout = setTimeout(function () { self.getProgress(); }, 5000); } else { window.setStatus('error', data); self.is_indexing = false; } } }); }, getInfo: function getInfo(type, label) { window.setStatus('load', FWP.__(label) + '...'); $.post(ajaxurl, { action: 'facetwp_get_info', type: type, nonce: FWP.nonce }, { done: function (ref) { var message = ref.message; window.setStatus('error', message); } }); }, getQueryArgs: function getQueryArgs(template) { template.modes.query = 'advanced'; template.query = FWP.__('Loading') + '...'; $.post(ajaxurl, { action: 'facetwp_get_query_args', query_obj: template.query_obj, nonce: FWP.nonce }, { done: function (message) { var json = JSON.stringify(message, null, 2); json = "'); template.query = json; } }); }, showIndexerStats: function showIndexerStats() { this.getInfo('indexer_stats', 'Looking'); }, searchablePostTypes: function searchablePostTypes() { this.getInfo('post_types', 'Looking'); }, purgeIndexTable: function purgeIndexTable() { this.getInfo('purge_index_table', 'Purging'); }, copyToClipboard: function copyToClipboard(name, type, ref) { var target = ref.target; var $this = $(target); var $el = $('.facetwp-clipboard'); var orig_text = $this.text(); try { $el.removeClass('hidden'); $el.val('[facetwp ' + type + '="' + name + '"]'); $el.nodes[0].select(); document.execCommand('copy'); $el.addClass('hidden'); $this.text(FWP.__('Copied!')); } catch(err) { $this.text(FWP.__('Press CTRL+C to copy')); } window.setTimeout(function () { $this.text(orig_text); }, 2000); }, activate: function activate() { $('.facetwp-activation-status').html(FWP.__('Activating') + '...'); $.post(ajaxurl, { action: 'facetwp_license', nonce: FWP.nonce, license: $('.facetwp-license').val() }, { done: function (ref) { var message = ref.message; $('.facetwp-activation-status').html(message); } }); }, isNameEditable: function isNameEditable(ref) { var name = ref.name; this.is_name_editable = ('' == name || 'new_' == name.substr(0, 4)); }, maybeEditName: function maybeEditName(item) { if (this.is_name_editable) { item.name = this.sanitizeName(item.label); } }, sanitizeName: function sanitizeName(name) { var val = name.trim().toLowerCase(); val = val.replace(/[^\w- ]/g, ''); // strip invalid characters val = val.replace(/[- ]/g, '_'); // replace space and hyphen with underscore val = val.replace(/[_]{2,}/g, '_'); // strip consecutive underscores val = ('pager' == val || 'sort' == val || 'labels' == val) ? val + '_' : val; // reserved return val; }, documentClick: function documentClick(ref) { var target = ref.target; var el = target; if (! el.classList.contains('btn-caret')) { this.is_rebuild_open = false; } }, cloneObj: function cloneObj(obj) { return JSON.parse(JSON.stringify(obj)); } }, computed: { isEditing: function isEditing() { return this.editing_facet || this.editing_template; }, indexButtonLabel: function indexButtonLabel() { return this.is_indexing ? FWP.__('Stop indexer') : FWP.__('Re-index'); } }, created: function created() { document.addEventListener('click', this.documentClick); }, mounted: function mounted() { this.getProgress(); } }); } function init_custom_js() { window.setStatus = function (code, message) { $('.facetwp-response').html(message); $('.facetwp-response-icon').nodes[0].setAttribute('data-status', code); if ('error' == code) { $('.facetwp-response').addClass('visible'); } }; $().on('click', '.facetwp-settings-section .facetwp-switch', function () { window.setStatus('error', 'Press "Save changes" to apply'); }); $().on('click', '.facetwp-response-wrap', function () { $('.facetwp-response').toggleClass('visible'); }); // Export $().on('click', '.export-submit', function () { $('.import-code').val(FWP.__('Loading') + '...'); $.post(ajaxurl, { action: 'facetwp_backup', nonce: FWP.nonce, action_type: 'export', items: $('.export-items').val() }, { done: function (resp) { $('.import-code').val(JSON.stringify(resp)); } }); }); // Import $().on('click', '.import-submit', function () { window.setStatus('load', FWP.__('Importing') + '...'); try { var code = JSON.parse($('.import-code').val()); $.post(ajaxurl, { action: 'facetwp_backup', nonce: FWP.nonce, action_type: 'import', import_code: code, overwrite: $('.import-overwrite').nodes[0].checked ? 1 : 0 }, { dataType: 'text', done: function (resp) { window.setStatus('ok', resp); setTimeout(function () { window.location.reload(); }, 1500); } }); } catch(err) { window.setStatus('error', 'Invalid JSON'); } }); // Initialize tooltips $().on('mouseover', '.facetwp-tooltip', function() { if (!this.classList.contains('.ftip-enabled')) { fTip(this, { content: function (node) { return $(node).find('.facetwp-tooltip-content').html(); } }).open(); } }); // fSelect fSelect('.export-items'); } })(fUtil); })();