Article Overview: Difference between revisions

From AlphaX Wiki
Jump to navigation Jump to search
Created page with "<div id="article-overview-wrapper"> <div style="margin-bottom:12px;"> <button id="download-csv-btn" style="background-color:#e07b00;color:#fff;padding:8px 18px;border:none;border-radius:4px;font-size:14px;font-weight:bold;cursor:pointer;">⬇ Download CSV</button> <span id="overview-status" style="margin-left:14px;font-size:13px;color:#aaa;"></span> </div> <table id="article-overview-table" style="width:100%;border-collapse:collapse;font-size:13px;"> <thead> <tr style=..."
 
No edit summary
Line 1: Line 1:
<div id="article-overview-wrapper">
== Article Overview ==


<div style="margin-bottom:12px;">
This page displays all wiki articles organised by category and subcategory, including word count and focus area. Use the button below to download the full list as a CSV file.
<button id="download-csv-btn" style="background-color:#e07b00;color:#fff;padding:8px 18px;border:none;border-radius:4px;font-size:14px;font-weight:bold;cursor:pointer;">⬇ Download CSV</button>
 
<span id="overview-status" style="margin-left:14px;font-size:13px;color:#aaa;"></span>
<div id="article-overview-wrapper" style="margin-top:16px;">
 
<div style="margin-bottom:14px;">
<button id="download-csv-btn" style="background-color:#e07b00;color:#fff;padding:9px 20px;border:none;border-radius:5px;font-size:14px;font-weight:bold;cursor:pointer;letter-spacing:0.3px;">⬇ Download CSV</button>
<span id="overview-status" style="margin-left:14px;font-size:13px;color:#aaa;vertical-align:middle;"></span>
</div>
</div>


<table id="article-overview-table" style="width:100%;border-collapse:collapse;font-size:13px;">
<table id="article-overview-table" style="width:100%;border-collapse:collapse;font-size:13px;">
<thead>
<thead>
<tr style="background-color:#2a2a2a;color:#f0a500;">
<tr style="background-color:#2a2a2a;color:#f0a500;text-align:left;">
<th style="padding:8px 10px;border:1px solid #444;text-align:left;">Category</th>
<th style="padding:9px 12px;border:1px solid #444;">Category</th>
<th style="padding:8px 10px;border:1px solid #444;text-align:left;">Subcategory</th>
<th style="padding:9px 12px;border:1px solid #444;">Subcategory</th>
<th style="padding:8px 10px;border:1px solid #444;text-align:left;">Title</th>
<th style="padding:9px 12px;border:1px solid #444;">Title</th>
<th style="padding:8px 10px;border:1px solid #444;text-align:right;">Words</th>
<th style="padding:9px 12px;border:1px solid #444;text-align:right;">Words</th>
<th style="padding:8px 10px;border:1px solid #444;text-align:left;">Focus</th>
<th style="padding:9px 12px;border:1px solid #444;">Focus</th>
</tr>
</tr>
</thead>
</thead>
<tbody id="article-overview-body">
<tbody id="article-overview-body">
<tr><td colspan="5" style="padding:10px;text-align:center;color:#aaa;">Loading data…</td></tr>
<tr><td colspan="5" style="padding:12px;text-align:center;color:#aaa;font-style:italic;">Loading articles… please wait.</td></tr>
</tbody>
</tbody>
</table>
</table>


