This is an automated email from the ASF dual-hosted git repository.

yao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new 246a2a16fbd7 [SPARK-55778][UI] Remove redundant 
data-bs-placement="top" from tooltip markup
246a2a16fbd7 is described below

commit 246a2a16fbd7196655156b7dfb0a16baccc89d0e
Author: Kent Yao <[email protected]>
AuthorDate: Thu Mar 5 12:45:09 2026 +0800

    [SPARK-55778][UI] Remove redundant data-bs-placement="top" from tooltip 
markup
    
    ### What changes were proposed in this pull request?
    
    Remove all `data-bs-placement="top"` attributes from tooltip markup across 
the Spark Web UI, including Scala files, JavaScript files, and HTML templates.
    
    ### Why are the changes needed?
    
    Bootstrap 5 Tooltip defaults to `top` placement (see [Bootstrap 
docs](https://getbootstrap.com/docs/5.3/components/tooltips/#options)), so 
explicitly setting `data-bs-placement="top"` is redundant. Removing it 
simplifies the HTML/JS markup without any behavioral change.
    
    ### Does this PR introduce _any_ user-facing change?
    
    No. Tooltip placement behavior remains identical since Bootstrap 5 already 
defaults to `top`.
    
    ### How was this patch tested?
    
    - `./dev/lint-js` — passed
    - `./dev/scalastyle` — passed
    - `./build/sbt 'core/testOnly org.apache.spark.ui.UIUtilsSuite'` — all 8 
tests passed
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Yes, GitHub Copilot assisted with identifying and removing the redundant 
attributes.
    
    Closes #54622 from yaooqinn/SPARK-55778.
    
    Authored-by: Kent Yao <[email protected]>
    Signed-off-by: Kent Yao <[email protected]>
---
 .../spark/ui/static/executorspage-template.html    | 46 +++++++++++-----------
 .../spark/ui/static/historypage-template.html      | 20 +++++-----
 .../org/apache/spark/ui/static/stagepage.js        |  1 -
 .../spark/ui/static/stagespage-template.html       |  2 +-
 .../main/scala/org/apache/spark/ui/UIUtils.scala   | 10 +++--
 .../org/apache/spark/ui/jobs/AllJobsPage.scala     |  6 +--
 .../scala/org/apache/spark/ui/jobs/JobPage.scala   |  6 +--
 .../scala/org/apache/spark/ui/jobs/StagePage.scala |  2 +-
 .../scala/org/apache/spark/ui/UIUtilsSuite.scala   |  2 +-
 9 files changed, 49 insertions(+), 46 deletions(-)

diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/executorspage-template.html
 
b/core/src/main/resources/org/apache/spark/ui/static/executorspage-template.html
index 3dfcc0dd0416..3654afc051aa 100644
--- 
a/core/src/main/resources/org/apache/spark/ui/static/executorspage-template.html
+++ 
b/core/src/main/resources/org/apache/spark/ui/static/executorspage-template.html
@@ -24,11 +24,11 @@ limitations under the License.
           <tr>
         <th></th>
         <th>RDD Blocks</th>
-        <th><span data-bs-toggle="tooltip" data-bs-placement="top"
+        <th><span data-bs-toggle="tooltip"
                   title="Memory used / total available memory for storage of 
data like RDD partitions cached in memory.">Storage Memory</span>
         </th>
         <th>
-          <span data-bs-toggle="tooltip" data-bs-placement="top"
+          <span data-bs-toggle="tooltip"
                 title="Memory used / total available memory for on heap 
storage of data like RDD partitions cached in memory.">On Heap Storage 
Memory</span>
         </th>
         <th>
@@ -37,25 +37,25 @@ limitations under the License.
         </th>
         <th>Disk Used</th>
         <th>Cores</th>
-        <th><span data-bs-toggle="tooltip" data-bs-placement="top" 
title="Number of tasks currently executing. Darker shading highlights executors 
with more active tasks.">Active Tasks</span></th>
-        <th><span data-bs-toggle="tooltip" data-bs-placement="top" 
title="Number of tasks that have failed on this executor. Darker shading 
highlights executors with a high proportion of failed tasks.">Failed 
Tasks</span></th>
+        <th><span data-bs-toggle="tooltip" title="Number of tasks currently 
executing. Darker shading highlights executors with more active tasks.">Active 
Tasks</span></th>
+        <th><span data-bs-toggle="tooltip" title="Number of tasks that have 
failed on this executor. Darker shading highlights executors with a high 
proportion of failed tasks.">Failed Tasks</span></th>
         <th>Complete Tasks</th>
         <th>Total Tasks</th>
-        <th><span data-bs-toggle="tooltip" data-bs-placement="top"
+        <th><span data-bs-toggle="tooltip"
                   title="Shaded red when garbage collection (GC) time is over 
10% of task time">
           Task Time (GC Time)</span></th>
-        <th><span data-bs-toggle="tooltip" data-bs-placement="top"
+        <th><span data-bs-toggle="tooltip"
                   title="Bytes and records read from Hadoop or from Spark 
storage.">Input</span></th>
-        <th><span data-bs-toggle="tooltip" data-bs-placement="top"
+        <th><span data-bs-toggle="tooltip"
                   title="Total shuffle bytes and records read (includes both 
data read locally and data read from remote executors).">
           Shuffle Read</span></th>
         <th>
-          <span data-bs-toggle="tooltip" data-bs-placement="top"
+          <span data-bs-toggle="tooltip"
                 title="Bytes and records written to disk in order to be read 
by a shuffle in a future stage.">
             Shuffle Write</span>
         </th>
         <th>
-          <span data-bs-toggle="tooltip" data-bs-placement="top"
+          <span data-bs-toggle="tooltip"
                 title="Number of executors excluded by the scheduler due to 
task failures.">
             Excluded</span>
         </th>
@@ -75,55 +75,55 @@ limitations under the License.
           <th>Status</th>
           <th>RDD Blocks</th>
           <th>
-            <span data-bs-toggle="tooltip" data-bs-placement="top"
+            <span data-bs-toggle="tooltip"
                   title="Memory used / total available memory for storage of 
data like RDD partitions cached in memory.">
               Storage Memory</span></th>
           <th>
-            <span data-bs-toggle="tooltip" data-bs-placement="top"
+            <span data-bs-toggle="tooltip"
                   title="Memory used / total available memory for on heap 
storage of data like RDD partitions cached in memory.">
               On Heap Storage Memory</span></th>
           <th>
-            <span data-bs-toggle="tooltip" data-bs-placement="top"
+            <span data-bs-toggle="tooltip"
                   title="Memory used / total available memory for off heap 
storage of data like RDD partitions cached in memory.">
               Off Heap Storage Memory</span></th>
           <th>
-            <span data-bs-toggle="tooltip" data-bs-placement="top"
+            <span data-bs-toggle="tooltip"
                   title="Peak onHeap / offHeap memory used by JVM.">
               Peak JVM Memory OnHeap / OffHeap</span></th>
           <th>
-            <span data-bs-toggle="tooltip" data-bs-placement="top"
+            <span data-bs-toggle="tooltip"
                   title="Peak onHeap / offHeap memory used for execution. This 
refers to memory used for computation in shuffles, joins, user data structures, 
etc. See the Memory Management Overview documentation for more details.">
               Peak Execution Memory OnHeap / OffHeap</span></th>
           <th>
-            <span data-bs-toggle="tooltip" data-bs-placement="top"
+            <span data-bs-toggle="tooltip"
             title="Peak storage onHeap / offHeap memory used for storage of 
data like RDD partitions cached in memory.">
               Peak Storage Memory OnHeap / OffHeap</span></th>
           <th>
-            <span data-bs-toggle="tooltip" data-bs-placement="top"
+            <span data-bs-toggle="tooltip"
                   title="Peak direct byte buffer / memory-mapped buffer pool 
memory used by JVM. This refers to BufferPoolMXBean with form 
'java.nio:type=BufferPool,name=direct' and 
'java.nio:type=BufferPool,name=mapped'.">
               Peak Pool Memory Direct / Mapped</span></th>
           <th>Disk Used</th>
           <th>Cores</th>
-          <th><span data-bs-toggle="tooltip" data-bs-placement="top" 
title="Resources currently used by each executor, such as GPU, FPGA, 
etc.">Resources</span></th>
+          <th><span data-bs-toggle="tooltip" title="Resources currently used 
by each executor, such as GPU, FPGA, etc.">Resources</span></th>
           <th>Resource Profile Id</th>
-          <th><span data-bs-toggle="tooltip" data-bs-placement="top" 
title="Number of tasks currently executing. Darker shading highlights executors 
with more active tasks.">Active Tasks</span></th>
-          <th><span data-bs-toggle="tooltip" data-bs-placement="top" 
title="Number of tasks that have failed on this executor. Darker shading 
highlights executors with a high proportion of failed tasks.">Failed 
Tasks</span></th>
+          <th><span data-bs-toggle="tooltip" title="Number of tasks currently 
executing. Darker shading highlights executors with more active tasks.">Active 
Tasks</span></th>
+          <th><span data-bs-toggle="tooltip" title="Number of tasks that have 
failed on this executor. Darker shading highlights executors with a high 
proportion of failed tasks.">Failed Tasks</span></th>
           <th>Complete Tasks</th>
           <th>Total Tasks</th>
           <th>
-            <span data-bs-toggle="tooltip" data-bs-placement="top"
+            <span data-bs-toggle="tooltip"
                   title="Shaded red when garbage collection (GC) time is over 
10% of task time">
               Task Time (GC Time)
             </span>
           </th>
-          <th><span data-bs-toggle="tooltip" data-bs-placement="top"
+          <th><span data-bs-toggle="tooltip"
                     title="Bytes and records read from Hadoop or from Spark 
storage.">Input</span></th>
           <th>
-            <span data-bs-toggle="tooltip" data-bs-placement="top"
+            <span data-bs-toggle="tooltip"
                   title="Total shuffle bytes and records read (includes both 
data read locally and data read from remote executors).">
               Shuffle Read</span></th>
           <th>
