diff --git a/acm-autocomplete.js b/acm-autocomplete.js index 5f8a853..3acc58b 100644 --- a/acm-autocomplete.js +++ b/acm-autocomplete.js @@ -39,38 +39,52 @@ bindEvents: function() { var self = this; - // Use event delegation for dynamically added conditional selects (Add form only). - $( document ).on( 'change', '#add-adcode select[name="acm-conditionals[]"]', function() { + // Use event delegation for dynamically added conditional selects (Add and Edit forms). + $( document ).on( 'change', '#add-adcode select[name="acm-conditionals[]"], #edit-adcode select[name="acm-conditionals[]"]', function() { self.handleConditionalChange( $( this ) ); self.updateAddButtonVisibility(); + self.updateOperatorVisibility(); }); - // Re-initialize when new conditional rows are added. - $( document ).on( 'click', '.add-more-conditionals', function() { - // Small delay to allow DOM to update. + // Handle adding new conditional rows. + $( document ).on( 'click', '.add-more-conditionals', function( e ) { + e.preventDefault(); + var $button = $( this ); + var $form = $button.closest( 'form' ); + var $container = $form.find( '.form-new-row' ); + + self.addConditionalRow( $container ); + + // Small delay to allow DOM to update, then clean up. setTimeout( function() { self.cleanupNewRows(); self.updateAddButtonVisibility(); + self.updateOperatorVisibility(); }, 100 ); }); // Handle remove conditional click. - $( document ).on( 'click', '.acm-remove-conditional', function() { + $( document ).on( 'click', '.acm-remove-conditional', function( e ) { + e.preventDefault(); + var $row = $( this ).closest( '.conditional-single-field' ); + $row.remove(); + setTimeout( function() { self.updateAddButtonVisibility(); + self.updateOperatorVisibility(); }, 100 ); }); }, /** * Initialize any existing conditional fields on page load. - * Only targets the Add form, not inline edit. + * Targets both Add and Edit forms. */ initExistingFields: function() { var self = this; - // Only target the Add form to avoid conflicts with inline edit. - $( '#add-adcode select[name="acm-conditionals[]"]' ).each( function() { + // Target both Add and Edit forms. + $( '#add-adcode select[name="acm-conditionals[]"], #edit-adcode select[name="acm-conditionals[]"]' ).each( function() { var $select = $( this ); var conditional = $select.val(); var $argumentsContainer = $select.closest( '.conditional-single-field' ).find( '.conditional-arguments' ); @@ -92,6 +106,62 @@ }); }, + /** + * Add a new conditional row to the form. + * + * @param {jQuery} $container The container to add the row to. + */ + addConditionalRow: function( $container ) { + var $master = $container.find( '#conditional-single-field-master' ); + + if ( ! $master.length ) { + $master = $container.find( '.conditional-single-field' ).first(); + } + + if ( ! $master.length ) { + return; + } + + // Clone the master row. + var $newRow = $master.clone(); + + // Remove the master ID so only one exists. + $newRow.removeAttr( 'id' ); + + // Reset select to default. + $newRow.find( 'select[name="acm-conditionals[]"]' ).val( '' ); + + // Reset and show the input. + var $input = $newRow.find( 'input[name="acm-arguments[]"]' ); + $input.val( '' ).show(); + + // Remove any Select2 elements that may have been cloned. + $newRow.find( 'select.acm-autocomplete-select' ).remove(); + $newRow.find( '.select2-container' ).remove(); + + // Restore hidden input if present. + var $hiddenInput = $newRow.find( 'input[data-original-name="acm-arguments[]"]' ); + if ( $hiddenInput.length ) { + $hiddenInput + .attr( 'name', 'acm-arguments[]' ) + .removeAttr( 'data-original-name' ) + .val( '' ) + .show(); + } + + // Add remove link if not present. + var $arguments = $newRow.find( '.conditional-arguments' ); + if ( ! $arguments.find( '.acm-remove-conditional' ).length ) { + $arguments.append( ' Remove' ); + } + + // Hide the arguments container initially. + $arguments.hide(); + + // Append to container. + $container.append( $newRow ); + }, + /** * Clean up newly added conditional rows. * @@ -366,22 +436,53 @@ * Shows the button only when at least one condition is selected. */ updateAddButtonVisibility: function() { - var $form = $( '#add-adcode' ); - var $addButton = $form.find( '.form-add-more' ); - var hasSelectedCondition = false; + var $forms = $( '#add-adcode, #edit-adcode' ); + + $forms.each( function() { + var $form = $( this ); + var $addButton = $form.find( '.form-add-more' ); + var hasSelectedCondition = false; + + // Check if any conditional select has a value. + $form.find( 'select[name="acm-conditionals[]"]' ).each( function() { + if ( $( this ).val() ) { + hasSelectedCondition = true; + return false; // Break the loop. + } + }); + + if ( hasSelectedCondition ) { + $addButton.addClass( 'visible' ); + } else { + $addButton.removeClass( 'visible' ); + } + }); + }, + + /** + * Update visibility of the Logical Operator row. + * + * Shows the operator row only when 2+ conditions are selected. + */ + updateOperatorVisibility: function() { + var $operatorRow = $( '#operator-row' ); + + if ( ! $operatorRow.length ) { + return; + } - // Check if any conditional select has a value. - $form.find( 'select[name="acm-conditionals[]"]' ).each( function() { + // Count selected conditionals. + var selectedCount = 0; + $( '#edit-adcode select[name="acm-conditionals[]"]' ).each( function() { if ( $( this ).val() ) { - hasSelectedCondition = true; - return false; // Break the loop. + selectedCount++; } }); - if ( hasSelectedCondition ) { - $addButton.addClass( 'visible' ); + if ( selectedCount >= 2 ) { + $operatorRow.show(); } else { - $addButton.removeClass( 'visible' ); + $operatorRow.hide(); } } }; diff --git a/acm.css b/acm.css index 3b55ff7..86ba15c 100644 --- a/acm.css +++ b/acm.css @@ -37,127 +37,11 @@ tr:hover .row-actions { margin-bottom: 5px; } -.inline-edit-col .acm-section-label { - margin-bottom: 5px; - text-transform: none; -} - -.inline-edit-col .acm-float-left { - float: left; -} - -.inline-edit-col .acm-column-fields, -.inline-edit-col .acm-priority-field { - width: 250px; -} - -.inline-edit-col .acm-column-fields label { - float: left; - width: 75px; -} - -.inline-edit-col .acm-column-fields input { - margin-bottom: 5px; -} - -.inline-edit-col .acm-conditional-fields { - float: left; - min-width: 270px; -} - -.inline-edit-col .acm-conditional-fields .conditional-arguments { - margin-left: 140px; -} - -.inline-edit-col .acm-conditional-fields .conditional-arguments input { - width: 70%; - margin-bottom: 5px; -} - -.inline-edit-col .acm-conditional-fields .form-add-more { - margin-top: 10px; - clear: both; -} - #add-adcode .form-add-more { clear:left; width: 90%; } -.acm-edit-field { - position: relative; - max-width: 200px; - float: left; - margin: 15px 0 0 15px; -} - -.acm-edit-field label { - position: relative; - float: left; - font-weight: 700; - color: #333; -} - -.acm-edit-cond, -.acm-cancel-button, -.acm-edit-field input, -.acm-conditional-label { - position: relative; - float: left; - clear: left; -} - -.acm-edit-cond { - margin: 5px 0 0 15px; -} - -.acm-edit-cond input { - margin-left: 15px; -} - -.acm-conditional-label { - width: 100%; - font-weight: 700; - color: #333; - margin: 10px 0 0 15px; -} - -.acm-cancel-button { - margin: 10px 0 30px 15px; -} - -.acm-edit-button { - float: left; - margin: 10px 0 30px 15px; -} - -.acm-x-cond { - font-size: 14px; - padding-left: 5px; - color: #888; - cursor: pointer; - font-family: sans-serif -} - -.acm-x-cond:hover { - color: #333; - text-decoration: underline; -} - -#acm-add-inline-cond { - display: block; - float: left; - clear: left; - padding-top: 5px; - width: 295px; - text-align: right; - cursor:pointer; -} - -#acm-add-inline-cond:hover { - text-decoration: underline; -} - .acm-global-options { clear: both; margin-bottom: 20px; @@ -214,12 +98,6 @@ tr:hover .row-actions { height: 28px; } -/* Inline edit Select2 styling */ -.inline-edit-col .conditional-arguments .select2-container { - width: 70% !important; - margin-bottom: 5px; -} - /* Hide Add button initially until first condition is selected */ #add-adcode .form-add-more { display: none; @@ -229,13 +107,76 @@ tr:hover .row-actions { display: block; } -/* Operator field styling in inline edit */ -.inline-edit-col .acm-operator-field { - clear: both; +/* Edit page styles */ +#edit-adcode .form-table th { + width: 200px; + padding: 20px 10px 20px 0; +} + +#edit-adcode .regular-text { + width: 25em; +} + +#edit-adcode .conditional-single-field { + margin-bottom: 10px; + display: flex; + align-items: flex-start; + gap: 10px; +} + +#edit-adcode .conditional-function { + flex: 0 0 200px; +} + +#edit-adcode .conditional-function select { + width: 100%; +} + +#edit-adcode .conditional-arguments { + flex: 1; + display: flex; + align-items: center; + gap: 10px; +} + +#edit-adcode .conditional-arguments input[type="text"] { + width: 200px; +} + +#edit-adcode .form-add-more { + display: none; margin-top: 10px; - padding-top: 10px; } -.inline-edit-col .acm-operator-field .acm-section-label { - margin-bottom: 5px; +#edit-adcode .form-add-more.visible { + display: block; +} + +#edit-adcode .acm-remove-conditional { + color: #b32d2e; + text-decoration: none; +} + +#edit-adcode .acm-remove-conditional:hover { + color: #a00; +} + +/* Select2 styling for edit page */ +#edit-adcode .conditional-arguments .select2-container { + width: 200px !important; +} + +#edit-adcode .conditional-arguments .select2-container--default .select2-selection--single { + height: 30px; + border-color: #8c8f94; + border-radius: 4px; +} + +#edit-adcode .conditional-arguments .select2-container--default .select2-selection--single .select2-selection__rendered { + line-height: 28px; + padding-left: 8px; +} + +#edit-adcode .conditional-arguments .select2-container--default .select2-selection--single .select2-selection__arrow { + height: 28px; } diff --git a/acm.js b/acm.js deleted file mode 100644 index 58c1777..0000000 --- a/acm.js +++ /dev/null @@ -1,396 +0,0 @@ -( function( window, $, undefined ) { - var document = window.document; - - var AdCodeManager = function() { - /** - * A reference to the AdCodeManager object so we avoid confusion with `this` later on - * - * @type {*} - */ - var SELF = this; - - /** - * Container for cached UI elements - * - * @type {Object} - */ - var UI = {}; - - /** - * Used for storing the currently edited ACM ID - * @type {Boolean} - */ - var EDIT_ID = false; - - /** - * Initializes the AdCodeManager when the object is instantiated. This script must always run from the footer - * after the DOM elements are rendered - * - * @private - */ - var _init = function() { - _cacheElements(); - _bindEvents(); - }; - - /** - * Caches useful DOM elements so we can easily reference them later without the extra lookup - * - * @private - */ - var _cacheElements = function() { - UI.addMoreButton = document.getElementById( 'conditional-tpl' ).querySelector( '.add-more-conditionals' ); - UI.theList = document.getElementById( 'the-list' ); - UI.theNew = document.getElementById( 'add-adcode' ); - }; - - /** - * Handles binding our events for the page to work - * - * @private - */ - var _bindEvents = function() { - _addEvent( 'click', UI.addMoreButton, _addConditional ); - _addEvent( 'click', UI.theList, _delegateListClicks ); - _addEvent( 'click', UI.theNew, _delegateNewAdClicks ); - _addEvent( 'keydown', UI.theList, _delegateListKeyEvents ); - }; - - /** - * Registers a DOM event for the specified element - * - * @param event The event we're hooking to - * @param element The element we want to monitor for the event - * @param callback The callback to be fired when the event is triggered - * @private - */ - var _addEvent = function( event, element, callback ) { - if( window.addEventListener ) { - element.addEventListener( event, callback, false ); - } - else { - element.attachEvent( 'on' + event, callback ); - } - }; - - /** - * Handles adding a new conditional row to the UI for the user - * - * @param e The event object - * @private - */ - var _addConditional = function( e ) { - e = e || window.event; - var target = e.srcElement || e.target; - var parent = target.parentNode.parentNode.querySelector( '.form-new-row' ); - _addInlineConditionalRow( parent ); - - _killEvent( e ); - }; - - /** - * Kills the passed event and prevents it from bubbling up the DOM - * - * @param e The event we're killing - * @private - */ - var _killEvent = function( e ) { - e.returnValue = false; - e.cancelBubble = true; - if( e.stopPropagation ) { - e.stopPropagation(); - } - if( e.preventDefault ) { - e.preventDefault(); - } - }; - - /** - * Handles checking delegated events for the add ad code area - * - * @param e The event object - * @private - */ - var _delegateNewAdClicks = function( e ) { - e = e || window.event; - var target = e.srcElement || e.target; - - // check for remove conditional call - if( _hasClass( target, 'acm-remove-conditional' ) === true ) { - _removeInlineConditionalRow( target ); - _killEvent( e ); - } - }; - - /** - * Handles checking delegated key events for the inline editor and table rows - * @param e - * @private - */ - var _delegateListKeyEvents = function( e ) { - e = e || window.event; - var key = e.which || e.keyCode; - - // 13 is Enter, which avoids the default form on the page from saving - if ( key === 13 ) { - _saveInlineEditorChanges(); - _killEvent( e ); - } - }; - - /** - * Handles checking delegated events for the inline editor and table rows - * - * @param e The event object - * @private - */ - var _delegateListClicks = function( e ) { - e = e || window.event; - var target = e.srcElement || e.target; - - // check for ajax edit click - if( _hasClass( target, 'acm-ajax-edit' ) === true ) { - // close other editors - if( EDIT_ID !== false ) { - if( confirm( 'Are you sure you want to do this? Any unsaved data will be lost.' ) === false ) { - _killEvent( e ); - return; - } - _toggleInlineEdit( false ); - } - - EDIT_ID = parseInt( target.id.replace( 'acm-edit-', '' ), 10 ); - _toggleInlineEdit( true ); - _killEvent( e ); - } - - // check for cancel button - else if( _hasClass( target, 'cancel' ) === true && EDIT_ID !== false ) { - _toggleInlineEdit( false ); - EDIT_ID = false; - } - - // check for remove conditional call - else if( _hasClass( target, 'acm-remove-conditional' ) === true ) { - _removeInlineConditionalRow( target ); - _killEvent( e ); - } - - // check for save button - else if( _hasClass( target, 'save' ) === true ) { - _toggleLoader( true ); - _saveInlineEditorChanges(); - _killEvent( e ); - } - - // check for add more conditionals - else if( _hasClass( target, 'add-more-conditionals' ) === true ) { - _addInlineConditionalRow( UI.theList.querySelector( '#ad-code-' + EDIT_ID + ' .acm-editor-row .acm-conditional-fields .form-new-row' ) ); - _killEvent( e ); - } - }; - - /** - * Saves any inline editor changes that occurred - * - * @private - */ - var _saveInlineEditorChanges = function() { - $.post( window.ajaxurl, _getFormData(), function( result ) { - if( result ) { - if( result.indexOf( '
' . esc_html( $message_text ) . '