</div>
</div>
<script>
(function() {
  var apiBase = '/api.php';
  var allRows = [];
  function fetchAllCategories(continueParam, accumulated, callback) {
    var url = apiBase + '?action=query&list=allcategories&aclimit=500&format=json&origin=*';
    if (continueParam) url += '&accontinue=' + encodeURIComponent(continueParam);
    fetch(url)
      .then(function(r){ return r.json(); })
      .then(function(data) {
        var cats = data.query && data.query.allcategories ? data.query.allcategories : [];
        cats.forEach(function(c){ accumulated.push(c['*']); });
        if (data.continue && data.continue.accontinue) {
          fetchAllCategories(data.continue.accontinue, accumulated, callback);
        } else {
          callback(accumulated);
        }
      })
      .catch(function(){ callback(accumulated); });
  }
  function getCategoryMembers(catName, type, continueParam, accumulated, callback) {
    var cmtype = type || 'page|subcat';
    var url = apiBase + '?action=query&list=categorymembers&cmtitle=Category:' + encodeURIComponent(catName) + '&cmlimit=500&cmtype=' + cmtype + '&format=json&origin=*';
    if (continueParam) url += '&cmcontinue=' + encodeURIComponent(continueParam);
    fetch(url)
      .then(function(r){ return r.json(); })
      .then(function(data) {
        var members = data.query && data.query.categorymembers ? data.query.categorymembers : [];
        members.forEach(function(m){ accumulated.push(m); });
        if (data.continue && data.continue.cmcontinue) {
          getCategoryMembers(catName, type, data.continue.cmcontinue, accumulated, callback);
        } else {
          callback(accumulated);
        }
      })
      .catch(function(){ callback(accumulated); });
  }
  function getPageWordCount(pageTitle, callback) {
    var url = apiBase + '?action=query&titles=' + encodeURIComponent(pageTitle) + '&prop=revisions&rvprop=content&rvslots=main&format=json&origin=*';
    fetch(url)
      .then(function(r){ return r.json(); })
      .then(function(data) {
        var pages = data.query && data.query.pages ? data.query.pages : {};
        var pageData = Object.values(pages)[0];
        var content = pageData && pageData.revisions && pageData.revisions[0] && pageData.revisions[0].slots && pageData.revisions[0].slots.main && pageData.revisions[0].slots.main['*'] ? pageData.revisions[0].slots.main['*'] : '';
        var text = content.replace(/\[\[.*?\]\]/g,'$1').replace(/{{.*?}}/gs,'').replace(/<.*?>/g,'').replace(/[^a-zA-ZäöüÄÖÜß\s]/g,' ');
        var words = text.trim().split(/\s+/).filter(function(w){ return w.length > 0; }).length;
        callback(words);
      })
      .catch(function(){ callback(0); });
  }
  function getPageCategories(pageTitle, callback) {
    var url = apiBase + '?action=query&titles=' + encodeURIComponent(pageTitle) + '&prop=categories&cllimit=50&format=json&origin=*';
    fetch(url)
      .then(function(r){ return r.json(); })
      .then(function(data) {
        var pages = data.query && data.query.pages ? data.query.pages : {};
        var pageData = Object.values(pages)[0];
        var cats = pageData && pageData.categories ? pageData.categories.map(function(c){ return c.title.replace('Category:',''); }) : [];
        callback(cats);
      })
      .catch(function(){ callback([]); });
  }
  function buildTable() {
    var status = document.getElementById('overview-status');
    status.textContent = 'Fetching categories…';
    fetch(apiBase + '?action=query&list=allcategories&aclimit=500&format=json&origin=*')
      .then(function(r){ return r.json(); })
      .then(function(data) {
        var topCats = data.query && data.query.allcategories ? data.query.allcategories.map(function(c){ return c['*']; }) : [];
        var rows = [];
        var pending = 0;
        var totalCats = topCats.length;
        var processed = 0;
        if (totalCats === 0) {
          document.getElementById('article-overview-body').innerHTML = '<tr><td colspan="5" style="padding:10px;text-align:center;color:#aaa;">No categories found.</td></tr>';
          status.textContent = '';
          return;
        }
        function checkDone() {
          processed++;
          status.textContent = 'Loading… (' + processed + '/' + totalCats + ' categories)';
          if (processed === totalCats) {
            rows.sort(function(a,b){
              if (a.category < b.category) return -1;
              if (a.category > b.category) return 1;
              if (a.sub < b.sub) return -1;
              if (a.sub > b.sub) return 1;
              return a.title.localeCompare(b.title);
            });
            allRows = rows;
            renderTable(rows);
            status.textContent = rows.length + ' articles loaded.';
          }
        }
        topCats.forEach(function(catName) {
          getCategoryMembers(catName, 'page|subcat', null, [], function(members) {
            var pages = members.filter(function(m){ return m.ns === 0; });
            var subcats = members.filter(function(m){ return m.ns === 14; });
            if (pages.length === 0 && subcats.length === 0) {
              checkDone();
              return;
            }
            var subPending = 0;
            function trySubDone() {
              subPending--;
              if (subPending <= 0) checkDone();
            }
            // Direct pages in this category (no subcat)
            pages.forEach(function(page) {
              subPending++;
              var focus = catName;
              rows.push({ category: catName, sub: '—', title: page.title, words: '…', focus: focus, _title: page.title });
            });
            // Pages in subcategories
            subcats.forEach(function(subcat) {
              subPending++;
              var subName = subcat.title.replace('Category:','');
              getCategoryMembers(subName, 'page', null, [], function(subPages) {
                subPages.filter(function(m){ return m.ns === 0; }).forEach(function(page) {
                  subPending++;
                  rows.push({ category: catName, sub: subName, title: page.title, words: '…', focus: catName, _title: page.title });
                });
                trySubDone();
              });
            });
            if (subPending === 0) checkDone();
          });
        });
      })
      .catch(function() {
        document.getElementById('article-overview-body').innerHTML = '<tr><td colspan="5" style="padding:10px;text-align:center;color:#f00;">Error loading data.</td></tr>';
      });
  }
  function renderTable(rows) {
    var tbody = document.getElementById('article-overview-body');
    if (!rows || rows.length === 0) {
      tbody.innerHTML = '<tr><td colspan="5" style="padding:10px;text-align:center;color:#aaa;">No articles found.</td></tr>';
      return;
    }
    var html = '';
    rows.forEach(function(row, i) {
      var bg = i % 2 === 0 ? '#1a1a1a' : '#222';
      html += '<tr style="background:' + bg + ';">';
      html += '<td style="padding:6px 10px;border:1px solid #333;">' + escHtml(row.category) + '</td>';
      html += '<td style="padding:6px 10px;border:1px solid #333;">' + escHtml(row.sub) + '</td>';
      html += '<td style="padding:6px 10px;border:1px solid #333;"><a href="/wiki/' + encodeURIComponent(row.title.replace(/ /g,'_')) + '">' + escHtml(row.title) + '</a></td>';
      html += '<td style="padding:6px 10px;border:1px solid #333;text-align:right;">' + escHtml(String(row.words)) + '</td>';
      html += '<td style="padding:6px 10px;border:1px solid #333;">' + escHtml(row.focus) + '</td>';
      html += '</tr>';
    });
    tbody.innerHTML = html;
  }
  function escHtml(str) {
    return String(str).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
  }
  function downloadCSV() {
    var rows = allRows;
    if (!rows || rows.length === 0) { alert('No data to download yet. Please wait for the table to load.'); return; }
    var csv = 'Category,Subcategory,Title,Words,Focus\n';
    rows.forEach(function(row) {
      csv += [row.category, row.sub, row.title, row.words, row.focus].map(function(v){
        return '"' + String(v).replace(/"/g,'""') + '"';
      }).join(',') + '\n';
    });
    var blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
    var url = URL.createObjectURL(blob);
    var a = document.createElement('a');
    a.href = url;
    a.download = 'article-overview.csv';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  }
  document.addEventListener('DOMContentLoaded', function() {
    var btn = document.getElementById('download-csv-btn');
    if (btn) btn.addEventListener('click', downloadCSV);
    buildTable();
  });
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', function() {
      var btn = document.getElementById('download-csv-btn');
      if (btn) btn.addEventListener('click', downloadCSV);
      buildTable();
    });
  } else {
    var btn = document.getElementById('download-csv-btn');
    if (btn) btn.addEventListener('click', downloadCSV);
    buildTable();
  }
})();
</script>

Revision as of 07:14, 11 May 2026

Article Overview

This page displays all wiki articles organised by category and subcategory, including word count and focus area. Use the button below to download the full list as a CSV file.

<button id="download-csv-btn" style="background-color:#e07b00;color:#fff;padding:9px 20px;border:none;border-radius:5px;font-size:14px;font-weight:bold;cursor:pointer;letter-spacing:0.3px;">⬇ Download CSV</button>

<thead> </thead> <tbody id="article-overview-body">

</tbody>

Category Subcategory Title Words Focus
Loading articles… please wait.