HEX
Server: Apache
System: Linux p3plzcpnl506847.prod.phx3.secureserver.net 4.18.0-553.54.1.lve.el8.x86_64 #1 SMP Wed Jun 4 13:01:13 UTC 2025 x86_64
User: slfopp7cb1df (5698090)
PHP: 8.1.34
Disabled: NONE
Upload Files
File: //home/slfopp7cb1df/www/home/wp-content/themes/nanosoft/admin/js/options.js
( function( $ ) {
	"use strict";

	var Mixins = {
		methods: {
			triggerChange: function() {
				this.$emit( 'change', this );
			},

			getValue: function() {
				return $.extend( {}, this.value );
			},

			debounce: function(func, wait, immediate) {
				var timeout;
				return function() {
					var context = this, args = arguments;
					var later = function() {
						timeout = null;
						if (!immediate) func.apply(context, args);
					};
					var callNow = immediate && !timeout;
					clearTimeout(timeout);
					timeout = setTimeout(later, wait);
					if (callNow) func.apply(context, args);
				};
			}
		}
	}

	Vue.component( 'textfield', {
		props: ['value'],
		mixins: [Mixins],
		template: '\
			<div>\
				<input type="text" v-model:value="value" v-on:change="triggerChange" />\
			</div>',

		data: function() {
			return {
				value: this.value
			};
		},

		methods: {
			getValue: function() {
				return this.value;
			}
		}
	} );

	Vue.component( 'textareafield', {
		props: ['value'],
		mixins: [Mixins],
		template: '\
			<div>\
				<textarea type="text" v-model:value="value" v-on:change="triggerChange"></textarea>\
			</div>',

		data: function() {
			return {
				value: this.value
			};
		},

		methods: {
			getValue: function() {
				return this.value;
			}
		}
	} );

	/**
	 * The image uploader component
	 * @since  1.0.0
	 */
	Vue.component( 'image-upload', {
		props: {
			value: {
				type: Object,
				required: true,
				default: function () {
					return {
						id: false,
						url: false
					}
				}
			}
		},
		mixins: [Mixins],

		data: function() {
			return this.value;
		},

		template: '\
			<div class="image-uploader">\
				<div class="upload-dropzone">\
					<span class="upload-message">\
						Drop a file here or<br>\
						<a href="javascript:;" v-on:click="media.open()">select a file</a>\
						<a href="#" class="upload"></a>\
					</span>\
					<span v-if="value.url" class="upload-preview">\
						<img v-bind:src="value.url" />\
					</span>\
				</div>\
				<a v-if="value.url" href="javascript:;" v-on:click="_clear" class="button">Remove</a>\
			</div>\
		',

		mounted: function() {
			this.media = wp.media.frames.file_frame = wp.media({
				title: 'Choose Image',
				button: { text: 'Choose Image' },
				multiple: false,
				library: {
					type: 'image'
				}
			});

			this.media.on( 'select', ( function() {
				var selected = this.media.state().get('selection').first();

				this.value.id = selected.get( 'id' );
				this.value.url = selected.get( 'url' );
				
				this.triggerChange();
			} ).bind( this ) );
		},

		methods: {
			_clear: function() {
				this.value.id = -1;
				this.value.url = false;

				this.triggerChange();
			}
		}
	} );

	Vue.component( 'color', {
		props: ['value'],
		mixins: [Mixins],
		template: '<input type="text" v-bind:value="value" />',

		data: function() {
			return {
				value: this.value
			};
		},

		mounted: function() {
			var self     = this;
			var $element = $( this.$el );

			$element.spectrum( {
				showInput: true,
				showAlpha: true,
				allowEmpty:true,
				clickoutFiresChange: true,
				preferredFormat: "hex",
				chooseText: "Ok",
    			cancelText: "Cancel",
				change: function( color ) {
					self.value = color == null ? '' : color.toString();
					self.triggerChange();
				}
			} );
		},

		methods: {
			getValue: function() {
				return this.value;
			}
		}
	} );

	Vue.component( 'colors', {
		props: ['value', 'options'],
		mixins: [Mixins],
		template: '\
			<div>\
				<div v-for="(title, key) in options" class="color-field">\
					<label>{{ title }}</label>\
					<div class="color-input">\
						<color v-bind:value="value[key]" v-bind:data-key="key" v-on:change="changeValue"></color>\
					</div>\
				</div>\
			</div>',

		methods: {
			changeValue: function( context ) {
				this.value[ $( context.$el ).attr( 'data-key' ) ] = context.value;
				this.triggerChange();
			}
		}
	} );

	Vue.component( 'checkboxes', {
		props: ['value', 'options'],
		mixins: [Mixins],
		data: function() {
			var values = [];
			$.map( this.value, function( item, index ) {
				values.push( item );
			} );

			return {
				values: values
			}
		},
		template: '\
			<div>\
				<label v-for="(title, index) in options">\
					<input type="checkbox" v-bind:value="index" v-model="values" v-on:change="triggerChange" />\
					<span>{{ title }}</span>\
				</label>\
			</div>\
		',
		methods: {
			getValue: function() {
				return this.values;
			}
		}
	} );

	Vue.component( 'dropdown', {
		props: ['value', 'options'],
		mixins: [Mixins],
		template: '\
			<div>\
				<select v-model="value" v-on:change="triggerChange">\
					<option v-for="(title, key) in options" v-bind:value="key">{{ title }}</option>\
				</select>\
			</div>\
		',
		methods: {
			getValue: function() {
				return this.value;
			}
		}
	} );

	Vue.component( 'radio-buttons', {
		props: ['value', 'options'],
		mixins: [Mixins],

		template: '\
			<div>\
				<label v-for="(title, key) in options">\
					<input type="radio" v-bind:value="key" v-bind:checked="value == key" v-on:change="changeValue" />\
					<span>{{ title }}</span>\
				</label>\
			</div>\
		',

		methods: {
			changeValue: function( e ) {
				this.value = e.target.value;
				console.log( this.value );
				this.triggerChange();
			},

			getValue: function() {
				return this.value;
			}
		}
	} );

	Vue.component( 'dimension', {
		props: ['value', 'choices'],
		mixins: [Mixins],
		template: '\
			<div>\
				<label v-for="(title, key) in choices">\
					<span>{{ title }}</span>\
					<input type="text" v-bind:value="value[key]" v-bind:data-key="key" v-on:change="changeValue">\
				</label>\
			</div>\
		',

		methods: {
			changeValue: function( context ) {
				this.value[ $( context.target ).attr( 'data-key' ) ] = context.target.value;
				this.triggerChange();
			}
		}
	} );

	Vue.component( 'typography', {
		props: ['value', 'fonts'],
		mixins: [Mixins],
		data: function() {
			return {
				fontVariants: []
			}
		},
		filters: {
			parseTitle: function( value ) {
				return decodeURIComponent( value.substring( 0, value.indexOf( '/' ) ) ).replace(/\+/g, ' ');
			}
		},
		template: '\
			<div> \
				<div class="typography-font">\
					<select ref="font" v-model="value.family">\
						<option v-for="font in fonts" v-bind:value="font">{{ font | parseTitle }}</option>\
					</select>\
				</div>\
				<div class="typography-style">\
					<select ref="fontVariants" v-model="value.style">\
						<option v-for="variant in fontVariants" v-bind:value="variant">{{ variant }}</option>\
					</select>\
				</div>\
				<div class="typography-color">\
					<color v-bind:value="value.color" v-on:change="changeColor"></color>\
				</div>\
				<div class="typography-group">\
					<div class="typography-transform">\
						<select ref="textStyle" v-model="value.textStyle">\
							<option value="none">None</option>\
							<option value="uppercase">Upper Case</option>\
							<option value="lowercase">Lower Case</option>\
							<option value="capitalize">Capitalize</option>\
						</select>\
						<label class="typography-label">Text Style</label>\
					</div>\
					<div class="typography-size">\
						<input type="text" v-model="value.size" v-on:change="triggerChange" />\
						<label class="typography-label">Size</label>\
					</div>\
					<div class="typography-line-height">\
						<input type="text" v-model="value.lineHeight" v-on:change="triggerChange" />\
						<label class="typography-label">Line Height</label>\
					</div>\
					<div class="typography-letter-spacing">\
						<input type="text" v-model="value.letterSpacing" v-on:change="triggerChange" />\
						<label class="typography-label">Letter Spacing</label>\
					</div>\
				</div>\
			</div>\
		',
		beforeMount: function() {
			if ( /\//.test( this.value.family ) ) {
				this.fontVariants = this.value.family.split( '/' )[1].split( ',' );
			}
		},
		mounted: function() {
			$( 'select', this.$el ).chosen( {
				width: '100%',
				disable_search_threshold: 10
			} );

			$( this.$refs.font ).on( 'change', this.updateVariants );
			$( this.$refs.textStyle ).on( 'change', this.setStyle );
			$( this.$refs.fontVariants )
				.on( 'change', this.setVariant )
				.trigger( 'chosen:updated' );
		},
		updated: function() {
			$( this.$refs.fontVariants ).trigger( 'chosen:updated' );
		},
		methods: {
			updateVariants: function( e ) {
				this.value.family = $( e.target ).val();
				this.fontVariants = this.value.family.split( '/' )[1].split( ',' );
				this.value.style  = this.fontVariants.indexOf( this.value.style ) == -1 ? 'regular' : this.value.style;
				
				this.triggerChange();
			},

			setVariant: function ( e ) {
				this.value.style = $( e.target ).val();
				this.triggerChange();
			},

			setStyle: function( e ) {
				this.value.textStyle = $( e.target ).val();
				this.triggerChange();
			},

			changeColor: function( context ) {
				this.value.color = context.value;
				this.triggerChange();
			}
		}
	} );

	/**
	 * The background settings component
	 * @since  1.0.0
	 */
	Vue.component( 'background', {
		props: ['value'],
		mixins: [Mixins],

		template: '\
			<div class="options-control-wrap">\
				<div class="background-image">\
					<image-upload v-bind:value="value.image" v-on:change="triggerChange"></image-upload>\
				</div>\
				<div class="background-color">\
					<color v-bind:value="value.color" v-on:change="changeColor"></color>\
				</div>\
				<div class="background-group">\
					<div class="background-repeat">\
						<label>Repeat</label>\
						<select v-on:change="triggerChange" v-model="value.repeat">\
							<option value="no-repeat">No Repeat</option>\
							<option value="repeat-x">Repeat X</option>\
							<option value="repeat-y">Repeat Y</option>\
							<option value="repeat">Repeat Both</option>\
						</select>\
					</div>\
					<div class="background-position">\
						<label>Position</label>\
						<select v-on:change="triggerChange" v-model="value.position">\
							<option value="top left">Top Left</option>\
							<option value="top center">Top Center</option>\
							<option value="top right">Top Right</option>\
							<option value="center left">Middle Left</option>\
							<option value="center center">Middle Center</option>\
							<option value="center right">Middle Right</option>\
							<option value="bottom left">Bottom Left</option>\
							<option value="bottom center">Bottom Center</option>\
							<option value="bottom right">Bottom Right</option>\
							<option value="custom">Custom</option>\
						</select>\
					</div>\
				</div>\
				<div v-if="value.position == \'custom\'" class="background-position-custom background-group">\
					<label>Custom Position</label>\
					<div>\
						<input type="text" v-on:change="triggerChange" v-model="value.x" />\
						<label>Position X</label>\
					</div>\
					<div>\
						<input type="text" v-on:change="triggerChange" v-model="value.y" />\
						<label>Position Y</label>\
					</div>\
				</div>\
				<div class="background-group">\
					<div class="background-attachment">\
						<label>Attachment</label>\
						<select v-on:change="triggerChange" v-model="value.attachment">\
							<option value="scroll">Scroll</option>\
							<option value="fixed">Fixed</option>\
						</select>\
					</div>\
					<div class="background-size">\
						<label>Size</label>\
						<select v-on:change="triggerChange" v-model="value.size">\
							<option value="auto">Auto</option>\
							<option value="cover">Cover</option>\
							<option value="contain">Contain</option>\
							<option value="fit-width">100% Width</option>\
							<option value="fit-height">100% Height</option>\
							<option value="stretch">Stretch</option>\
							<option value="custom">Custom</option>\
						</select>\
					</div>\
				</div>\
				<div v-if="value.size == \'custom\'" class="background-size-custom background-group">\
					<label>Custom Size</label>\
					<div>\
						<input type="text" v-on:change="triggerChange" v-model="value.width" />\
						<label>Width</label>\
					</div>\
					<div>\
						<input type="text" v-on:change="triggerChange" v-model="value.height" />\
						<label>Height</label>\
					</div>\
				</div>\
			</div>\
		',
		methods: {
			changeColor: function( context ) {
				this.value.color = context.value;
				this.triggerChange();
			}
		}
	} );

	Vue.component( 'border-item', {
		props: ['value', 'title'],
		mixins: [Mixins],
		template: '\
			<div class="border-field-wrap">\
				<label>{{ title }}</label>\
				<div class="border-field">\
					<div class="border-size">\
						<input v-model="value.size" type="text" v-on:change="triggerChange" />\
					</div>\
					<div class="border-style">\
						<select v-model="value.style" v-on:change="triggerChange">\
							<option value="none">None</option>\
							<option value="dotted">Dotted</option>\
							<option value="dashed">Dashed</option>\
							<option value="solid">Solid</option>\
							<option value="double">Double</option>\
							<option value="groove">Groove</option>\
							<option value="ridge">Ridge</option>\
							<option value="inset">Inset</option>\
							<option value="outset">Outset</option>\
							<option value="hidden">Hidden</option>\
						</select>\
					</div>\
					<div class="border-color">\
						<color v-bind:value="value.color" v-on:change="changeColor"></color>\
					</div>\
				</div>\
			</div>\
		',
		methods: {
			changeColor: function( context ) {
				this.value.color = context.value;
				this.triggerChange();
			},

			getValue: function() {
				return $.extend( {}, this.value );
			}
		}
	} );

	Vue.component( 'border', {
		props: ['value', 'options'],
		mixins: [Mixins],
		template: '\
			<div v-bind:class="{ simplify: isSimplify }">\
				<div class="border-simplify">\
					<label>\
						<span>Show Simplify Controls</span>\
						<input type="checkbox" v-bind:checked="isSimplify" v-on:change="setSimplify" />\
					</label>\
				</div>\
				<border-item v-show="isSimplify" v-bind:value="value.all" title="All" v-on:change="triggerChange"></border-item>\
				<border-item v-for="(title, key) in options" \
							 v-bind:value="value[key]" \
							 v-show="!isSimplify" \
							 v-bind:title="title" \
							 v-bind:data-key="key" \
							 v-on:change="setOptions">\
				</border-item>\
			</div>\
		',

		data: function() {
			return {
				isSimplify: this.value.simplify === true
			}	
		},

		methods: {
			setSimplify: function( e ) {
				this.value.simplify = this.isSimplify = e.target.checked;
				this.triggerChange();
			},

			setOptions: function ( context ) {
				this.value[ $( context.$el ).attr( 'data-key' ) ] = context.getValue();
				this.triggerChange();
			},

			getValue: function() {
				var value = {};
				$.map( this.value, function( item, index ) {
					value[index] = typeof( item ) == 'object'
						? $.extend( {}, item )
						: item;
				} );

				return value;
			}
		}
	} );


	Vue.component( 'column-layout-item', {
		props: ['value'],
		mixins: [Mixins],
		computed: {
			sizes: function() {
				return this.value;
			}
		},
		template: '\
			<div class="columns-layout">\
				<div v-for="size in sizes" :data-width="size"></div>\
			</div>\
		',
		updated() {
			this.setupResizable();
		},
		mounted() {
			this.setupResizable();
		},
		methods: {
			setupResizable: function() {
				var self = this;
				var root = this.$el;
				var initResize, doResize, getMaxWidth, commitChanges, parentWidth, stepWidth, increase, decrease, resizeHolder;

				initResize = function(event, ui) {
					resizeHolder = $(event.srcElement);
					parentWidth = ui.element.parent().width();
					stepWidth = Math.floor(parentWidth / 12);
				};

				getMaxWidth = function(element) {
					var prevWidth = 0;
					
					element.prevAll().each(function() {
						prevWidth += parseInt($(this).attr('data-width'));
					});

					return (12 - prevWidth) - (element.nextAll().length * 2);
				};

				decrease = function(element, width, invert) {
					var currentWidth = parseInt(element.attr('data-width')),
						isInvert = invert || false,
						newWidth = currentWidth - width;

					if (newWidth < 2) {
						decrease(isInvert ? element.prev() : element.next(), width, isInvert);
					}
					else {
						element.attr('data-width', newWidth);
						element.find('span').text(newWidth);
					}
				};

				increase = function(element, width) {
					var currentWidth = parseInt(element.attr('data-width')),
						newWidth = currentWidth + width;

					element.attr('data-width', newWidth);
					element.find('span').text(newWidth);
				};

				doResize = function(event, ui) {
					var newWidth = Math.round(ui.size.width / stepWidth),
						currentWidth = parseInt(ui.element.attr('data-width')),
						maxWidth = getMaxWidth(ui.element);

					if (newWidth < 2) newWidth = 2;
					if (newWidth > maxWidth) newWidth = maxWidth;

					if (newWidth > currentWidth)
						decrease(ui.element.next(), newWidth - currentWidth);
					else
						increase(ui.element.next(), currentWidth - newWidth);

					ui.element.attr('data-width', newWidth);
					ui.element.removeAttr('style');
					ui.element.find('span').text(newWidth);
				};

				commitChanges = function() {
					var columns = [];

					$('div[data-width]', root).each(function() {
						columns.push( parseInt( $(this).attr('data-width') ) );
					});

					self.value = columns;
					self.triggerChange();
				};

				$('div[data-width]', root).resizable({
					handles: 'e',
					start: initResize,
					resize: doResize,
					stop: commitChanges
				});
			},
			getValue: function() {
				return JSON.parse( JSON.stringify( this.value ) );
			}
		}
	} );


	Vue.component( 'column-layout', {
		props: ['value'],
		mixins: [Mixins],
		template: '\
			<div>\
				<div class="columns-count options-control-radio-buttons">\
					<div class="options-control-inputs">\
						<radio-buttons v-bind:value="columns" v-bind:options="ranges" v-on:change="setColumns"></radio-buttons>\
					</div>\
				</div>\
				<column-layout-item v-bind:value="layout" v-on:change="setLayout"></column-layout-item>\
			</div>\
		',
		data: function() {
			return {
				columns: this.value.columns,
				ranges: { 1: 1, 2: 2, 3: 3, 4:4 }
			}
		},
		computed: {
			columns: function() {
				return this.value.columns;
			},
			layout: function() {
				return this.value.layout[this.columns];
			}
		},
		methods: {
			setColumns: function(columns) {
				this.value.columns = parseInt(columns.value);
				this.triggerChange();
			},
			setLayout: function(context) {
				this.value.layout[this.columns] = context.getValue();
				this.triggerChange();
			}
		}
	} );

	Vue.component( 'icon-item', {
		props: ['value', 'icons'],
		mixins: [Mixins],
		template: '\
			<div class="sortable-content">\
				<div class="sortable-item-icon">\
					<input type="text" class="item-icon" :value="value.icon" />\
				</div>\
				<div class="sortable-item-title">\
					<input type="text" :value="value.title" @input="changeTitle" />\
				</div>\
				<div class="sortable-item-url">\
					<input type="text" :value="value.url" @input="changeUrl" />\
				</div>\
			</div>\
		',
		mounted() {
			this.$nextTick((function() {
				$('.item-icon', this.$el).fontIconPicker({
					source: this.icons,
					theme: 'fip-inverted'
				}).on('change', (function(e) {
					this.value.icon = $(e.target).val();
					this.triggerChange();
				}).bind(this));
			}).bind(this));
		},
		methods: {
			changeTitle: function(e) {
				this.value.title = $(e.target).val();
				this.triggerChange();
			},
			changeUrl: function(e) {
				this.value.url = $(e.target).val();
				this.triggerChangeDebounced();
			},
			triggerChangeDebounced: function() {
				this.debounce(this.triggerChange, 100)();
			}
		}
	} );

	Vue.component( 'icons', {
		props: ['value', 'icons'],
		mixins: [Mixins],
		data: function() {
			return {
				addedIcons: []
			}
		},
		template: '\
			<div>\
				<ul class="social-icons-sortable">\
					<li v-for="(item, index) in addedIcons" :data-index="index">\
						<div class="handle"></div>\
						<icon-item :value="item" :icons="icons" :data-index="index" @change="updateIcon"></icon-item>\
						<button type="button" class="button" @click="removeIcon(item)">\
							<i class="fa fa-times"></i>\
						</button>\
					</li>\
				</ul>\
				<button type="button" class="add-new-icon" @click="addIcon">Add Icon</button>\
			</div>\
		',

		created() {
			this.$set(this, 'addedIcons', this.value);
		},

		mounted() {
			$('.social-icons-sortable', this.$el).sortable({
				items: '> li',
				handle: '.handle',
				axis: 'y',
				update: this.updatePosition.bind(this)
			});
		},

		methods: {
			addIcon: function() {
				this.addedIcons.push({ icon: 'fa fa-cog', title: '', url: '#' });
				this.triggerChange();
			},
			removeIcon: function(icon) {
				this.addedIcons.splice(this.addedIcons.indexOf(icon), 1);
				this.triggerChange();
			},
			updateIcon: function(context) {
				var index = $(context.$el).attr('data-index');
				var value = context.getValue();

				this.$set(this.addedIcons, index, value);
				this.triggerChange();
			},
			updatePosition: function(e, ui) {
				var originalIndex = ui.item.data('index');
				var item = this.addedIcons[originalIndex];

				// Delete the old item
				this.addedIcons.splice(originalIndex, 1);
				this.addedIcons.splice(ui.item.index(), 0, item);

				this.triggerChange();
			},


			getValue: function() {
				return JSON.parse( JSON.stringify( this.addedIcons ) );
			}
		}
	} );



	$( function() {
		$( '.options-control' ).each( function() {
			var elm         = $( this );
			var elmId       = elm.data( 'option' );
			var link        = elm.data( 'customizeid' );
			var data        = elm.attr( 'data-value' );
			var dataDefault = elm.attr( 'data-default' );
			var choices     = elm.data( 'choices' );

			try {
				data = JSON.parse( data );
				
				if ( $.isPlainObject( data ) ) {
					dataDefault = JSON.parse( dataDefault );
					data = $.extend( {}, dataDefault, data );
				}
			}
			catch( e ) {}

			new Vue( {
				el: $( '.options-control-inputs', elm ).get( 0 ),
				data: function() {
					return {
						data: data,
						choices: choices
					}
				},
				methods: {
					triggerChange: function( context ) {
						if ( link ) {
							wp.customize.instance( link ).set(
								context.getValue()
							);
						}
					}
				}
			} );
		} );
	} )
} )( jQuery );