Code
dictionary = data_index
function createDatasetMap(df) {
let dataArray = Array.from({ length: df[Object.keys(df)[0]].length }, (_, i) => {
return Object.fromEntries(Object.entries(df).map(([key, values]) => [key, values[i]]));
});
// Sort the array alphabetically by dataset
dataArray.sort((a, b) => a.dataset.localeCompare(b.dataset));
// Create the map from sorted array
let datasetMap = new Map();
for (let row of dataArray) {
datasetMap.set(row.dataset, row);
}
return datasetMap;
}
// Create dataset map from data_index instead of metadata
dataset_map = createDatasetMap(data_index);
viewof dataset_name = {
const allNames = Array.from(dataset_map.keys());
let selectedName = allNames[0];
// Attach list to body so it's never clipped by layout overflow
const list = document.createElement("div");
list.style.cssText = "position:fixed;z-index:99999;max-height:260px;overflow-y:auto;border:1px solid #ccc;border-radius:0 0 4px 4px;background:white;display:none;box-shadow:0 4px 12px rgba(0,0,0,0.15);";
document.body.appendChild(list);
const container = html`<div style="display:inline-block;width:400px;margin-bottom:20px;">
<label style="font-weight:600;display:block;margin-bottom:4px;">Search Dataset</label>
<div style="position:relative;">
<svg style="position:absolute;left:8px;top:50%;transform:translateY(-50%);pointer-events:none;color:#888;" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>
</svg>
<input type="text" placeholder="Type to search datasets…"
style="width:100%;padding:6px 10px 6px 28px;font-size:smaller;border:1px solid #ccc;border-radius:4px;box-sizing:border-box;" />
</div>
</div>`;
const input = container.querySelector("input");
function positionList() {
const r = input.getBoundingClientRect();
list.style.top = r.bottom + "px";
list.style.left = r.left + "px";
list.style.width = r.width + "px";
}
function renderList(filter) {
const matches = filter
? allNames.filter(n => n.toLowerCase().includes(filter.toLowerCase()))
: allNames;
list.innerHTML = "";
for (const name of matches.slice(0, 300)) {
const item = document.createElement("div");
item.textContent = name;
item.style.cssText = "padding:5px 10px;cursor:pointer;font-size:13px;border-bottom:1px solid #f0f0f0;";
item.onmousedown = (e) => {
e.preventDefault();
selectedName = name;
input.value = name;
list.style.display = "none";
container.value = selectedName;
container.dispatchEvent(new Event("input", {bubbles: true}));
};
item.onmouseenter = () => item.style.backgroundColor = "#f0f4ff";
item.onmouseleave = () => item.style.backgroundColor = "";
list.appendChild(item);
}
}
input.addEventListener("focus", () => {
input.value = "";
renderList("");
positionList();
list.style.display = "block";
});
input.addEventListener("input", (e) => {
e.stopPropagation();
renderList(input.value);
positionList();
list.style.display = "block";
});
input.addEventListener("blur", () => {
setTimeout(() => { list.style.display = "none"; input.value = selectedName; }, 150);
});
function onScroll(e) { if (list.contains(e.target)) return; list.style.display = "none"; input.value = selectedName; }
window.addEventListener("scroll", onScroll, true);
invalidation.then(() => { list.remove(); window.removeEventListener("scroll", onScroll, true); });
input.value = selectedName;
container.value = selectedName;
return container;
}
// Function to find dataset info from dictionary (fixed field name)
function findDatasetInfo(dictionary, datasetName) {
// Convert dictionary column data into array of objects
const dictionaryArray = Array.from({ length: dictionary[Object.keys(dictionary)[0]].length }, (_, i) => {
return Object.fromEntries(Object.entries(dictionary).map(([key, values]) => [key, values[i]]));
});
// Now we can use find on the array
const dictRow = dictionaryArray.find(row => row.dataset === datasetName);
return {
reference: dictRow?.reference || "Reference not available",
BibTex: dictRow?.BibTex || "BibTeX not available",
doi: dictRow?.doi
};
}
dataset_info = findDatasetInfo(dictionary, dataset_name);
// Create the display elements with reference and BibTeX
display = {
const sanitizedDatasetName = dataset_name.replace(/\./g, "_"); // Replace all dots with underscores
const url = `https://redivis.com/embed/tables/datapages.item_response_warehouse:as2e:current.${sanitizedDatasetName}`;
const container = html`<div>
<div style="margin-bottom: 20px;">
<button onclick="toggleInfo(this)" style="
padding: 8px 16px;
background-color: #4287f5;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: 500;
display: flex;
align-items: center;
gap: 5px;
transition: background-color 0.2s;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
">
<span>Show Citation Info</span>
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" style="transform: rotate(0deg); transition: transform 0.3s;">
<path d="M2 4L6 8L10 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<div style="
display: none;
margin-top: 10px;
padding: 20px;
background-color: #ffffff;
border-radius: 8px;
border: 1px solid #e1e4e8;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
">
<div style="display: flex; gap: 20px;">
<div style="flex: 1;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 5px;">
<div style="font-weight: 600; color: #24292e;">Reference</div>
<button onclick="copyText(this, 'reference')" style="
padding: 4px 12px;
background-color: #f6f8fa;
border: 1px solid #e1e4e8;
border-radius: 6px;
cursor: pointer;
font-size: 0.8em;
color: #24292e;
display: flex;
align-items: center;
gap: 4px;
transition: all 0.2s;
">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Copy
</button>
</div>
<div style="
font-size: 0.95em;
line-height: 1.6;
color: #24292e;
font-style: italic;
background-color: #f8f9fa;
padding: 12px;
border-radius: 6px;
border: 1px solid #e1e4e8;
" class="reference-text">${dataset_info.reference}</div>
</div>
<div style="flex: 1;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 5px;">
<div style="font-weight: 600; color: #24292e;">BibTeX</div>
<button onclick="copyText(this, 'bibtex')" style="
padding: 4px 12px;
background-color: #f6f8fa;
border: 1px solid #e1e4e8;
border-radius: 6px;
cursor: pointer;
font-size: 0.8em;
color: #24292e;
display: flex;
align-items: center;
gap: 4px;
transition: all 0.2s;
">
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Copy
</button>
</div>
<pre style="
margin: 0;
padding: 12px;
background-color: #f8f9fa;
border-radius: 6px;
border: 1px solid #e1e4e8;
font-size: 0.9em;
line-height: 1.5;
overflow-x: auto;
white-space: pre-wrap;
word-wrap: break-word;
color: #24292e;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;
" class="bibtex-text"></pre>
</div>
</div>
<!-- R Package Citation -->
<div style="margin-top: 20px;">
<button onclick="toggleRCitation(this)" style="
padding: 6px 12px;
background-color: #4287f5;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 0.9em;
transition: background-color 0.2s;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
">To cite using IRW's R package</button>
<div class="r-citation" style="
display: none;
margin-top: 10px;
padding: 12px;
background-color: #f8f9fa;
border-radius: 6px;
border: 1px solid #e1e4e8;
font-family: monospace;
">
<div style="
padding: 8px;
background-color: #f8f9fa;
border-left: 3px solid #4287f5;
margin-bottom: 10px;
">
> <code>irw_citation('${dataset_name}')</code>
</div>
</div>
</div>
</div>
</div>
<iframe id="myIframe" width="800" height="500" allowfullscreen style="border: 1px solid #e1e4e8; border-radius: 8px;" src="${url}"></iframe>
</div>`;
// Add toggle functions to window object
window.toggleInfo = function(button) {
const infoDiv = button.nextElementSibling;
const arrow = button.querySelector('svg');
const isVisible = infoDiv.style.display === 'block';
infoDiv.style.display = isVisible ? 'none' : 'block';
arrow.style.transform = isVisible ? 'rotate(0deg)' : 'rotate(180deg)';
button.querySelector('span').textContent = isVisible ? 'Show Citation Info' : 'Hide Citation Info';
};
window.toggleRCitation = function(button) {
const citationDiv = button.nextElementSibling;
citationDiv.style.display = citationDiv.style.display === 'none' ? 'block' : 'none';
};
// Add copy function to window object
window.copyText = function(button, type) {
const container = button.closest('div').parentElement;
const text = type === 'reference' ?
container.querySelector('.reference-text').textContent :
container.querySelector('.bibtex-text').textContent;
navigator.clipboard.writeText(text).then(() => {
const originalText = button.textContent;
button.textContent = 'Copied!';
button.style.backgroundColor = '#28a745';
button.style.borderColor = '#28a745';
button.style.color = 'white';
setTimeout(() => {
button.innerHTML = `
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M8 4v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7.242a2 2 0 0 0-.602-1.43L16.083 2.57A2 2 0 0 0 14.685 2H10a2 2 0 0 0-2 2z" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M16 18v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Copy
`;
button.style.backgroundColor = '#f6f8fa';
button.style.borderColor = '#e1e4e8';
button.style.color = '#24292e';
}, 2000);
});
};
// Update BibTeX text
const bibtexElement = container.querySelector('.bibtex-text');
if (bibtexElement) {
bibtexElement.textContent = dataset_info.BibTex || "BibTeX not available";
}
return container;
}