-            <span data-bs-toggle="tooltip" data-bs-placement="top"
+            <span data-bs-toggle="tooltip"
                   title="Bytes and records written to disk in order to be read 
by a shuffle in a future stage.">
               Shuffle Write</span></th>
           <th>Logs</th>
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/historypage-template.html 
b/core/src/main/resources/org/apache/spark/ui/static/historypage-template.html
index a780459fee1f..27daf08fed12 100644
--- 
a/core/src/main/resources/org/apache/spark/ui/static/historypage-template.html
+++ 
b/core/src/main/resources/org/apache/spark/ui/static/historypage-template.html
@@ -20,56 +20,56 @@
   <thead>
     <tr>
       <th>
-        <span data-bs-toggle="tooltip" data-bs-placement="top" title="Spark 
version of this application.">
+        <span data-bs-toggle="tooltip" title="Spark version of this 
application.">
           Version
         </span>
       </th>
       <th>
-        <span data-bs-toggle="tooltip" data-bs-placement="top" title="ID of 
this application.">
+        <span data-bs-toggle="tooltip" title="ID of this application.">
           App ID
         </span>
       </th>
       <th>
-        <span data-bs-toggle="tooltip" data-bs-placement="top" title="Name of 
this application.">
+        <span data-bs-toggle="tooltip" title="Name of this application.">
           App Name
         </span>
       </th>
       {{#hasMultipleAttempts}}
       <th>
-        <span data-bs-toggle="tooltip" data-bs-placement="top" title="The 
attempt ID of this application since one application might be launched several 
times">
+        <span data-bs-toggle="tooltip" title="The attempt ID of this 
application since one application might be launched several times">
           Attempt ID
         </span>
       </th>
       {{/hasMultipleAttempts}}
       <th>
-        <span data-bs-toggle="tooltip" data-bs-placement="top" title="Started 
time of this application.">
+        <span data-bs-toggle="tooltip" title="Started time of this 
application.">
           Started
         </span>
       </th>
       {{#showCompletedColumns}}
       <th>
-        <span data-bs-toggle="tooltip" data-bs-placement="top" title="The 
completed time of this application.">
+        <span data-bs-toggle="tooltip" title="The completed time of this 
application.">
           Completed
         </span>
       </th>
       <th>
-        <span data-bs-toggle="tooltip" data-bs-placement="top" title="The 
duration time of this application.">
+        <span data-bs-toggle="tooltip" title="The duration time of this 
application.">
           Duration
         </span>
       </th>
       {{/showCompletedColumns}}
       <th>
-        <span data-bs-toggle="tooltip" data-bs-placement="top" title="The 
Spark user of this application">
+        <span data-bs-toggle="tooltip" title="The Spark user of this 
application">
           Spark User
         </span>
       </th>
       <th>
-        <span data-bs-toggle="tooltip" data-bs-placement="top" title="The 
timestamp of the last updating on this application">
+        <span data-bs-toggle="tooltip" title="The timestamp of the last 
updating on this application">
           Last Updated
         </span>
       </th>
       <th>
-        <span data-bs-toggle="tooltip" data-bs-placement="top" title="Download 
the event log for this application">
+        <span data-bs-toggle="tooltip" title="Download the event log for this 
application">
           Event Log
         </span>
       </th>
diff --git a/core/src/main/resources/org/apache/spark/ui/static/stagepage.js 
b/core/src/main/resources/org/apache/spark/ui/static/stagepage.js
index 90ec6a74f194..8550ae74a466 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/stagepage.js
+++ b/core/src/main/resources/org/apache/spark/ui/static/stagepage.js
@@ -28,7 +28,6 @@ export {setTaskThreadDumpEnabled};
 
 function setTooltip(selector, text) {
   $(selector).attr("data-bs-toggle", "tooltip")
-    .attr("data-bs-placement", "top")
     .attr("title", text);
 }
 
diff --git 
a/core/src/main/resources/org/apache/spark/ui/static/stagespage-template.html 
b/core/src/main/resources/org/apache/spark/ui/static/stagespage-template.html
index ab911ea77988..283782719555 100644
--- 
a/core/src/main/resources/org/apache/spark/ui/static/stagespage-template.html
+++ 
b/core/src/main/resources/org/apache/spark/ui/static/stagespage-template.html
@@ -64,7 +64,7 @@ limitations under the License.
                 <th>Killed Tasks</th>
                 <th>Succeeded Tasks</th>
                 <th>
-          <span data-bs-toggle="tooltip" data-bs-placement="top"
+          <span data-bs-toggle="tooltip"
                 title="Shows if this executor has been excluded by the 
scheduler due to task failures.">
             Excluded</span>
                 </th>
diff --git a/core/src/main/scala/org/apache/spark/ui/UIUtils.scala 
b/core/src/main/scala/org/apache/spark/ui/UIUtils.scala
index fc44636c5998..d12a7a84daad 100644
--- a/core/src/main/scala/org/apache/spark/ui/UIUtils.scala
+++ b/core/src/main/scala/org/apache/spark/ui/UIUtils.scala
@@ -546,14 +546,16 @@ private[spark] object UIUtils extends Logging {
 
   def tooltip(text: String, position: String): Seq[Node] = {
     <sup>
-      (<a data-bs-toggle="tooltip" data-bs-placement={position} 
title={text}>?</a>)
+      (<a data-bs-toggle="tooltip" title={text}>?</a>)
     </sup>
   }
 
   /** Wrap content in a span with a Bootstrap 5 tooltip. */
   def tooltipSpan(content: Seq[Node], text: String,
       placement: String = "top"): Seq[Node] = {
-    <span data-bs-toggle="tooltip" data-bs-placement={placement} title={text}>
+    val bsPlacement = if (placement == "top") null else placement
+    <span data-bs-toggle="tooltip"
+        data-bs-placement={bsPlacement} title={text}>
       {content}
     </span>
   }
@@ -561,7 +563,9 @@ private[spark] object UIUtils extends Logging {
   /** Create a link with a Bootstrap 5 tooltip. */
   def tooltipLink(content: Seq[Node], text: String,
       placement: String = "top"): Seq[Node] = {
-    <a data-bs-toggle="tooltip" data-bs-placement={placement} title={text}>
+    val bsPlacement = if (placement == "top") null else placement
+    <a data-bs-toggle="tooltip"
+        data-bs-placement={bsPlacement} title={text}>
       {content}
     </a>
   }
diff --git a/core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala 
b/core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala
index 53f81b01a1a4..7234d13cec77 100644
--- a/core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala
+++ b/core/src/main/scala/org/apache/spark/ui/jobs/AllJobsPage.scala
@@ -105,7 +105,7 @@ private[ui] class AllJobsPage(parent: JobsTab, store: 
AppStatusStore) extends We
            |  'start': new Date(${submissionTime}),
            |  'end': new Date(${completionTime}),
            |  'content': '<div class="application-timeline-content"' +
-           |     'data-bs-html="true" data-bs-placement="top" 
data-bs-toggle="tooltip"' +
+           |     'data-bs-html="true" data-bs-toggle="tooltip"' +
            |     'data-bs-title="${jsEscapedDescForTooltip} (Job 
${jobId})<br>' +
            |     'Status: ${status}<br>' +
            |     'Submitted: ${UIUtils.formatDate(new Date(submissionTime))}' +
@@ -136,7 +136,7 @@ private[ui] class AllJobsPage(parent: JobsTab, store: 
AppStatusStore) extends We
            |  'group': 'executors',
            |  'start': new Date(${e.addTime.getTime()}),
            |  'content': '<div class="executor-event-content"' +
-           |    'data-bs-toggle="tooltip" data-bs-placement="top"' +
+           |    'data-bs-toggle="tooltip"' +
            |    'data-bs-title="Executor ${e.id}<br>' +
            |    'Added at ${UIUtils.formatDate(e.addTime)}"' +
            |    'data-bs-html="true">Executor ${e.id} added</div>'
@@ -152,7 +152,7 @@ private[ui] class AllJobsPage(parent: JobsTab, store: 
AppStatusStore) extends We
              |  'group': 'executors',
              |  'start': new Date(${removeTime.getTime()}),
              |  'content': '<div class="executor-event-content"' +
-             |    'data-bs-toggle="tooltip" data-bs-placement="top"' +
+             |    'data-bs-toggle="tooltip"' +
              |    'data-bs-title="Executor ${e.id}<br>' +
              |    'Removed at ${UIUtils.formatDate(removeTime)}' +
              |    '${
diff --git a/core/src/main/scala/org/apache/spark/ui/jobs/JobPage.scala 
b/core/src/main/scala/org/apache/spark/ui/jobs/JobPage.scala
index 77869163c8d0..30e0f678de78 100644
--- a/core/src/main/scala/org/apache/spark/ui/jobs/JobPage.scala
+++ b/core/src/main/scala/org/apache/spark/ui/jobs/JobPage.scala
@@ -87,7 +87,7 @@ private[ui] class JobPage(parent: JobsTab, store: 
AppStatusStore) extends WebUIP
          |  'start': new Date(${submissionTime}),
          |  'end': new Date(${completionTime}),
          |  'content': '<div class="job-timeline-content" 
data-bs-toggle="tooltip"' +
-         |   'data-bs-placement="top" data-bs-html="true"' +
+         |   'data-bs-html="true"' +
          |   'data-bs-title="${jsEscapedNameForTooltip} (Stage 
${stageId}.${attemptId})<br>' +
          |   'Status: ${status.toUpperCase(Locale.ROOT)}<br>' +
          |   'Submitted: ${UIUtils.formatDate(submissionTime)}' +
@@ -116,7 +116,7 @@ private[ui] class JobPage(parent: JobsTab, store: 
AppStatusStore) extends WebUIP
            |  'group': 'executors',
            |  'start': new Date(${e.addTime.getTime()}),
            |  'content': '<div class="executor-event-content"' +
-           |    'data-bs-toggle="tooltip" data-bs-placement="top"' +
+           |    'data-bs-toggle="tooltip"' +
            |    'data-bs-title="Executor ${e.id}<br>' +
            |    'Added at ${UIUtils.formatDate(e.addTime)}"' +
            |    'data-bs-html="true">Executor ${e.id} added</div>'
@@ -132,7 +132,7 @@ private[ui] class JobPage(parent: JobsTab, store: 
AppStatusStore) extends WebUIP
              |  'group': 'executors',
              |  'start': new Date(${removeTime.getTime()}),
              |  'content': '<div class="executor-event-content"' +
-             |    'data-bs-toggle="tooltip" data-bs-placement="top"' +
+             |    'data-bs-toggle="tooltip"' +
              |    'data-bs-title="Executor ${e.id}<br>' +
              |    'Removed at ${UIUtils.formatDate(removeTime)}' +
              |    '${
diff --git a/core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala 
b/core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala
index d40ba9b1446c..264a57efff0c 100644
--- a/core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala
+++ b/core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala
@@ -361,7 +361,7 @@ private[ui] class StagePage(parent: StagesTab, store: 
AppStatusStore) extends We
                |'className': 'task task-assignment-timeline-object',
                |'group': '$executorId',
                |'content': '<div class="task-assignment-timeline-content"
-                 |data-bs-toggle="tooltip" data-bs-placement="top"
+                 |data-bs-toggle="tooltip"
                  |data-bs-html="true" data-bs-container="body"
                  |data-bs-title="${"Task " + index + " (attempt " + attempt + 
")"}<br>
                  |Status: ${taskInfo.status}<br>
diff --git a/core/src/test/scala/org/apache/spark/ui/UIUtilsSuite.scala 
b/core/src/test/scala/org/apache/spark/ui/UIUtilsSuite.scala
index 7e497d60fde8..8da6c9c1a555 100644
--- a/core/src/test/scala/org/apache/spark/ui/UIUtilsSuite.scala
+++ b/core/src/test/scala/org/apache/spark/ui/UIUtilsSuite.scala
@@ -165,7 +165,7 @@ class UIUtilsSuite extends SparkFunSuite {
         <thead>
           <th width="" class="">{header(0)}</th>
           <th width="" class="">
-              <span data-bs-toggle="tooltip" data-bs-placement="top" 
title="tooltip">
+              <span data-bs-toggle="tooltip" title="tooltip">
                 {header(1)}
               </span>
           </th>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to