• File: widget-builder-admin.js
  • Full Path: /home/bravrvjk/hpgt.org/wp-content/plugins/royal-elementor-addons/modules/widget-builder/assets/js/widget-builder-admin.js
  • Date Modified: 04/10/2026 2:58 PM
  • File size: 11.62 KB
  • MIME-type: text/plain
  • Charset: utf-8
(function($) {
	'use strict';

	var WprWidgetBuilder = {
		controlCounter: 0,
		typesWithOptions: ['select', 'select2', 'choose'],

		init: function() {
			this.bindEvents();
			this.loadWidget();
			this.initSortable();
		},

		bindEvents: function() {
			var self = this;

			// Tab switching
			$(document).on('click', '.wpr-wb-tab', function() {
				var tab = $(this).data('tab');
				$('.wpr-wb-tab').removeClass('active');
				$(this).addClass('active');
				$('.wpr-wb-tab-panel').removeClass('active');
				$('.wpr-wb-tab-panel[data-tab="' + tab + '"]').addClass('active');
			});

			// Add control
			$(document).on('click', '.wpr-wb-add-control', function() {
				var tab = $(this).data('tab');
				self.addControl(tab);
				self.updateTabCounts();
			});

			// Remove control
			$(document).on('click', '.wpr-wb-control-remove', function(e) {
				e.stopPropagation();
				if (confirm('Remove this control?')) {
					$(this).closest('.wpr-wb-control-item').slideUp(200, function() {
						$(this).remove();
						self.updateTabCounts();
					});
				}
			});

			// Duplicate control
			$(document).on('click', '.wpr-wb-control-duplicate', function(e) {
				e.stopPropagation();
				var $item = $(this).closest('.wpr-wb-control-item');
				var tab = $item.closest('.wpr-wb-controls-list').data('tab');
				var data = self.getControlItemData($item);
				data.key = data.key + '_copy';
				data.label = data.label + ' (Copy)';
				self.addControl(tab, data);
				self.updateTabCounts();
			});

			// Toggle control
			$(document).on('click', '.wpr-wb-control-header', function(e) {
				if ($(e.target).closest('.wpr-wb-control-actions').length) return;
				$(this).closest('.wpr-wb-control-item').toggleClass('collapsed');
			});

			// Update control title and auto-generate key
			$(document).on('input', '.wpr-wb-ctrl-label', function() {
				var label = $(this).val() || 'New Control';
				var $item = $(this).closest('.wpr-wb-control-item');
				$item.find('.wpr-wb-control-title').text(label);

				// Auto-generate key if key field is empty or was auto-generated
				var $keyField = $item.find('.wpr-wb-ctrl-key');
				var currentKey = $keyField.val();
				if (!currentKey || $keyField.data('auto')) {
					var autoKey = label.toLowerCase()
						.replace(/[^a-z0-9]+/g, '_')
						.replace(/^_|_$/g, '')
						.substring(0, 40);
					$keyField.val(autoKey).data('auto', true);
				}
			});

			// Mark key as manually edited
			$(document).on('input', '.wpr-wb-ctrl-key', function() {
				$(this).data('auto', false);
			});

			// Show/hide options field based on type
			$(document).on('change', '.wpr-wb-ctrl-type', function() {
				var type = $(this).val();
				var wrap = $(this).closest('.wpr-wb-control-body').find('.wpr-wb-ctrl-options-wrap');
				if (self.typesWithOptions.indexOf(type) !== -1) {
					wrap.slideDown(150);
				} else {
					wrap.slideUp(150);
				}
			});

			// Save widget
			$('#wpr-wb-save').on('click', function() {
				self.saveWidget();
			});

			// Ctrl+S to save
			$(document).on('keydown', function(e) {
				if ((e.ctrlKey || e.metaKey) && e.key === 's') {
					e.preventDefault();
					self.saveWidget();
				}
			});

			// Collapse/Expand all controls
			$(document).on('click', '.wpr-wb-collapse-all', function() {
				var tab = $(this).closest('.wpr-wb-tab-panel').data('tab');
				var $items = $('.wpr-wb-controls-list[data-tab="' + tab + '"] .wpr-wb-control-item');
				var allCollapsed = $items.filter('.collapsed').length === $items.length;
				if (allCollapsed) {
					$items.removeClass('collapsed');
				} else {
					$items.addClass('collapsed');
				}
			});

			// Insert tag helper
			$(document).on('click', '.wpr-wb-insert-tag', function() {
				var tag = $(this).data('tag');
				var $textarea = $('#wpr-wb-markup');
				var pos = $textarea[0].selectionStart;
				var text = $textarea.val();
				$textarea.val(text.substring(0, pos) + tag + text.substring(pos));
				$textarea[0].selectionStart = $textarea[0].selectionEnd = pos + tag.length;
				$textarea.focus();
			});
		},

		initSortable: function() {
			if (!$.fn.sortable) return;

			$('.wpr-wb-controls-list').sortable({
				handle: '.wpr-wb-control-header',
				placeholder: 'wpr-wb-sortable-placeholder',
				opacity: 0.7,
				tolerance: 'pointer',
				cursor: 'move'
			});
		},

		getControlItemData: function($item) {
			var data = {
				key: $item.find('.wpr-wb-ctrl-key').val().trim(),
				label: $item.find('.wpr-wb-ctrl-label').val().trim(),
				type: $item.find('.wpr-wb-ctrl-type').val(),
				default: $item.find('.wpr-wb-ctrl-default').val(),
				section: $item.find('.wpr-wb-ctrl-section').val().trim() || 'general',
				section_label: $item.find('.wpr-wb-ctrl-section-label').val().trim() || 'General'
			};

			var optionsText = $item.find('.wpr-wb-ctrl-options').val().trim();
			if (optionsText) {
				data.options = {};
				optionsText.split('\n').forEach(function(line) {
					line = line.trim();
					if (line) {
						var parts = line.split('|');
						data.options[parts[0].trim()] = parts.length > 1 ? parts[1].trim() : parts[0].trim();
					}
				});
			}

			return data;
		},

		addControl: function(tab, data) {
			var template = $('#tmpl-wpr-wb-control').html();
			var $control = $(template);
			var key = 'control_' + (++this.controlCounter);

			$control.attr('data-key', key);

			if (data) {
				$control.find('.wpr-wb-ctrl-key').val(data.key || '');
				$control.find('.wpr-wb-ctrl-label').val(data.label || '');
				$control.find('.wpr-wb-ctrl-type').val(data.type || 'text');
				$control.find('.wpr-wb-ctrl-default').val(data.default || '');
				$control.find('.wpr-wb-ctrl-section').val(data.section || 'general');
				$control.find('.wpr-wb-ctrl-section-label').val(data.section_label || '');
				$control.find('.wpr-wb-control-title').text(data.label || 'New Control');

				// Type badge
				$control.find('.wpr-wb-control-type-badge').text(data.type || 'text');

				if (data.options) {
					var lines = [];
					for (var optKey in data.options) {
						if (data.options.hasOwnProperty(optKey)) {
							lines.push(optKey + '|' + data.options[optKey]);
						}
					}
					$control.find('.wpr-wb-ctrl-options').val(lines.join('\n'));
				}

				if (this.typesWithOptions.indexOf(data.type) !== -1) {
					$control.find('.wpr-wb-ctrl-options-wrap').show();
				}

				$control.addClass('collapsed');
			} else {
				// New control — focus the label field
				setTimeout(function() {
					$control.find('.wpr-wb-ctrl-label').focus();
				}, 50);
			}

			$('.wpr-wb-controls-list[data-tab="' + tab + '"]').append($control);

			// Update type badge on change
			$control.find('.wpr-wb-ctrl-type').on('change', function() {
				$control.find('.wpr-wb-control-type-badge').text($(this).val());
			});
		},

		updateTabCounts: function() {
			['content', 'style', 'advanced'].forEach(function(tab) {
				var count = $('.wpr-wb-controls-list[data-tab="' + tab + '"] .wpr-wb-control-item').length;
				var $badge = $('.wpr-wb-tab[data-tab="' + tab + '"] .wpr-wb-tab-count');
				if (count > 0) {
					if (!$badge.length) {
						$('.wpr-wb-tab[data-tab="' + tab + '"]').append(' <span class="wpr-wb-tab-count">' + count + '</span>');
					} else {
						$badge.text(count);
					}
				} else {
					$badge.remove();
				}
			});
		},

		getControlsData: function(tab) {
			var self = this;
			var controls = [];
			$('.wpr-wb-controls-list[data-tab="' + tab + '"] .wpr-wb-control-item').each(function() {
				var data = self.getControlItemData($(this));
				if (data.key) {
					controls.push(data);
				}
			});
			return controls;
		},

		collectData: function() {
			var cssIncludes = $('#wpr-wb-css-includes').val().trim();
			var jsIncludes = $('#wpr-wb-js-includes').val().trim();

			return {
				title: $('#wpr-wb-title').val().trim(),
				icon: $('#wpr-wb-icon').val().trim() || 'eicon-cog',
				categories: [$('#wpr-wb-category').val()],
				markup: $('#wpr-wb-markup').val(),
				css: $('#wpr-wb-css').val(),
				js: $('#wpr-wb-js').val(),
				css_includes: cssIncludes ? cssIncludes.split('\n').map(function(s) { return s.trim(); }).filter(Boolean) : [],
				js_includes: jsIncludes ? jsIncludes.split('\n').map(function(s) { return s.trim(); }).filter(Boolean) : [],
				tabs: {
					content: this.getControlsData('content'),
					style: this.getControlsData('style'),
					advanced: this.getControlsData('advanced')
				}
			};
		},

		populateData: function(data) {
			$('#wpr-wb-title').val(data.title || '');
			$('#wpr-wb-icon').val(data.icon || 'eicon-cog');

			if (data.categories && data.categories.length) {
				$('#wpr-wb-category').val(data.categories[0]);
			}

			$('#wpr-wb-markup').val(data.markup || '');
			$('#wpr-wb-css').val(data.css || '');
			$('#wpr-wb-js').val(data.js || '');

			if (data.css_includes) {
				var cssArr = Array.isArray(data.css_includes) ? data.css_includes : [];
				$('#wpr-wb-css-includes').val(cssArr.join('\n'));
			}
			if (data.js_includes) {
				var jsArr = Array.isArray(data.js_includes) ? data.js_includes : [];
				$('#wpr-wb-js-includes').val(jsArr.join('\n'));
			}

			// Populate controls
			var self = this;
			if (data.tabs) {
				['content', 'style', 'advanced'].forEach(function(tab) {
					if (data.tabs[tab] && Array.isArray(data.tabs[tab])) {
						data.tabs[tab].forEach(function(control) {
							self.addControl(tab, control);
						});
					}
				});
			}

			this.updateTabCounts();

			// Sync post title
			var $postTitle = $('#title');
			if ($postTitle.length && data.title) {
				$postTitle.val(data.title);
			}
		},

		setStatus: function(message, type) {
			var $status = $('#wpr-wb-status');
			$status.text(message).removeClass('error saving').addClass(type || '');

			if (type !== 'error') {
				setTimeout(function() {
					$status.text('');
				}, 3000);
			}
		},

		saveWidget: function() {
			var self = this;
			var data = this.collectData();
			var postId = wprWidgetBuilder.postId;

			if (!data.title) {
				this.setStatus('Please enter a widget title.', 'error');
				$('#wpr-wb-title').focus();
				return;
			}

			this.setStatus('Saving...', 'saving');
			$('#wpr-wb-save').prop('disabled', true).text('Saving...');

			var url = wprWidgetBuilder.apiBase + 'save';
			if (postId) {
				url += '/' + postId;
			}

			$.ajax({
				url: url,
				method: 'POST',
				contentType: 'application/json',
				data: JSON.stringify(data),
				beforeSend: function(xhr) {
					xhr.setRequestHeader('X-WP-Nonce', wprWidgetBuilder.nonce);
				},
				success: function(response) {
					if (response.success) {
						self.setStatus('Widget saved!', '');

						// Update post ID for new widgets
						if (response.post_id && !wprWidgetBuilder.postId) {
							wprWidgetBuilder.postId = response.post_id;
							window.location.href = 'post.php?post=' + response.post_id + '&action=edit&saved=1';
						}

						$('#title').val(data.title);
					} else {
						self.setStatus(response.message || 'Save failed.', 'error');
					}
				},
				error: function(xhr) {
					var msg = 'Save failed.';
					if (xhr.responseJSON && xhr.responseJSON.message) {
						msg = xhr.responseJSON.message;
					}
					self.setStatus(msg, 'error');
				},
				complete: function() {
					$('#wpr-wb-save').prop('disabled', false).text('Save Widget');
				}
			});
		},

		loadWidget: function() {
			var self = this;
			var postId = wprWidgetBuilder.postId;

			if (!postId) return;

			$.ajax({
				url: wprWidgetBuilder.apiBase + 'load/' + postId,
				method: 'GET',
				beforeSend: function(xhr) {
					xhr.setRequestHeader('X-WP-Nonce', wprWidgetBuilder.nonce);
				},
				success: function(response) {
					if (response.success && response.data) {
						self.populateData(response.data);
					}
				}
			});
		}
	};

	$(document).ready(function() {
		if ($('#wpr-widget-builder-app').length) {
			WprWidgetBuilder.init();
		}
	});

})(jQuery);