(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 {{ 'Narrow results by' | i18n }}\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 ",
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 ",
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 "
});
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
\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 ",
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 ",
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 ",
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 "
});
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 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);
})();