MediaWiki:Common.js: Difference between revisions
No edit summary |
No edit summary |
||
| Line 1,267: | Line 1,267: | ||
try { JSON.parse(readLS(LS_TEEKA_KEY) || '[]').forEach(function (s) { selectedTeekaSlugs[s] = true; }); } catch (e) { } | try { JSON.parse(readLS(LS_TEEKA_KEY) || '[]').forEach(function (s) { selectedTeekaSlugs[s] = true; }); } catch (e) { } | ||
var teekaIndex = null; | var teekaIndex = null; | ||
var | var availableList = []; // [{slug, title, subItems: [{slug, title}, ...]}] | ||
var checkboxesBySlug = {}; | var checkboxesBySlug = {}; | ||
var readyCallbacks = []; | var readyCallbacks = []; | ||
| Line 1,301: | Line 1,301: | ||
// matched by real href rather than any assumed list markup, since | // matched by real href rather than any assumed list markup, since | ||
// that markup isn't something this script controls. | // that markup isn't something this script controls. | ||
// CHANGED: checkbox is now wrapped in a .gr-teeka-cb-wrap span for | |||
// reliable vertical centering (confirmed directly - screenshot - | |||
// that a bare checkbox relying on vertical-align alone rendered | |||
// oversized/misaligned), and the enclosing <li> (if any) gets | |||
// .gr-teeka-list-item so its bullet can be removed via CSS, since a | |||
// checkbox is now the line's own visual marker. | |||
function augmentExistingTeekaLinks(subpageTitles, docs) { | function augmentExistingTeekaLinks(subpageTitles, docs) { | ||
var slugByPath = {}; | var slugByPath = {}; | ||
| Line 1,317: | Line 1,323: | ||
var slug = slugByPath[path]; | var slug = slugByPath[path]; | ||
if (!slug || this.closest('.gr-injected-teeka-group')) return; | if (!slug || this.closest('.gr-injected-teeka-group')) return; | ||
var li = this.closest('li'); | |||
if (li) li.classList.add('gr-teeka-list-item'); | |||
var $wrap = $('<span>').addClass('gr-teeka-cb-wrap'); | |||
var $cb = $('<input>').attr({ type: 'checkbox' }).addClass('gr-teeka-inline-checkbox').prop('checked', !!selectedTeekaSlugs[slug]); | var $cb = $('<input>').attr({ type: 'checkbox' }).addClass('gr-teeka-inline-checkbox').prop('checked', !!selectedTeekaSlugs[slug]); | ||
$(this).before($ | $wrap.append($cb); | ||
$(this).before($wrap); | |||
registerCheckbox(slug, $cb); | registerCheckbox(slug, $cb); | ||
$cb.on('change', function () { toggleSlug(slug, $cb.is(':checked')); }); | $cb.on('change', function () { toggleSlug(slug, $cb.is(':checked')); }); | ||
| Line 1,376: | Line 1,386: | ||
return !!p.doc; | return !!p.doc; | ||
}); | }); | ||
var | var topDocs = pairs.map(function (p) { return p.doc; }); | ||
teekaIndex = buildTeekaInMoolaIndex( | |||
// NEW: sub-commentaries (tippanis) - a teeka doc declares | |||
// its own children via doc.related (an array of slugs, | |||
// matching the same field this session's own generator | |||
// already writes into new JSON docs). Only the ASK here | |||
// is to show these as sub-categories in the options list | |||
// and gate their visibility on the parent being checked | |||
// - so this only needs one more level of fetching, not | |||
// unbounded recursion. | |||
var relatedSlugs = []; | |||
topDocs.forEach(function (d) { (d.doc.related || []).forEach(function (s) { relatedSlugs.push(s); }); }); | |||
var uniqueRelated = relatedSlugs.filter(function (s, i) { return relatedSlugs.indexOf(s) === i; }); | |||
function finishInit(subDocsBySlug) { | |||
var allDocs = topDocs.slice(); | |||
Object.keys(subDocsBySlug).forEach(function (slug) { if (subDocsBySlug[slug]) allDocs.push(subDocsBySlug[slug]); }); | |||
teekaIndex = buildTeekaInMoolaIndex(allDocs); | |||
availableList = topDocs.map(function (d) { | |||
var subItems = (d.doc.related || []) | |||
.map(function (s) { return subDocsBySlug[s]; }) | |||
.filter(Boolean) | |||
.map(function (sd) { return { slug: sd.doc.slug || sd._title, title: sd.doc.title || sd._title }; }); | |||
return { slug: d.doc.slug || d._title, title: d.doc.title || d._title, subItems: subItems }; | |||
}); | |||
var augmented = augmentExistingTeekaLinks(pairs.map(function (p) { return p.title; }), topDocs); | |||
if (augmented.length) observeInlineVisibility(augmented.map(function (a) { return a.el; })); | |||
else inlineListVisible = false; // no inline checkboxes exist - toolbar control should always show as the only access point | |||
if (Object.keys(selectedTeekaSlugs).length) renderInterleave(); | |||
isReady = true; | |||
readyCallbacks.forEach(function (cb) { cb(availableList); }); | |||
if (inlineListVisible !== null) visibilityCallbacks.forEach(function (cb) { cb(inlineListVisible); }); | |||
} | |||
if (!uniqueRelated.length) { finishInit({}); return; } | |||
$.when.apply($, uniqueRelated.map(fetchTeekaJson)).then(function () { | |||
var subFetched = arguments.length === 1 ? [arguments[0]] : Array.prototype.slice.call(arguments); | |||
var subDocsBySlug = {}; | |||
uniqueRelated.forEach(function (slug, i) { | |||
if (!subFetched[i]) console.warn('[grTeekaInterleave] Could not load sub-commentary JSON:' + slug); | |||
subDocsBySlug[slug] = subFetched[i]; | |||
}); | |||
finishInit(subDocsBySlug); | |||
}); | |||
}); | }); | ||
}); | }); | ||
| Line 1,391: | Line 1,435: | ||
window.grTeekaInterleave = { | window.grTeekaInterleave = { | ||
onReady: function (cb) { if (isReady) cb( | onReady: function (cb) { if (isReady) cb(availableList); else readyCallbacks.push(cb); }, | ||
onChange: function (cb) { changeCallbacks.push(cb); }, | onChange: function (cb) { changeCallbacks.push(cb); }, | ||
onVisibilityChange: function (cb) { visibilityCallbacks.push(cb); if (inlineListVisible !== null) cb(inlineListVisible); }, | onVisibilityChange: function (cb) { visibilityCallbacks.push(cb); if (inlineListVisible !== null) cb(inlineListVisible); }, | ||