PluginProbe
Solace Extra / trunk
Solace Extra vtrunk
1.7.1 1.7.0 1.6.2 1.6.1 1.6.0 1.5.3 trunk 1.0.8 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.7 1.1.8 1.1.9 1.2.1 1.2.2 1.3.0 1.3.1 1.3.2 1.3.3 1.5.0 1.5.1 All 26 releases
solace-extra / admin / js / sitebuilder.js

sitebuilder.js in Solace Extra trunk, at admin/js/sitebuilder.js

1,182 lines 46.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function ($) {
2 'use strict';
3
4 var solaceConditions = {
5 includeLabel: 'Include',
6 excludeLabel: 'Exclude'
7 };
8
9 // $('.status-switch').on('change', function() {
10
11 // const parts = ['singleproduct', 'purchase-summary', 'blogsinglepost', 'blogarchive', '404', 'shopproduct'];
12
13 // parts.forEach(part => {
14 // $('.status-switch[data-part="' + part + '"]')
15 // .not(this)
16 // .prop('checked', false);
17 // });
18
19 // var postId = $(this).data('post-id');
20 // var part = $(this).data('part').toString();
21 // var status = $(this).is(':checked') ? 1 : 0;
22
23 // $.ajax({
24 // url: solaceSitebuilderParams.ajaxurl,
25 // type: 'POST',
26 // data: {
27 // // action: 'solace_update_header_status',
28 // action: 'solace_update_sitebuilder_status',
29 // post_id: postId,
30 // status: status,
31 // part: part,
32 // nonce: solaceSitebuilderParams.nonce,
33 // security: solaceSitebuilderParams.nonce,
34 // },
35 // success: function(response) {
36 // if(response.success) {
37 // location.reload(); // Refresh the page after successful update
38 // } else {
39 // alert('Failed to update status.');
40 // }
41 // }
42 // });
43 // });
44
45 $('.status-switch').on('change', function() {
46 var postId = $(this).data('post-id');
47 var part = $(this).data('part').toString();
48 var status = $(this).is(':checked') ? 1 : 0;
49
50 if (part !== 'header' && part !== 'footer') {
51
52 const parts = ['singleproduct', 'purchase-summary', 'blogsinglepost', 'blogarchive', '404', 'shopproduct'];
53
54 parts.forEach(p => {
55 if (p === part) {
56 $('.status-switch[data-part="' + p + '"]')
57 .not(this)
58 .prop('checked', false);
59 }
60 });
61 } else {
62 }
63
64 $.ajax({
65 url: solaceSitebuilderParams.ajaxurl,
66 type: 'POST',
67 data: {
68 action: 'solace_update_sitebuilder_status',
69 post_id: postId,
70 status: status,
71 part: part,
72 nonce: solaceSitebuilderParams.nonce,
73 security: solaceSitebuilderParams.nonce,
74 },
75 success: function(response) {
76 console.log('Respon Server:', response);
77 if(response.success) {
78 location.reload();
79 } else {
80 alert('Failed to update status: ' + response.data);
81 }
82 },
83 error: function(xhr, status, error) {
84 alert('An error occurred during the AJAX request.');
85 }
86 });
87 });
88
89 jQuery(document).ready(function($) {
90 $('.solace-extra-add-to-cart').on('submit', 'form.cart', function(e) {
91 e.preventDefault();
92
93 var $form = $(this);
94 var $button = $form.find('.ajax_add_to_cart');
95 var product_id = $button.data('product_id');
96 var quantity = $form.find('.quantity').val();
97 var $viewCartButton = $form.siblings('.view_cart_button');
98
99 $.ajax({
100 type: 'POST',
101 url: solaceSitebuilderParams.ajax_url,
102 data: {
103 action: 'woocommerce_ajax_add_to_cart',
104 product_id: product_id,
105 quantity: quantity,
106 nonce: $form.find('input[name="nonce"]').val()
107 },
108 beforeSend: function() {
109 $button.addClass('loading').text('Adding...');
110 },
111 success: function(response) {
112 $button.removeClass('loading');
113
114 if (response.success) {
115 $button.hide();
116 $viewCartButton.show();
117 } else {
118 alert(response.message || 'Failed to add product to cart.');
119 }
120 },
121 error: function() {
122 alert('An error occurred. Please try again.');
123 }
124 });
125 });
126
127 });
128
129
130
131
132
133
134
135
136 $('.all-status-switch').click(function(event) {
137 // BULK CHANGE ALL EVERY PART TO DISABLE OR ENABLE
138 var part = $(this).data('part-global').toString();
139 var vpart = $(this).data('part-global').toString().toUpperCase();
140
141
142 if ($(this).hasClass('disabled-checkbox')) {
143 event.preventDefault();
144 alert('There is no ' + vpart + ' part that can be activated yet.');
145 return false;
146
147 }
148 var status = $(this).is(':checked') ? 1 : 0;
149 $.ajax({
150 url: solaceSitebuilderParams.ajaxurl,
151 type: 'POST',
152 data: {
153 action: 'solace_update_sitebuilder_all_status',
154 status: status,
155 part: part,
156 nonce: solaceSitebuilderParams.nonce,
157 security: solaceSitebuilderParams.nonce,
158 },
159 success: function(response) {
160 if(response.success) {
161 location.reload(); // Refresh the page after successful update
162 } else {
163 alert('Failed to update status.');
164 }
165 }
166 });
167 });
168
169 function generateOptionsHtml(selectedValue) {
170 // Debugging: Check if solaceSitebuilderParams is defined
171 console.log('solaceSitebuilderParams:', solaceSitebuilderParams);
172
173 if (typeof solaceSitebuilderParams !== 'undefined') {
174 console.log('WooCommerce active:', solaceSitebuilderParams.woocommerce);
175
176 var options = `
177 <optgroup label="Basic">
178 <option value="basic-global" ${selectedValue === 'basic-global' ? 'selected' : ''}>Entire Website</option>
179 <option value="basic-singulars" ${selectedValue === 'basic-singulars' ? 'selected' : ''}>All Singulars</option>
180 <option value="basic-archives" ${selectedValue === 'basic-archives' ? 'selected' : ''}>All Archives</option>
181 </optgroup>
182 <optgroup label="Special Pages">
183 <option value="special-404" ${selectedValue === 'special-404' ? 'selected' : ''}>404 Page</option>
184 <option value="special-search" ${selectedValue === 'special-search' ? 'selected' : ''}>Search Page</option>
185 <option value="special-blog" ${selectedValue === 'special-blog' ? 'selected' : ''}>Blog / Posts Page</option>
186 <option value="special-front" ${selectedValue === 'special-front' ? 'selected' : ''}>Front Page</option>
187 <option value="special-date" ${selectedValue === 'special-date' ? 'selected' : ''}>Date Archive</option>
188 <option value="special-author" ${selectedValue === 'special-author' ? 'selected' : ''}>Author Archive</option>
189 </optgroup>
190 <optgroup label="Posts">
191 <option value="post|all" ${selectedValue === 'post|all' ? 'selected' : ''}>All Posts</option>
192 <option value="post|all|taxarchive|category" ${selectedValue === 'post|all|taxarchive|category' ? 'selected' : ''}>All Categories Archive</option>
193 <option value="post|all|taxarchive|post_tag" ${selectedValue === 'post|all|taxarchive|post_tag' ? 'selected' : ''}>All Tags Archive</option>
194 </optgroup>
195 <optgroup label="Pages">
196 <option value="page|all" ${selectedValue === 'page|all' ? 'selected' : ''}>All Pages</option>
197 </optgroup>
198
199 `;
200
201 // Check if WooCommerce is active (passed from PHP)
202 if (solaceSitebuilderParams.woocommerce == true || solaceSitebuilderParams.woocommerce == 1) {
203 console.log('Adding WooCommerce options...');
204 options += `
205 <optgroup label="Products">
206 <option value="product|all" ${selectedValue === 'product|all' ? 'selected' : ''}>All Products</option>
207 <option value="product|all|taxarchive|product_cat" ${selectedValue === 'product|all|taxarchive|product_cat' ? 'selected' : ''}>All Product Categories Archive</option>
208 <option value="product|all|taxarchive|product_tag" ${selectedValue === 'product|all|taxarchive|product_tag' ? 'selected' : ''}>All Product Tags Archive</option>
209 </optgroup>
210 `;
211 } else {
212 console.log('WooCommerce options not added.');
213 }
214 return options;
215 } else {
216 console.log('solaceSitebuilderParams is undefined.');
217 }
218 }
219
220 function generateConditionPopup(postId, conditionsData) {
221
222 var conditionsContainer = $('<div class="conditions-container rico1" data-post-id="' + postId + '" ></div>');
223 var assetsUrl = solaceSitebuilderParams.assetsUrl;
224
225 if (!conditionsData || conditionsData.length === 0) {
226 conditionsData = [{
227 type: 'include',
228 value: ''
229 }];
230 }
231
232 conditionsData.forEach(function(condition, index) {
233 var hideClass = index === 0 ? ' hide' : '';
234
235 var conditionItem = `
236 <div class="condition-item">
237 <span class="icon-container">
238 <img src="${assetsUrl}images/plus-include.svg" />
239 </span>
240 <select name="condition_${index + 1}_exclude_include" class="condition-exclude-include-select">
241 <option value="include" ${condition.type === 'include' ? 'selected' : ''}>Include</option>
242 <option value="exclude" ${condition.type === 'exclude' ? 'selected' : ''}>Exclude</option>
243 </select>
244 <select name="condition_${index + 1}_value" class="condition-select">
245 ${generateOptionsHtml(condition.value)}
246 </select>
247 <a href="#" class="delete-condition dashicons dashicons-trash${hideClass}" title="Delete Condition"></a>
248
249 </div>`;
250
251 conditionsContainer.append(conditionItem);
252 });
253
254 $('#edit-conditions-container').append(conditionsContainer);
255 }
256
257 $('.condition-part-select').change(function() {
258 var selectedValue = $(this).val();
259
260 if (selectedValue === '404') {
261 $('.solace-popup-content #all-new-conditions-container').hide();
262 $('.solace-popup-content .solace-popup-footer').hide();
263
264 $('.solace-popup-content .chooseparts').addClass('part404');
265 } else {
266 $('.solace-popup-content #all-new-conditions-container').show();
267 $('.solace-popup-content .solace-popup-footer').show();
268
269 $('.solace-popup-content .chooseparts').removeClass('404');
270 }
271 });
272
273 $('.edit-conditions-button').on('click', function(e) {
274 $('#edit-conditions-container').find('.conditions-container').remove();
275 e.preventDefault();
276 var postId = $(this).data('post-id');
277 $('.conditions-container').fadeIn(400);
278 $('.conditions-container[data-post-id="' + postId + '"]').show();
279
280 $('#edit-conditions-popup').fadeIn(400);
281 $('#edit-conditions-overlay').fadeIn(400);
282 var conditionsData = $(this).data('conditions');
283
284 if (typeof conditionsData === 'string') {
285 conditionsData = JSON.parse(conditionsData.replace(/&quot;/g, '"'));
286 }
287 generateConditionPopup(postId, conditionsData);
288
289 });
290
291 function getParameterByName(name, url) {
292 if (!url) url = window.location.href;
293 name = name.replace(/[\[\]]/g, '\\$&');
294 var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
295 results = regex.exec(url);
296 if (!results) return null;
297 if (!results[2]) return '';
298 return decodeURIComponent(results[2].replace(/\+/g, ' '));
299 }
300
301 function showPopup(popupSelector, overlaySelector) {
302 $(overlaySelector).fadeIn(400); // Fade in overlay
303 $(popupSelector).fadeIn(400); // Fade in popup
304 }
305
306 // Function to hide popup and overlay with fade out effect
307 function hidePopup(popupSelector, overlaySelector) {
308 $(popupSelector).fadeOut(400, function() { // Fade out popup
309 $(overlaySelector).fadeOut(400); // Fade out overlay after popup is hidden
310 });
311 }
312 var partValue = getParameterByName('part');
313
314 $('.button.addnew').attr('data-part', partValue);
315
316 // Event handler for 'Add New' button click
317 $('.addnew').on('click', function(e) {
318 e.preventDefault();
319
320 const part = String($(this).data('part')).trim();
321 // Allowed page types for creation
322 const allowedTypes = ['header', 'footer', 'singleproduct', 'shopproduct', 'purchase-summary', 'blogsinglepost', 'blogarchive', '404'];
323
324 // Validate if the provided type is allowed
325 if ( ! allowedTypes.includes(part) ) {
326 console.warn('Invalid type provided:', part);
327 return;
328 }
329
330 // Disable button to prevent multiple clicks during request
331 const $button = $(this);
332 $button.prop('disabled', true);
333
334 // If 'part' exists, initiate AJAX request to create a new page
335 if ( part && part !== 'header' && part !== 'footer' ) {
336 createAndRedirect(part, $button);
337 } else if ( part === 'header' || part === 'footer' ) {
338 showAddNewPopup(part);
339 $button.prop('disabled', false);
340 }
341 });
342
343 /**
344 * AJAX call to create a new custom post and redirect to Elementor editor.
345 * @param {string} part - The type of page to create.
346 * @param {object} $button - The jQuery button element to re-enable after completion.
347 */
348 function createAndRedirect(part, $button) {
349 $.ajax({
350 url: solaceSitebuilderParams.ajaxurl,
351 method: 'POST',
352 data: {
353 action: 'create_and_edit_page',
354 type: part,
355 nonce: solaceSitebuilderParams.nonce,
356 },
357 success: function(response) {
358 if (response.success) {
359 const postId = response.data.post_id;
360 let editUrl = solaceSitebuilderParams.edit_url
361 .replace('{post_id}', postId)
362 .concat('&post_type=solace-sitebuilder&action=elementor');
363
364 // Add conditional GET parameters based on part type
365 if (part === 'header' || part === 'footer' || part === '404') {
366 editUrl += '&solace-extra=1';
367 } else if (part === 'singleproduct') {
368 editUrl += '&solace-extra-single=1';
369 } else if (part === 'shopproduct' || part === 'purchase-summary') {
370 editUrl += '&solace-extra-woocommerce=1';
371 } else if (part === 'blogsinglepost') {
372 editUrl += '&solace-extra-single-post=1';
373 } else if (part === 'blogarchive') {
374 editUrl += '&solace-extra-archive=1';
375 }
376
377 // Append part parameter if not empty
378 if (part && part.trim() !== '') {
379 editUrl += '&part=' + encodeURIComponent(part);
380 }
381
382 // Redirect to the constructed URL
383 window.location.href = editUrl;
384 } else {
385 alert('Failed to create new page.');
386 }
387 },
388 error: function(xhr) {
389 console.error(xhr);
390 let errorMsg = 'Unknown Error, please try again.';
391
392 try {
393 const response = JSON.parse(xhr.responseText);
394 if (response?.data?.error) {
395 errorMsg = response.data.error;
396 }
397 } catch (e) {
398 // Ignore JSON parse errors
399 }
400
401 alert(errorMsg);
402 },
403 complete: function() {
404 // Always re-enable the button regardless of success/failure
405 $button.prop('disabled', false);
406 }
407 });
408 }
409
410 /**
411 * Displays the 'Add New' popup with default condition selectors.
412 * @param {string} part - The type of page to associate with the popup (may be empty).
413 */
414 function showAddNewPopup(part) {
415 $('#add-new-popup')
416 .attr('data-part', part)
417 .attr('data-popup-type', 'add-new');
418
419 $('#add-new-popup .new-conditions-container').html(`
420 <div class="condition-item">
421 <select name="condition_1_exclude_include" class="condition-exclude-include-select">
422 <option value="include">${solaceConditions.includeLabel}</option>
423 <option value="exclude">${solaceConditions.excludeLabel}</option>
424 </select>
425 <select name="condition_1_value" class="condition-select">
426 ${generateOptionsHtml()}
427 </select>
428 <a href="#" class="delete-condition dashicons dashicons-trash" title="Delete Condition"></a>
429 </div>
430 `);
431
432 $('#add-new-popup, #add-new-overlay').fadeIn(400);
433 }
434
435 $('.newpart').on('click', function(e) {
436 $('#all-add-new-popup').fadeIn(400);
437 $('#all-add-new-overlay').fadeIn(400);
438 });
439
440 // This 404 go for redirect to elementor
441 $('#save-404').on('click', function(e) {
442 // alert('save404');
443 e.preventDefault();
444 var part = $(this).data('part');
445 console.log('Add New Party:', part);
446
447 $('#add-404-popup').attr('data-part', part);
448 $('#add-404-popup').attr('data-popup-type', 'add-new');
449 // $('#add-new-popup .new-conditions-container').html(`
450 // <div class="condition-item">
451 // <select name="condition_1_exclude_include" class="condition-exclude-include-select">
452 // <option value="include">${solaceConditions.includeLabel}</option>
453 // <option value="exclude">${solaceConditions.excludeLabel}</option>
454 // </select>
455 // <select name="condition_1_value" class="condition-select">
456 // ${generateOptionsHtml()}
457 // </select>
458 // <a href="#" class="delete-condition dashicons dashicons-trash" title="Delete Condition"></a>
459 // </div>
460 // `);
461
462 $('#add-404-popup').fadeIn(400);
463 $('#add-404-popup-overlay').fadeIn(400);
464
465 });
466
467 // Attach a click event listener to elements with class 'delete-column' inside the specified selector
468 $('.solace-list-item .group.action .delete-column .delete').on('click', function(e) {
469 e.preventDefault();
470 const id = Number($(this).attr('data-id'));
471 const listItem = $(this).parent().parent().parent().parent();
472
473 Swal.fire({
474 title: solaceSitebuilderI18n.delete_confirm_title,
475 text: solaceSitebuilderI18n.delete_confirm_text,
476 icon: "warning",
477 showCancelButton: true,
478 showCloseButton: true,
479 confirmButtonText: solaceSitebuilderI18n.delete_confirm_button,
480 cancelButtonText: solaceSitebuilderI18n.delete_cancel_button,
481 reverseButtons: true,
482 customClass: {
483 confirmButton: 'swal2-confirm btn btn-danger',
484 cancelButton: 'swal2-cancel btn btn-secondary'
485 }
486 }).then((result) => {
487 if (result.isConfirmed) {
488 // Send an AJAX request to delete the item
489 $.ajax({
490 url: solaceSitebuilderParams.ajaxurl,
491 method: 'POST',
492 dataType: 'json',
493 data: {
494 action: 'delete_action',
495 id: id,
496 nonce: solaceSitebuilderParams.nonce
497 },
498 success: function(response) {
499 console.log('AJAX Response:', response);
500
501 if (response.success) {
502 // Animate the removal of the item
503 listItem.fadeOut(350, function() {
504 $(this).remove(); // Remove from DOM after fade out
505 });
506 } else {
507 alert(response.data?.error || solaceSitebuilderI18n.delete_failed_message);
508 $(this).css('cursor', 'pointer'); // Reset cursor if failed
509 }
510 },
511 error: function(jqXHR, textStatus, errorThrown) {
512 console.error('AJAX error:', textStatus, errorThrown);
513 alert(solaceSitebuilderI18n.delete_error_message);
514 $(this).css('cursor', 'pointer'); // Reset cursor on error
515 }
516 });
517 }
518 });
519 });
520
521 $('#save-new-conditions').on('click', function(e) {
522 e.preventDefault();
523 var assetsUrl = solaceSitebuilderParams.assetsUrl;
524
525 var $container = $('#new-conditions-container');
526 if ($container.length === 0) {
527 alert('No conditions container found.');
528 return;
529 }
530
531 var conditions = [];
532 var selectedValues = new Set();
533 var postId = 0;
534 var part = $('#add-new-popup').data('part');
535
536 var hasDuplicate = false;
537
538 $container.find('.condition-item').each(function(index, item) {
539 var $item = $(item);
540 var conditionType = $item.find('.condition-exclude-include-select').val();
541 var conditionValue = $item.find('.condition-select').val();
542
543 if (selectedValues.has(conditionValue)) {
544 hasDuplicate = true;
545 return false;
546 }
547
548 selectedValues.add(conditionValue);
549 conditions.push({
550 type: conditionType,
551 value: conditionValue
552 });
553 });
554
555 if (hasDuplicate) {
556 alert('Condition on same instance, please select other conditions');
557 return;
558 }
559
560 $('#save-new-conditions').addClass('active');
561 $('#save-new-conditions dotlottie-player').fadeIn(1000);
562
563 $(this).addClass('active-button').css({
564 'width': '300px',
565 'padding-right': '85px',
566 'transition': 'width .5s ease, padding-right .5s ease'
567 });
568
569 $.ajax({
570 url: solaceSitebuilderParams.ajaxurl,
571 method: 'POST',
572 dataType: 'json',
573 contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
574 data: {
575 action: 'save_conditions',
576 part: part,
577 conditions: conditions,
578 nonce: solaceSitebuilderParams.nonce,
579 security: solaceSitebuilderParams.nonce,
580 from: $('#add-new-popup').attr('data-popup-type')
581 },
582 success: function(response) {
583 console.log('AJAX Response #save-new-conditions:', response); // Debugging
584 if (response.success) {
585 postId = response.data.post_id;
586 console.log('postID sukses:' + postId);
587 saveEditConditions(postId, part, conditions);
588 } else {
589 alert('Failed to save conditions: ' + (response.data || 'Unknown error.'));
590 }
591 },
592 error: function(jqXHR, textStatus, errorThrown) {
593 console.error('AJAX error:', textStatus, errorThrown);
594 console.error('Response Text:', jqXHR.responseText);
595 alert('An error occurred while saving. Please try again.');
596 }
597 });
598
599 });
600
601 function saveEditConditions(postId, part, conditions) {
602 $.ajax({
603 url: solaceSitebuilderParams.ajaxurl,
604 method: 'POST',
605 data: {
606 action: 'save_edit_conditions',
607 post_id: postId,
608 conditions: conditions,
609 post_type: 'solace-sitebuilder',
610 nonce: solaceSitebuilderParams.nonce,
611 },
612 success: function(response) {
613 console.log('AJAX response saveEditConditions:', response);
614
615 if (response.success) {
616 var editUrl = solaceSitebuilderParams.edit_url.replace('{post_id}', postId).concat('&post_type=solace-sitebuilder&action=elementor&solace-extra=1&part=' + part);
617 window.location.href = editUrl;
618 } else {
619
620 alert('Failed to save conditions. Please try again.');
621 }
622 },
623 error: function(jqXHR, textStatus, errorThrown) {
624 alert('An error occurred while saving. Please try again.');
625 }
626 });
627 }
628
629 $('#save-conditions').on('click', function(e) {
630 e.preventDefault();
631
632 var $container = $('.conditions-container');
633 if ($container.length === 0) {
634 alert('No conditions container found.');
635 return;
636 }
637
638 var conditions = [];
639 var selectedValues = new Set();
640 var postId = $('.conditions-container').data('post-id');
641 var part = $('.addnew').data('part');
642
643 var hasDuplicate = false;
644
645 $container.find('.condition-item').each(function(index, item) {
646 var $item = $(item);
647 var conditionType = $item.find('.condition-exclude-include-select').val();
648 var conditionValue = $item.find('.condition-select').val();
649
650 if (selectedValues.has(conditionValue)) {
651 hasDuplicate = true;
652 return false;
653 }
654
655 selectedValues.add(conditionValue);
656 conditions.push({
657 type: conditionType,
658 value: conditionValue
659 });
660 });
661
662 if (hasDuplicate) {
663 alert('Condition on same instance, please select other conditions');
664 return;
665 }
666
667
668 $('#save-conditions').addClass('active');
669 $('#save-conditions dotlottie-player').fadeIn(1000);
670
671 $(this).addClass('active-button').css({
672 'width': '300px',
673 'padding-right': '85px',
674 'transition': 'width .5s ease, padding-right .5s ease'
675 });
676
677 $.ajax({
678 url: solaceSitebuilderParams.ajaxurl,
679 method: 'POST',
680 dataType: 'json',
681 contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
682 data: {
683 action: 'save_conditions',
684 post_id: postId,
685 part: part,
686 conditions: conditions,
687 from: 'edit',
688 nonce: solaceSitebuilderParams.nonce,
689 security: solaceSitebuilderParams.nonce,
690 },
691 success: function(response) {
692 if (response.success) {
693 window.location.href = solaceSitebuilderParams['part_' + part];
694 } else {
695 alert('Failed to save conditions: ' + (response.data || 'Unknown error.'));
696 }
697 },
698 error: function(jqXHR, textStatus, errorThrown) {
699 alert('An error occurred while saving. Please try again.');
700 }
701 });
702
703 });
704
705 $('#partnew-save-new-conditions').on('click', function(e) {
706 e.preventDefault();
707 var assetsUrl = solaceSitebuilderParams.assetsUrl;
708
709 var $container = $('#all-new-conditions-container');
710 if ($container.length === 0) {
711 alert('No conditions container found.');
712 return;
713 }
714
715 var conditions = [];
716 var selectedValues = new Set();
717 var part = $('.condition-part-select').val();
718 var postId = 0;
719
720 var hasDuplicate = false;
721
722 $container.find('.condition-item').each(function(index, item) {
723 var $item = $(item);
724 var conditionType = $item.find('.condition-exclude-include-select').val();
725 var conditionValue = $item.find('.condition-select').val();
726
727 if (selectedValues.has(conditionValue)) {
728 hasDuplicate = true;
729 return false;
730 }
731
732 selectedValues.add(conditionValue);
733 conditions.push({
734 type: conditionType,
735 value: conditionValue
736 });
737 });
738
739 if (hasDuplicate) {
740 alert('Condition on same instance, please select other conditions');
741 return;
742 }
743
744 $('#partnew-save-new-conditions').addClass('active');
745 $('#partnew-save-new-conditions dotlottie-player').fadeIn(1000);
746
747 $(this).addClass('active-button').css({
748 'width': '300px',
749 'padding-right': '85px',
750 'transition': 'width .5s ease, padding-right .5s ease'
751 });
752
753 $.ajax({
754 url: solaceSitebuilderParams.ajaxurl,
755 method: 'POST',
756 dataType: 'json',
757 contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
758 data: {
759 action: 'save_conditions',
760 part: part,
761 conditions: conditions,
762 nonce: solaceSitebuilderParams.nonce,
763 security: solaceSitebuilderParams.nonce,
764 from: 'add-new'
765 },
766 success: function(response) {
767 console.log('AJAX Response:', response);
768 if (response.success) {
769 postId = response.data.post_id;
770 console.log('postID sukses:' + postId);
771 saveEditConditions(postId, part, conditions);
772 } else {
773 alert('Failed to save conditions: ' + (response.data || 'Unknown error.'));
774 }
775 },
776 error: function(jqXHR, textStatus, errorThrown) {
777 console.error('AJAX error:', textStatus, errorThrown);
778 console.error('Response Text:', jqXHR.responseText);
779 alert('An error occurred while saving. Please try again.');
780 }
781 });
782
783 });
784
785 $('#add-condition').on('click', function() {
786 var conditionsContainer = $('.conditions-container:visible');
787 var conditionCount = conditionsContainer.find('.condition-item').length + 1;
788 var assetsUrl = solaceSitebuilderParams.assetsUrl;
789
790 var conditionItem = $(`
791 <div class="condition-item">
792 <span class="icon-container">
793 <img src="${assetsUrl}images/plus-include.svg" />
794 </span>
795 <select name="condition_${conditionCount}_exclude_include" class="condition-exclude-include-select">
796 <option value="include">${solaceConditions.includeLabel}</option>
797 <option value="exclude">${solaceConditions.excludeLabel}</option>
798 </select>
799 <select name="condition_${conditionCount}_value" class="condition-select">
800 ${generateOptionsHtml()}
801 </select>
802 <a href="#" class="delete-condition dashicons dashicons-trash" title="Delete Condition"></a>
803 </div>
804 `);
805 conditionsContainer.append(conditionItem);
806
807 });
808
809 $('#addnew-add-condition').on('click', function() {
810 var conditionsContainer = $('#new-conditions-container:visible');
811 var conditionCount = conditionsContainer.find('.condition-item').length + 1;
812 var assetsUrl = solaceSitebuilderParams.assetsUrl;
813
814 var conditionItem = $(`
815 <div class="condition-item">
816 <span class="icon-container">
817 <img src="${assetsUrl}images/plus-include.svg" />
818 </span>
819 <select name="condition_${conditionCount}_exclude_include" class="condition-exclude-include-select">
820 <option value="include">${solaceConditions.includeLabel}</option>
821 <option value="exclude">${solaceConditions.excludeLabel}</option>
822 </select>
823 <select name="condition_${conditionCount}_value" class="condition-select">
824 ${generateOptionsHtml()}
825 </select>
826 <a href="#" class="delete-condition dashicons dashicons-trash" title="Delete Condition"></a>
827 </div>
828 `);
829 conditionsContainer.append(conditionItem);
830
831 });
832
833 $('#partnew-add-condition').on('click', function() {
834 var conditionsContainer = $('#all-new-conditions-container:visible');
835 var conditionCount = conditionsContainer.find('.condition-item').length + 1;
836 var assetsUrl = solaceSitebuilderParams.assetsUrl;
837
838 var conditionItem = $(`
839 <div class="condition-item">
840 <span class="icon-container">
841 <img src="${assetsUrl}images/plus-include.svg" />
842 </span>
843 <select name="condition_${conditionCount}_exclude_include" class="condition-exclude-include-select">
844 <option value="include">${solaceConditions.includeLabel}</option>
845 <option value="exclude">${solaceConditions.excludeLabel}</option>
846 </select>
847 <select name="condition_${conditionCount}_value" class="condition-select">
848 ${generateOptionsHtml()}
849 </select>
850 <a href="#" class="delete-condition dashicons dashicons-trash" title="Delete Condition"></a>
851 </div>
852 `);
853 conditionsContainer.append(conditionItem);
854
855 });
856
857 $('#edit-conditions-popup').on('click', '.delete-condition', function(e) {
858 e.preventDefault();
859 $(this).closest('.condition-item').remove();
860 });
861
862 $('#add-new-popup').on('click', '.delete-condition', function(e) {
863 e.preventDefault();
864 $(this).closest('.condition-item').remove();
865 });
866
867 $('#all-add-new-popup').on('click', '.delete-condition', function(e) {
868 e.preventDefault();
869 $(this).closest('.condition-item').remove();
870 });
871
872 function hidePopup() {
873 $('#edit-conditions-overlay').fadeOut(400);
874 $('#edit-conditions-popup').fadeOut(400);
875 $('#add-new-overlay').fadeOut(400);
876 $('#add-new-popup').fadeOut(400);
877 $('#all-add-new-overlay').fadeOut(400);
878 $('#all-add-new-popup').fadeOut(400);
879 }
880
881 $('#edit-conditions-popup .close-popup, #edit-conditions-overlay').on('click', function() {
882 hidePopup();
883 });
884
885 $('#add-new-popup .close-popup, #add-new-overlay').on('click', function() {
886 hidePopup();
887 });
888
889 $('#all-add-new-popup .close-popup, #all-add-new-overlay').on('click', function() {
890 hidePopup();
891 });
892
893 $('#add-include-condition').on('click', function() {
894 var includeHtml = `
895 <select name="solace_sitebuilder_conditions[include][]">
896 ${generateOptionsHtml()}
897 </select>`;
898 $('#include-conditions-container').append(includeHtml);
899 });
900
901 $('#add-exclude-condition').on('click', function() {
902 var excludeHtml = `
903 <select name="solace_sitebuilder_conditions[exclude][]">
904 ${generateOptionsHtml()}
905 </select>`;
906 $('#exclude-conditions-container').append(excludeHtml);
907 });
908
909 var selectedPostId = null; // To keep track of the selected post
910
911 // When the Rename button is clicked
912 $('.solace-rename-button').on('click', function(e) {
913 e.preventDefault();
914
915 const $button = $(this);
916 const postId = $button.data('post-id');
917 const $item = $button.closest('.solace-list-item');
918 const $titleColumn = $item.find('.title-column');
919
920 // Prevent action if the rename input is already active in this item
921 if ($titleColumn.find('.rename-input').length) {
922 return;
923 }
924
925 // Reset all title columns back to their original titles (if any)
926 $('.solace-list-item .title-column').each(function() {
927 const $col = $(this);
928 const originalTitle = $col.data('original-title');
929
930 // Restore the original title only if it was previously saved
931 if (originalTitle) {
932 $col.text(originalTitle);
933 }
934 });
935
936 // Store the current title as a data attribute for possible reset later
937 const currentTitle = $titleColumn.text().trim();
938 $titleColumn.data('original-title', currentTitle);
939
940 // Replace the title text with an input field, save button, and cancel button
941 $titleColumn.html(`
942 <input style="border-radius: 8px; border: 1px solid #f1f1f1;" type="text" class="rename-input" value="${currentTitle}" />
943 <button style="margin-left: 10px; padding: 0 20px;" class="button save-rename" data-post-id="${postId}">Save</button>
944 <button style="margin-left: 5px; padding: 0 20px;" class="button cancel-rename">Cancel</button>
945 `);
946
947 // Focus the input after it has been added to the DOM
948 const $input = $titleColumn.find('.rename-input');
949 $input.focus();
950
951 // Move cursor to the end of the text
952 const inputEl = $input.get(0);
953 inputEl.setSelectionRange(inputEl.value.length, inputEl.value.length);
954
955 });
956
957 // When the Save button is clicked
958 $(document).on('click', '.save-rename', function(e) {
959 e.preventDefault();
960
961 const $saveBtn = $(this);
962 const postId = $saveBtn.data('post-id');
963 const $input = $saveBtn.siblings('.rename-input');
964 const newTitle = $input.val();
965
966 // Send AJAX request to WordPress to update the post title
967 $.ajax({
968 url: solaceSitebuilderParams.ajaxurl,
969 type: 'POST',
970 data: {
971 action: 'solace_rename_post_title',
972 post_id: postId,
973 new_title: newTitle,
974 nonce: solaceSitebuilderParams.nonce
975 },
976 success: function(response) {
977 if (response.success) {
978 $saveBtn.closest('.title-column')
979 .text(newTitle)
980 .data('original-title', newTitle); // Update the original title
981
982 Swal.fire({
983 icon: 'success',
984 title: solaceSitebuilderI18n.rename_success_title,
985 text: solaceSitebuilderI18n.rename_success_text,
986 showCloseButton: true,
987 customClass: {
988 confirmButton: 'swal2-confirm-orange'
989 },
990 });
991 } else {
992 Swal.fire({
993 icon: 'error',
994 title: solaceSitebuilderI18n.rename_failed_title,
995 text: solaceSitebuilderI18n.rename_failed_text,
996 showCloseButton: true,
997 });
998 }
999 },
1000 error: function() {
1001 Swal.fire({
1002 icon: 'error',
1003 title: solaceSitebuilderI18n.ajax_error_title,
1004 text: solaceSitebuilderI18n.ajax_error_text,
1005 showCloseButton: true,
1006 });
1007 }
1008 });
1009 });
1010
1011 // When the Cancel button is clicked
1012 $(document).on('click', '.cancel-rename', function(e) {
1013 e.preventDefault();
1014
1015 const $cancelBtn = $(this);
1016 const $titleColumn = $cancelBtn.closest('.title-column');
1017 const originalTitle = $titleColumn.data('original-title');
1018
1019 if (originalTitle) {
1020 $titleColumn.text(originalTitle);
1021 }
1022 });
1023
1024 // Trigger save on Enter key in rename input
1025 $(document).on('keydown', '.rename-input', function(e) {
1026 if (e.key === "Enter") {
1027 e.preventDefault();
1028 $(this).siblings('.save-rename').trigger('click');
1029 }
1030 });
1031
1032 $('#solace-save-404').on('click', function(e) {
1033 e.preventDefault();
1034
1035 $('#solace-save-404').addClass('active');
1036 $('#solace-save-404 dotlottie-player').fadeIn(1000);
1037
1038 $(this).addClass('active-button').css({
1039 'width': '300px',
1040 'padding-right': '85px',
1041 'transition': 'width .5s ease, padding-right .5s ease'
1042 });
1043
1044 var part = 404;
1045 var postId=0;
1046
1047 var conditions = [{
1048 type: '',
1049 value: ''
1050 }];
1051
1052 console.log('Conditions to be sent:', conditions);
1053
1054 $.ajax({
1055 url: solaceSitebuilderParams.ajaxurl,
1056 method: 'POST',
1057 dataType: 'json',
1058 contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
1059 data: {
1060 action: 'save_conditions',
1061 part: part,
1062 conditions: conditions,
1063 from: 'add-new',
1064 nonce: solaceSitebuilderParams.nonce,
1065 security: solaceSitebuilderParams.nonce,
1066 },
1067 success: function(response) {
1068 console.log('AJAX Response:', response);
1069 if (response.success) {
1070 postId = response.data.post_id;
1071 console.log('postID sukses:'+postId);
1072 saveEditConditions(postId, part, conditions);
1073 } else {
1074 alert('Failed to save conditions: ' + (response.data || 'Unknown error.'));
1075 }
1076 },
1077 error: function(jqXHR, textStatus, errorThrown) {
1078 console.error('AJAX error:', textStatus, errorThrown);
1079 console.error('Response Text:', jqXHR.responseText);
1080 alert('An error occurred while saving. Please try again.');
1081 }
1082 });
1083 });
1084
1085 document.addEventListener("DOMContentLoaded", function() {
1086 const iframe = document.getElementById("responsive-iframe");
1087 const customHeaderContent = document.getElementById("custom-header-content");
1088 const previewContainer = document.querySelector(".preview-container");
1089
1090
1091 function adjustWidths() {
1092 if (!previewContainer) {
1093 console.warn("Skipping adjustWidths: .preview-container not found.");
1094 return;
1095 }
1096
1097 const containerWidth = previewContainer.offsetWidth;
1098 const minWidth = 1025; // Minimum width in pixels
1099
1100 const adjustedWidth = containerWidth < minWidth ? minWidth : containerWidth;
1101
1102 // Calculate scale factor based on ratio between custom-header-content width and iframe width
1103 const screenWidth = window.innerWidth;
1104 const customHeaderWidth = screenWidth - 479; // Custom header content width
1105 const iframeWidth = 1400; // Fixed iframe width
1106 const scaleFactor = customHeaderWidth / iframeWidth; // Calculate scale ratio
1107
1108 iframe.style.width = `${iframeWidth}px`; // Fixed iframe width
1109 iframe.style.height = `${iframeWidth * 0.1819375}px`; // Maintain aspect ratio (254.7125 / 1400)
1110 iframe.style.transform = `scale(${scaleFactor})`;
1111 iframe.style.transformOrigin = "top left";
1112
1113 // Apply calculated width to customHeaderContent
1114 customHeaderContent.style.width = `${customHeaderWidth}px`;
1115
1116 // Debugging logs
1117 // console.log("Container Width:", containerWidth);
1118 // console.log("Adjusted Width:", adjustedWidth);
1119 // console.log("Scale Factor:", scaleFactor);
1120 // console.log("Iframe Width:", iframe.style.width);
1121 // console.log("Iframe Height:", iframe.style.height);
1122 // console.log("Screen Width:", screenWidth);
1123 // console.log("Custom Header Content Width:", customHeaderContent.style.width);
1124 }
1125
1126
1127
1128 // Function to check if the URL contains the parameter "part"
1129 function hasPartParameter() {
1130 const urlParams = new URLSearchParams(window.location.search);
1131 return urlParams.has("part"); // Returns true if "part" exists in the URL
1132 }
1133
1134 // Run adjustWidths only if the URL contains "&part"
1135 if (hasPartParameter() && previewContainer) {
1136 adjustWidths();
1137 window.addEventListener("resize", adjustWidths);
1138 } else {
1139 // console.log("Skipping adjustWidths: URL parameter 'part' not found.");
1140 }
1141
1142 });
1143
1144 $(window).on('elementor/frontend/init', function() {
1145 console.log("Elementor frontend initialized");
1146
1147 // Mengecek apakah ada control untuk background-color
1148 if (typeof elementor !== 'undefined' && elementor.settings && elementor.settings.controls) {
1149 console.log("Elementor settings controls found");
1150
1151 // Memastikan kontrol button background color ada
1152 if (elementor.settings.controls.button_background_color) {
1153 elementor.settings.controls.button_background_color.on('change', function(newColor) {
1154 console.log("New background color from color picker: ", newColor);
1155
1156 // Terapkan warna baru pada elemen .woocommerce ul.products li.product .button
1157 if (newColor) {
1158 $('.woocommerce ul.products li.product .button').css('background-color', newColor);
1159 console.log("New color applied to WooCommerce button:", newColor);
1160 }
1161 });
1162 }
1163 } else {
1164 console.warn("Elementor settings or controls not found");
1165 }
1166 });
1167
1168
1169
1170 })(jQuery);
1171
1172 document.addEventListener("DOMContentLoaded", function() {
1173 const upgradeUrl = solaceSitebuilderParams.upgradeUrl;
1174
1175 document.querySelectorAll(".lock button").forEach(function(btn) {
1176 btn.addEventListener("click", function(e) {
1177 e.preventDefault();
1178 window.open(upgradeUrl, "_blank");
1179 });
1180 });
1181 });
1182