From 380a93994a95c5cc299786e6af5fd2cde3f11c3d Mon Sep 17 00:00:00 2001 From: Melloware Date: Wed, 22 May 2024 11:42:45 -0400 Subject: [PATCH] Fix #11929: Confirm add yes/no icon handling (#11981) --- docs/15_0_0/gettingstarted/whatsnew.md | 2 + .../confirmdialog/confirmDialog001.xhtml | 14 ++- .../webapp/confirmpopup/confirmPopup001.xhtml | 10 +- .../confirmdialog/ConfirmDialog001Test.java | 13 +- .../confirmpopup/ConfirmPopup001Test.java | 14 ++- .../webapp/ui/overlay/confirmDialog.xhtml | 28 +++-- .../main/webapp/ui/overlay/confirmPopup.xhtml | 10 +- .../behavior/confirm/ConfirmBehavior.java | 22 ++++ .../resources/META-INF/primefaces.taglib.xml | 12 ++ .../primefaces/confirmpopup/confirmpopup.js | 115 ++++++++++-------- .../resources/primefaces/core/core.utils.js | 27 ++++ .../resources/primefaces/dialog/dialog.js | 11 +- 12 files changed, 189 insertions(+), 89 deletions(-) diff --git a/docs/15_0_0/gettingstarted/whatsnew.md b/docs/15_0_0/gettingstarted/whatsnew.md index c33b4718b8..58cf09ed15 100644 --- a/docs/15_0_0/gettingstarted/whatsnew.md +++ b/docs/15_0_0/gettingstarted/whatsnew.md @@ -19,8 +19,10 @@ Look into [migration guide](https://primefaces.github.io/primefaces/15_0_0/#/../ * ConfirmDialog/ConfirmPopup * `yesButtonLabel`: overrides label of 'Yes' button (and restores it before the global confirm dialog is reused elsewhere) * `yesButtonClass`: adds given class to 'Yes' button (and removes it before the global confirm dialog is reused elsewhere) + * `yesButtonIcon`: overrides icon of 'Yes' button (and removes it before the global confirm dialog is reused elsewhere) * `noButtonLabel`: overrides label of 'No' button (and restores it before the global confirm dialog is reused elsewhere) * `noButtonClass`: adds given class to 'No' button (and removes it before the global confirm dialog is reused elsewhere) + * `noButtonIcon`: overrides icon of 'No' button (and removes it before the global confirm dialog is reused elsewhere) * `confirmMessage`: facet on the parent component of the `p:confirm` behavior. Can be used as message content instead of the `p:confirm` `message` attribute. * FeedReader diff --git a/primefaces-integration-tests/src/main/webapp/confirmdialog/confirmDialog001.xhtml b/primefaces-integration-tests/src/main/webapp/confirmdialog/confirmDialog001.xhtml index d4cdbb08b5..5fb960df93 100644 --- a/primefaces-integration-tests/src/main/webapp/confirmdialog/confirmDialog001.xhtml +++ b/primefaces-integration-tests/src/main/webapp/confirmdialog/confirmDialog001.xhtml @@ -22,10 +22,12 @@ + yesButtonLabel="Delete Me!" + yesButtonClass="bg-red-600 text-white" + yesButtonIcon="pi pi-trash" + noButtonLabel="Keep this!" + noButtonClass="bg-green-600 text-white" + noButtonIcon="pi pi-heart"/> @@ -33,8 +35,8 @@ - - + + diff --git a/primefaces-integration-tests/src/main/webapp/confirmpopup/confirmPopup001.xhtml b/primefaces-integration-tests/src/main/webapp/confirmpopup/confirmPopup001.xhtml index 72ceb65600..842ecdf964 100644 --- a/primefaces-integration-tests/src/main/webapp/confirmpopup/confirmPopup001.xhtml +++ b/primefaces-integration-tests/src/main/webapp/confirmpopup/confirmPopup001.xhtml @@ -23,14 +23,16 @@ message="Do you want to delete this record?" icon="pi pi-info-circle" yesButtonLabel="Delete Me!" - yesButtonClass="bg-red-500 text-white" + yesButtonClass="bg-red-600 text-white" + yesButtonIcon="pi pi-trash" noButtonLabel="Keep this!" - noButtonClass="bg-green-500 text-white" /> + noButtonClass="bg-green-600 text-white" + noButtonIcon="pi pi-heart"/> - - + + diff --git a/primefaces-integration-tests/src/test/java/org/primefaces/integrationtests/confirmdialog/ConfirmDialog001Test.java b/primefaces-integration-tests/src/test/java/org/primefaces/integrationtests/confirmdialog/ConfirmDialog001Test.java index 0e2992e94f..de2332f318 100644 --- a/primefaces-integration-tests/src/test/java/org/primefaces/integrationtests/confirmdialog/ConfirmDialog001Test.java +++ b/primefaces-integration-tests/src/test/java/org/primefaces/integrationtests/confirmdialog/ConfirmDialog001Test.java @@ -29,6 +29,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; import org.openqa.selenium.ElementClickInterceptedException; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.support.FindBy; @@ -99,7 +100,8 @@ void confirmNo(Page page) { page.confirm.click(); CommandButton noButton = dialog.getNoButton(); assertEquals("No", noButton.getText()); - assertCss(noButton, "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-confirmdialog-no ui-button-flat"); + assertCss(noButton, "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-left ui-confirmdialog-no ui-button-flat"); + assertCss(noButton.findElement(By.className("ui-icon")), "ui-button-icon-left ui-icon ui-c pi pi-times"); // Act noButton.click(); @@ -119,7 +121,8 @@ void confirmYes(Page page) { assertTrue(dialog.isVisible()); CommandButton yesButton = dialog.getYesButton(); assertEquals("Yes", yesButton.getText()); - assertCss(yesButton, "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-confirmdialog-yes"); + assertCss(yesButton, "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-left ui-confirmdialog-yes"); + assertCss(yesButton.findElement(By.className("ui-icon")), "ui-button-icon-left ui-icon ui-c pi pi-check"); // Act PrimeSelenium.guardAjax(yesButton).click(); @@ -140,7 +143,8 @@ void deleteNo(Page page) { CommandButton noButton = dialog.getNoButton(); assertEquals("Keep this!", noButton.getText()); assertCss(noButton, - "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-confirmdialog-no ui-button-flat bg-green-500 text-white"); + "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-left ui-confirmdialog-no ui-button-flat bg-green-600 text-white"); + assertCss(noButton.findElement(By.className("ui-icon")), "ui-button-icon-left ui-icon ui-c pi pi-heart"); // Act dialog.getNoButton().click(); @@ -163,7 +167,8 @@ void deleteYes(Page page) { page.delete.click(); CommandButton yesButton = dialog.getYesButton(); assertEquals("Delete Me!", yesButton.getText()); - assertCss(yesButton, "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-confirmdialog-yes bg-red-500 text-white"); + assertCss(yesButton, "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-left ui-confirmdialog-yes bg-red-600 text-white"); + assertCss(yesButton.findElement(By.className("ui-icon")), "ui-button-icon-left ui-icon ui-c pi pi-trash"); // Act PrimeSelenium.guardAjax(yesButton).click(); diff --git a/primefaces-integration-tests/src/test/java/org/primefaces/integrationtests/confirmpopup/ConfirmPopup001Test.java b/primefaces-integration-tests/src/test/java/org/primefaces/integrationtests/confirmpopup/ConfirmPopup001Test.java index 6f8f51f005..0c4c2c1bb2 100644 --- a/primefaces-integration-tests/src/test/java/org/primefaces/integrationtests/confirmpopup/ConfirmPopup001Test.java +++ b/primefaces-integration-tests/src/test/java/org/primefaces/integrationtests/confirmpopup/ConfirmPopup001Test.java @@ -29,6 +29,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; import org.openqa.selenium.support.FindBy; import org.primefaces.selenium.AbstractPrimePage; import org.primefaces.selenium.AbstractPrimePageTest; @@ -87,7 +88,8 @@ void confirmNo(Page page) { CommandButton noButton = popup.getNoButton(); assertEquals("No", noButton.getText()); assertCss(noButton, - "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-confirm-popup-no ui-button-flat"); + "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-left ui-confirm-popup-no ui-button-flat"); + assertCss(noButton.findElement(By.className("ui-icon")), "ui-button-icon-left ui-icon ui-c pi pi-times"); // Act noButton.click(); @@ -108,7 +110,8 @@ void confirmYes(Page page) { page.confirm.click(); CommandButton yesButton = popup.getYesButton(); assertEquals("Yes", yesButton.getText()); - assertCss(yesButton, "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-confirm-popup-yes"); + assertCss(yesButton, "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-left ui-confirm-popup-yes ui-state-focus"); + assertCss(yesButton.findElement(By.className("ui-icon")), "ui-button-icon-left ui-icon ui-c pi pi-check"); // Act PrimeSelenium.guardAjax(yesButton).click(); @@ -130,7 +133,8 @@ void deleteNo(Page page) { CommandButton noButton = popup.getNoButton(); assertEquals("Keep this!", noButton.getText()); assertCss(noButton, - "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-confirm-popup-no ui-button-flat bg-green-500 text-white"); + "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-left ui-confirm-popup-no ui-button-flat bg-green-600 text-white"); + assertCss(noButton.findElement(By.className("ui-icon")), "ui-button-icon-left ui-icon ui-c pi pi-heart"); // Act noButton.click(); @@ -154,7 +158,9 @@ void deleteYes(Page page) { page.delete.click(); CommandButton yesButton = popup.getYesButton(); assertEquals("Delete Me!", yesButton.getText()); - assertCss(yesButton, "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only ui-confirm-popup-yes bg-red-500 text-white"); + assertCss(yesButton, + "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-icon-left ui-confirm-popup-yes bg-red-600 text-white ui-state-focus"); + assertCss(yesButton.findElement(By.className("ui-icon")), "ui-button-icon-left ui-icon ui-c pi pi-trash"); // Act PrimeSelenium.guardAjax(yesButton).click(); diff --git a/primefaces-showcase/src/main/webapp/ui/overlay/confirmDialog.xhtml b/primefaces-showcase/src/main/webapp/ui/overlay/confirmDialog.xhtml index c606732d08..ee2cf3caa0 100644 --- a/primefaces-showcase/src/main/webapp/ui/overlay/confirmDialog.xhtml +++ b/primefaces-showcase/src/main/webapp/ui/overlay/confirmDialog.xhtml @@ -25,17 +25,19 @@ - - - - - + + + + + @@ -49,8 +51,8 @@ - - + + diff --git a/primefaces-showcase/src/main/webapp/ui/overlay/confirmPopup.xhtml b/primefaces-showcase/src/main/webapp/ui/overlay/confirmPopup.xhtml index 3e1538ac41..1a718a3a49 100644 --- a/primefaces-showcase/src/main/webapp/ui/overlay/confirmPopup.xhtml +++ b/primefaces-showcase/src/main/webapp/ui/overlay/confirmPopup.xhtml @@ -30,9 +30,11 @@ message="Do you want to delete this record?" icon="pi pi-info-circle" yesButtonLabel="Delete Me!" - yesButtonClass="bg-red-500 text-white" + yesButtonClass="bg-red-600 text-white" + yesButtonIcon="pi pi-trash" noButtonLabel="Keep this!" - noButtonClass="bg-green-500 text-white" /> + noButtonClass="bg-green-600 text-white" + noButtonIcon="pi pi-heart"/> @@ -40,8 +42,8 @@ - - + + diff --git a/primefaces/src/main/java/org/primefaces/behavior/confirm/ConfirmBehavior.java b/primefaces/src/main/java/org/primefaces/behavior/confirm/ConfirmBehavior.java index 17f5c4ba41..5c5e876d31 100644 --- a/primefaces/src/main/java/org/primefaces/behavior/confirm/ConfirmBehavior.java +++ b/primefaces/src/main/java/org/primefaces/behavior/confirm/ConfirmBehavior.java @@ -46,8 +46,10 @@ public enum PropertyKeys implements BehaviorAttribute { icon(String.class), yesButtonLabel(String.class), yesButtonClass(String.class), + yesButtonIcon(String.class), noButtonLabel(String.class), noButtonClass(String.class), + noButtonIcon(String.class), disabled(Boolean.class), beforeShow(String.class), escape(Boolean.class); @@ -92,8 +94,10 @@ public String getScript(ClientBehaviorContext behaviorContext) { String beforeShow = JSONObject.quote(getBeforeShow()); String yesButtonClass = JSONObject.quote(getYesButtonClass()); String yesButtonLabel = JSONObject.quote(getYesButtonLabel()); + String yesButtonIcon = JSONObject.quote(getYesButtonIcon()); String noButtonClass = JSONObject.quote(getNoButtonClass()); String noButtonLabel = JSONObject.quote(getNoButtonLabel()); + String noButtonIcon = JSONObject.quote(getNoButtonIcon()); source = (source == null) ? component.getClientId(context) : source; @@ -108,8 +112,10 @@ public String getScript(ClientBehaviorContext behaviorContext) { + ",message:" + messageText + ",yesButtonClass:" + yesButtonClass + ",yesButtonLabel:" + yesButtonLabel + + ",yesButtonIcon:" + yesButtonIcon + ",noButtonClass:" + noButtonClass + ",noButtonLabel:" + noButtonLabel + + ",noButtonIcon:" + noButtonIcon + ",icon:\"" + (icon == null ? "" : icon) + "\",beforeShow:" + beforeShow + "});return false;"; @@ -208,6 +214,14 @@ public void setYesButtonClass(String yesButtonClass) { put(PropertyKeys.yesButtonClass, yesButtonClass); } + public String getYesButtonIcon() { + return eval(PropertyKeys.yesButtonIcon, null); + } + + public void setYesButtonIcon(String yesButtonIcon) { + put(PropertyKeys.yesButtonIcon, yesButtonIcon); + } + public String getNoButtonLabel() { return eval(PropertyKeys.noButtonLabel, null); } @@ -223,4 +237,12 @@ public String getNoButtonClass() { public void setNoButtonClass(String noButtonClass) { put(PropertyKeys.noButtonClass, noButtonClass); } + + public String getNoButtonIcon() { + return eval(PropertyKeys.noButtonIcon, null); + } + + public void setNoButtonIcon(String noButtonIcon) { + put(PropertyKeys.noButtonIcon, noButtonIcon); + } } diff --git a/primefaces/src/main/resources/META-INF/primefaces.taglib.xml b/primefaces/src/main/resources/META-INF/primefaces.taglib.xml index 06beddbcb0..8227ec6edf 100644 --- a/primefaces/src/main/resources/META-INF/primefaces.taglib.xml +++ b/primefaces/src/main/resources/META-INF/primefaces.taglib.xml @@ -545,6 +545,12 @@ false java.lang.String + + + yesButtonIcon + false + java.lang.String + noButtonLabel @@ -557,6 +563,12 @@ false java.lang.String + + + noButtonIcon + false + java.lang.String + diff --git a/primefaces/src/main/resources/META-INF/resources/primefaces/confirmpopup/confirmpopup.js b/primefaces/src/main/resources/META-INF/resources/primefaces/confirmpopup/confirmpopup.js index f319d15f44..466282bc5e 100644 --- a/primefaces/src/main/resources/META-INF/resources/primefaces/confirmpopup/confirmpopup.js +++ b/primefaces/src/main/resources/META-INF/resources/primefaces/confirmpopup/confirmpopup.js @@ -49,9 +49,9 @@ PrimeFaces.widget.ConfirmPopup = PrimeFaces.widget.DynamicOverlayWidget.extend({ if (!cfg.appendTo && cfg.global) { cfg.appendTo = '@(body)'; } - + this._super(cfg); - + this.focusedElementBeforeDialogOpened = null; this.content = this.jq.children('.ui-confirm-popup-content'); this.message = this.content.children('.ui-confirm-popup-message'); @@ -61,13 +61,15 @@ PrimeFaces.widget.ConfirmPopup = PrimeFaces.widget.DynamicOverlayWidget.extend({ this.noButton = this.jq.find('.ui-confirm-popup-no'); this.yesButton.data('p-text', this.yesButton.children('.ui-button-text').text()); this.noButton.data('p-text', this.noButton.children('.ui-button-text').text()); + this.yesButton.data('p-icon', this.yesButton.children('.ui-icon').attr('class')); + this.noButton.data('p-icon', this.noButton.children('.ui-icon').attr('class')); } - + this.transition = PrimeFaces.utils.registerCSSTransition(this.jq, 'ui-connected-overlay'); - + this.bindEvents(); }, - + /** * Sets up all event listeners required by this widget. * @protected @@ -75,16 +77,16 @@ PrimeFaces.widget.ConfirmPopup = PrimeFaces.widget.DynamicOverlayWidget.extend({ bindEvents: function() { if (this.cfg.global) { PrimeFaces.confirmPopup = this; - + this.jq.on('click.ui-confirmpopup', '.ui-confirm-popup-yes, .ui-confirm-popup-no', null, function(e) { var el = $(this); - + if (el.hasClass('ui-confirm-popup-yes') && PrimeFaces.confirmPopupSource) { var source = PrimeFaces.confirmPopupSource; var id = source.get(0); var js = source.data('pfconfirmcommand'); var command = $(id); - + // Test if the function matches the pattern if (PrimeFaces.ajax.Utils.isAjaxRequest(js) || command.is('a')) { // command is ajax=true @@ -115,7 +117,7 @@ PrimeFaces.widget.ConfirmPopup = PrimeFaces.widget.DynamicOverlayWidget.extend({ } command.removeAttr("data-pfconfirmcommand").click(); } - + PrimeFaces.confirmPopup.hide(); PrimeFaces.confirmPopupSource = null; } @@ -123,7 +125,7 @@ PrimeFaces.widget.ConfirmPopup = PrimeFaces.widget.DynamicOverlayWidget.extend({ PrimeFaces.confirmPopup.hide(); PrimeFaces.confirmPopupSource = null; } - + e.preventDefault(); }); } @@ -147,13 +149,13 @@ PrimeFaces.widget.ConfirmPopup = PrimeFaces.widget.DynamicOverlayWidget.extend({ } }); } - + this.resizeHandler = PrimeFaces.utils.registerResizeHandler(this, 'resize.' + this.id + '_hide', this.jq, function() { if (PrimeFaces.hideOverlaysOnViewportChange === true) { $this.hide(); } }); - + this.scrollHandler = PrimeFaces.utils.registerConnectedOverlayScrollHandler(this, 'scroll.' + this.id + '_hide', target, function() { if (PrimeFaces.hideOverlaysOnViewportChange === true) { $this.hide(); @@ -173,12 +175,12 @@ PrimeFaces.widget.ConfirmPopup = PrimeFaces.widget.DynamicOverlayWidget.extend({ if (this.resizeHandler) { this.resizeHandler.unbind(); } - + if (this.scrollHandler) { this.scrollHandler.unbind(); } }, - + /** * Makes the popup visible. * @param {string | JQuery} [target] Selector or DOM element of the target component that triggers this popup. @@ -187,7 +189,7 @@ PrimeFaces.widget.ConfirmPopup = PrimeFaces.widget.DynamicOverlayWidget.extend({ // Remember the focused element before we opened the dialog // so we can return focus to it once we close the dialog. this.focusedElementBeforeDialogOpened = document.activeElement; - + if (this.transition) { var $this = this; @@ -210,7 +212,7 @@ PrimeFaces.widget.ConfirmPopup = PrimeFaces.widget.DynamicOverlayWidget.extend({ }); } }, - + /** * Hides the popup. * @param {PrimeFaces.widget.ConfirmPopup.HideCallback} callback Callback that is invoked after this popup was closed. @@ -228,7 +230,7 @@ PrimeFaces.widget.ConfirmPopup = PrimeFaces.widget.DynamicOverlayWidget.extend({ callback(); } $this.returnFocus(50); - + // Remove added classes and reset button labels to their original values if (!PrimeFaces.animationEnabled || !$this.isVisible()) { $this.restoreButtons(); @@ -241,7 +243,7 @@ PrimeFaces.widget.ConfirmPopup = PrimeFaces.widget.DynamicOverlayWidget.extend({ $this.restoreButtons(); } }, - + /** * Restore the button text and styling to its original form. * @private @@ -253,9 +255,11 @@ PrimeFaces.widget.ConfirmPopup = PrimeFaces.widget.DynamicOverlayWidget.extend({ $this.noButton.removeClass($this.noButton.data('p-class')); $this.yesButton.children('.ui-button-text').text($this.yesButton.data('p-text')); $this.noButton.children('.ui-button-text').text($this.noButton.data('p-text')); + $this.yesButton.children('.ui-icon').attr('class', $this.yesButton.data('p-icon')); + $this.noButton.children('.ui-icon').attr('class', $this.noButton.data('p-icon')); } }, - + /** * Aligns the popup so that it is shown at the correct position. * @param {JQuery} [target] Jquery selector that is the target of this popup @@ -264,36 +268,36 @@ PrimeFaces.widget.ConfirmPopup = PrimeFaces.widget.DynamicOverlayWidget.extend({ align: function(target) { if (target) { var $this = this; - + this.jq.removeClass('ui-confirm-popup-flipped'); - - this.jq.css({left:'0px', top:'0px', 'transform-origin': 'center top'}).position({ - my: 'left top' - ,at: 'left bottom' - ,of: target - ,collision: 'flipfit' - ,using: function(pos, directions) { - var targetOffset = target.offset(); - var arrowLeft = 0; - - if (pos.left < targetOffset.left) { - arrowLeft = targetOffset.left - pos.left; - } - $this.jq.css('--overlayArrowLeft', arrowLeft + 'px'); - - if (pos.top < targetOffset.top) { - $this.jq.addClass('ui-confirm-popup-flipped'); - } - else { - pos.top += parseFloat($this.jq.css('margin-top')); - } - - $(this).css('transform-origin', 'center ' + directions.vertical).css(pos); + + this.jq.css({ left: '0px', top: '0px', 'transform-origin': 'center top' }).position({ + my: 'left top' + , at: 'left bottom' + , of: target + , collision: 'flipfit' + , using: function(pos, directions) { + var targetOffset = target.offset(); + var arrowLeft = 0; + + if (pos.left < targetOffset.left) { + arrowLeft = targetOffset.left - pos.left; } - }); + $this.jq.css('--overlayArrowLeft', arrowLeft + 'px'); + + if (pos.top < targetOffset.top) { + $this.jq.addClass('ui-confirm-popup-flipped'); + } + else { + pos.top += parseFloat($this.jq.css('margin-top')); + } + + $(this).css('transform-origin', 'center ' + directions.vertical).css(pos); + } + }); } }, - + /** * Applies focus to the first focusable element of the content in the popup. */ @@ -322,27 +326,27 @@ PrimeFaces.widget.ConfirmPopup = PrimeFaces.widget.DynamicOverlayWidget.extend({ isVisible: function() { return this.jq.is(':visible'); }, - + /** * Shows the given message in this confirmation popup. * @param {Partial} msg Message to show. */ showMessage: function(msg) { - PrimeFaces.confirmPopupSource = (typeof(msg.source) === 'string') ? $(PrimeFaces.escapeClientId(msg.source)) : $(msg.source); - + PrimeFaces.confirmPopupSource = (typeof (msg.source) === 'string') ? $(PrimeFaces.escapeClientId(msg.source)) : $(msg.source); + var $this = this; var beforeShow = function() { if (msg.beforeShow) { PrimeFaces.csp.eval(msg.beforeShow); } - + $this.icon.removeClass().addClass('ui-confirm-popup-icon'); if (msg.icon !== 'null') { $this.icon.addClass(msg.icon); } - + if (msg.message) { - if (msg.escape){ + if (msg.escape) { $this.message.text(msg.message); } else { @@ -350,20 +354,25 @@ PrimeFaces.widget.ConfirmPopup = PrimeFaces.widget.DynamicOverlayWidget.extend({ } } - // Set labels and classes for yes and no buttons if provided + // Set labels, icons, and CSS classes for yes/no buttons if (msg.yesButtonLabel) { $this.yesButton.children('.ui-button-text').text(msg.yesButtonLabel); } if (msg.yesButtonClass) { $this.yesButton.addClass(msg.yesButtonClass).data('p-class', msg.yesButtonClass); } - + if (msg.yesButtonIcon) { + PrimeFaces.utils.replaceIcon($this.yesButton.children('.ui-icon'), msg.yesButtonIcon); + } if (msg.noButtonLabel) { $this.noButton.children('.ui-button-text').text(msg.noButtonLabel); } if (msg.noButtonClass) { $this.noButton.addClass(msg.noButtonClass).data('p-class', msg.noButtonClass); } + if (msg.noButtonIcon) { + PrimeFaces.utils.replaceIcon($this.noButton.children('.ui-icon'), msg.noButtonIcon); + } }; if (this.isVisible()) { diff --git a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.utils.js b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.utils.js index 3ca88c6c6d..3c9724e04d 100644 --- a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.utils.js +++ b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.utils.js @@ -1146,6 +1146,33 @@ if (!PrimeFaces.utils) { jq.remove(); } }, + + /** + * Replaces a specific CSS icon class on an element and appends a new icon class. + * If the target class is found, all classes after it are removed and the new class is added. + * + * @param {JQuery | undefined} jq - The jQuery element to modify. + * @param {string} addIcon - The new CSS icon class to add. + */ + replaceIcon: function(jq, addIcon) { + if (!jq || !jq.length) { + return; + } + // Get the value of the 'class' attribute and split it into an array + var classes = jq.attr('class').split(' '); + + // Find the index of the target class + var targetIndex = classes.indexOf('ui-c'); + + // If the target class is found, remove all classes after it and add the new class + if (targetIndex !== -1) { + // Create the new class string by keeping classes up to and including the target class, then adding the new class + var newClasses = classes.slice(0, targetIndex + 1).join(' ') + ' ' + addIcon; + + // Set the new class string on the element and store the new class in the 'p-icon' data attribute + jq.attr('class', newClasses).data('p-icon', addIcon); + } + }, }; // set animation state globally diff --git a/primefaces/src/main/resources/META-INF/resources/primefaces/dialog/dialog.js b/primefaces/src/main/resources/META-INF/resources/primefaces/dialog/dialog.js index b1fc30f35f..e35d7957fc 100644 --- a/primefaces/src/main/resources/META-INF/resources/primefaces/dialog/dialog.js +++ b/primefaces/src/main/resources/META-INF/resources/primefaces/dialog/dialog.js @@ -955,6 +955,8 @@ PrimeFaces.widget.ConfirmDialog = PrimeFaces.widget.Dialog.extend({ this.noButton = this.jq.find('.ui-confirmdialog-no'); this.yesButton.data('p-text', this.yesButton.children('.ui-button-text').text()); this.noButton.data('p-text', this.noButton.children('.ui-button-text').text()); + this.yesButton.data('p-icon', this.yesButton.children('.ui-icon').attr('class')); + this.noButton.data('p-icon', this.noButton.children('.ui-icon').attr('class')); this.jq.on('click.ui-confirmdialog', '.ui-confirmdialog-yes, .ui-confirmdialog-no', null, function(e) { var el = $(this); @@ -1031,6 +1033,8 @@ PrimeFaces.widget.ConfirmDialog = PrimeFaces.widget.Dialog.extend({ this.noButton.removeClass(this.noButton.data('p-class')); this.yesButton.children('.ui-button-text').text(this.yesButton.data('p-text')); this.noButton.children('.ui-button-text').text(this.noButton.data('p-text')); + this.yesButton.children('.ui-icon').attr('class', this.yesButton.data('p-icon')); + this.noButton.children('.ui-icon').attr('class', this.noButton.data('p-icon')); } }, @@ -1059,13 +1063,18 @@ PrimeFaces.widget.ConfirmDialog = PrimeFaces.widget.Dialog.extend({ if (msg.yesButtonClass) { this.yesButton.addClass(msg.yesButtonClass).data('p-class', msg.yesButtonClass); } - + if (msg.yesButtonIcon) { + PrimeFaces.utils.replaceIcon(this.yesButton.children('.ui-icon'), msg.yesButtonIcon); + } if (msg.noButtonLabel) { this.noButton.children('.ui-button-text').text(msg.noButtonLabel); } if (msg.noButtonClass) { this.noButton.addClass(msg.noButtonClass).data('p-class', msg.noButtonClass); } + if (msg.noButtonIcon) { + PrimeFaces.utils.replaceIcon(this.noButton.children('.ui-icon'), msg.noButtonIcon); + } // Set title, message content, and escape HTML if necessary if (msg.header) {