Michael Rabinovich Cursor commited on
Commit
6905c70
·
1 Parent(s): 528723d

leaderboard: fit tasks iframe to content (kill blank space)

Browse files

The Tasks browser iframe was a fixed 90vh, so a short detail card left a large
blank gap above the Refresh button. Mirror the gallery's approach: size the
iframe to the document height on load / resize / view switch (and via a
ResizeObserver for lazy render images), so it shrinks to the detail card and
grows for the summary grid.

Co-authored-by: Cursor <cursoragent@cursor.com>

Files changed (1) hide show
  1. tasks.py +22 -0
tasks.py CHANGED
@@ -503,10 +503,22 @@ let currentIdx = -1;
503
  const total = document.querySelectorAll('.fixture-card').length;
504
  let query = '', typeFilter = 'all';
505
 
 
 
 
 
 
 
 
 
 
 
 
506
  function taskImgFail(img) {
507
  const view = img.closest('.view');
508
  if (view) { view.style.display = 'none'; return; }
509
  img.style.display = 'none';
 
510
  }
511
 
512
  // Live grid filter: the segmented control filters by type, the search
@@ -534,6 +546,7 @@ function applyFilter() {
534
  if (empty) empty.style.display = shown ? 'none' : '';
535
  const note = document.getElementById('countNote');
536
  if (note) note.textContent = shown + ' of ' + total + ' shown';
 
537
  }
538
 
539
  (function wireControls() {
@@ -557,6 +570,7 @@ function showSummary() {
557
  document.getElementById('summary-view').style.display = '';
558
  document.getElementById('detail-view').style.display = 'none';
559
  currentIdx = -1;
 
560
  }
561
 
562
  function showDetail(idx) {
@@ -568,6 +582,7 @@ function showDetail(idx) {
568
  currentIdx = idx;
569
  updateNav();
570
  window.scrollTo(0, 0);
 
571
  }
572
 
573
  function updateNav() {
@@ -607,4 +622,11 @@ function openHashTarget() {
607
  }
608
  openHashTarget();
609
  window.addEventListener('hashchange', openHashTarget);
 
 
 
 
 
 
 
610
  """
 
503
  const total = document.querySelectorAll('.fixture-card').length;
504
  let query = '', typeFilter = 'all';
505
 
506
+ // Size the embedding iframe to the document height so a short detail card
507
+ // doesn't leave a tall blank gap (the host iframe is otherwise a fixed
508
+ // height). srcdoc iframes are same-origin, so frameElement is readable; a
509
+ // no-op if it isn't (keeps the CSS fallback height).
510
+ function fitFrame() {
511
+ try {
512
+ const fe = window.frameElement;
513
+ if (fe) fe.style.height = Math.ceil(document.documentElement.scrollHeight) + 'px';
514
+ } catch (e) { /* sandboxed -> keep fallback height */ }
515
+ }
516
+
517
  function taskImgFail(img) {
518
  const view = img.closest('.view');
519
  if (view) { view.style.display = 'none'; return; }
520
  img.style.display = 'none';
521
+ fitFrame();
522
  }
523
 
524
  // Live grid filter: the segmented control filters by type, the search
 
546
  if (empty) empty.style.display = shown ? 'none' : '';
547
  const note = document.getElementById('countNote');
548
  if (note) note.textContent = shown + ' of ' + total + ' shown';
549
+ fitFrame();
550
  }
551
 
552
  (function wireControls() {
 
570
  document.getElementById('summary-view').style.display = '';
571
  document.getElementById('detail-view').style.display = 'none';
572
  currentIdx = -1;
573
+ fitFrame();
574
  }
575
 
576
  function showDetail(idx) {
 
582
  currentIdx = idx;
583
  updateNav();
584
  window.scrollTo(0, 0);
585
+ fitFrame();
586
  }
587
 
588
  function updateNav() {
 
622
  }
623
  openHashTarget();
624
  window.addEventListener('hashchange', openHashTarget);
625
+
626
+ // Keep the iframe height matched to the content: on first paint, on resize,
627
+ // and whenever layout changes (lazy render images loading, view switches).
628
+ fitFrame();
629
+ window.addEventListener('load', fitFrame);
630
+ window.addEventListener('resize', fitFrame);
631
+ if (window.ResizeObserver) new ResizeObserver(fitFrame).observe(document.body);
632
  """