Content deleted Content added
Polygnotus (talk | contribs) ←Created page with '// Wikipedia API Explorer Module const WikipediaAPI = { // Fetch Wikipedia userinfo data async fetchUserInfo() { const params = { action: 'query', meta: 'userinfo', uiprop: 'options', format: 'json', origin: '*' }; const url = 'https://en.wikipedia.org/w/api.php?' + new URLSearchParams(params); try { const response = await fetch(...' |
Polygnotus (talk | contribs) No edit summary |
||
(2 intermediate revisions by the same user not shown) | |||
Line 1:
// Wikipedia UserOptions API Explorer
$(document).ready(function() {
// Add link to Tools menu on all pages
mw.hook('wikipage.content').add(function() {
mw.loader.using(['mediawiki.util'], function() {
'p-tb', // Target portlet ID (Tools menu)
mw.config.get('wgServer') + '/wiki/Special:BlankPage/UserOptions', // Link URL
'User Options API', // Link text
't-useroptions-api', // Link ID
'Explore user options via MediaWiki API' // Tooltip
);
}
// Only run the main interface if we're on the specific page
if (mw.config.get('wgCanonicalSpecialPageName') === 'Blankpage' &&
mw.config.get('wgPageName') === 'Special:BlankPage/UserOptions') {
$('#firstHeading').text('User Options API Explorer');
var html = '<div id="useroptions-container">' +
'<div class="api-info" style="background: #e8f4f8; border: 1px solid #bee5eb; border-radius: 5px; padding: 15px; margin-bottom: 20px;">' +
'<strong>API Endpoint:</strong> ' + mw.config.get('wgServer') + '/w/api.php<br>' +
'<strong>Parameters:</strong> action=query, meta=userinfo, uiprop=options, format=json' +
'</div>' +
'<div class="controls" style="margin-bottom: 20px;">' +
'<button id="fetchBtn" class="btn btn-primary">Fetch User Options</button>' +
'<button id="expandBtn" class="btn btn-success">Expand All</button>' +
'<button id="collapseBtn" class="btn btn-danger">Collapse All</button>' +
'</div>' +
'<div id="status"></div>' +
'<div id="jsonResult"></div>' +
'</div>';
// Wikipedia UserOptions API Module
var UserOptionsAPI = {
fetchUserOptions: function() {
var params = {
action: 'query',
meta: 'userinfo',
uiprop: 'options',
format: 'json'
};
return new mw.Api().get(params);
},
createJSONTree: function(containerId, data) {
var container = document.getElementById(containerId);
container.innerHTML = '';
tree.appendChild(this.createNode('response', data, 0));
createNode: function(key, value, depth) {
var node = document.createElement('div');
var self = this;
node.innerHTML = '<span class="json-key">' + key + ':</span> <span class="json-null">null</span>';
node.innerHTML = '<span class="json-key">' + key + ':</span> <span class="json-string">"' + this.escapeHtml(value) + '"</span>';
} else if (typeof value === 'number') {
node.innerHTML = '<span class="json-key">' + key + ':</span> <span class="json-number">' + value + '</span>';
} else if (typeof value === 'boolean') {
node.innerHTML = '<span class="json-key">' + key + ':</span> <span class="json-boolean">' + value + '</span>';
} else if (Array.isArray(value)) {
var toggleId = 'toggle-' + Date.now() + '-' + Math.random().toString().replace('.', '');
var toggle = document.createElement('span');
toggle.className = 'json-toggle';
toggle.textContent = '▼';
toggle.id = toggleId;
var keySpan = document.createElement('span');
keySpan.className = 'json-key';
keySpan.textContent = key + ':';
var summary = document.createElement('span');
summary.className = 'json-collapsed';
summary.textContent = ' [' + value.length + ' items]';
node.appendChild(toggle);
node.appendChild(keySpan);
node.appendChild(summary);
var children = document.createElement('div');
children.className = 'json-children';
for (var i = 0; i < value.length; i++) {
children.appendChild(this.createNode('[' + i + ']', value[i], depth + 1));
}
node.appendChild(children);
// Create closure to preserve toggleId
(function(id) {
toggle.onclick = function() {
self.toggleNode(id);
};
})(toggleId);
} else if (typeof value === 'object') {
var keys = Object.keys(value);
var toggleId = 'toggle-' + Date.now() + '-' + Math.random();
var toggle = document.createElement('span');
toggle.className = 'json-toggle';
toggle.textContent = '▼';
toggle.id = toggleId;
var keySpan = document.createElement('span');
keySpan.className = 'json-key';
keySpan.textSize = key + ':';
var summary = document.createElement('span');
summary.className = 'json-collapsed';
summary.textContent = ' {' + keys.length + ' properties}';
node.appendChild(toggle);
node.appendChild(keySpan);
node.appendChild(summary);
var children = document.createElement('div');
children.className = 'json-children';
for (var j = 0; j < keys.length; j++) {
var objKey = keys[j];
children.appendChild(this.createNode(objKey, value[objKey], depth + 1));
}
node.appendChild(children);
toggle.onclick = function() {
self.toggleNode(toggleId);
};
}
return node;
},
toggleNode: function(toggleId) {
var toggle = document.getElementById(toggleId);
console.error('Toggle element not found:', toggleId);
}
var children = toggle.parentNode.querySelector('.json-children');
if (!children) {
console.error('Children element not found for toggle:', toggleId);
return;
}
if (children.classList.contains('hidden')) {
children.classList.remove('hidden');
toggle.textContent = '▼';
} else {
children.classList.add('hidden');
toggle.textContent = '▶';
}
},
expandAll: function(containerId) {
var container = document.getElementById(containerId);
for (var i = 0; i < toggles.length; i++) {
var toggle = toggles[i];
if (children) {
children.classList.remove('hidden');
collapseAll: function(containerId) {
var toggles = container.querySelectorAll('.json-toggle');
var toggle = toggles[i];
var children = toggle.parentNode.querySelector('.json-children');
}
}
},
escapeHtml: function(text) {
var div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
},
addStyles: function() {
if (document.getElementById('json-tree-styles')) return;
var style = document.createElement('style');
style.id = 'json-tree-styles';
style.textContent =
'.json-tree {' +
'font-family: "Courier New", monospace;' +
'background: #f8f9fa;' +
'border: 1px solid #e1e5e9;' +
'border-radius: 5px;' +
'padding: 15px;' +
'margin: 10px 0;' +
'overflow-x: auto;' +
'max-height: 600px;' +
'overflow-y: auto;' +
'}' +
'.json-node {' +
'margin: 2px 0;' +
'}' +
'.json-key {' +
'color: #0645ad;' +
'font-weight: bold;' +
'}' +
'.json-string {' +
'color: #d73a49;' +
'}' +
'.json-number {' +
'color: #005cc5;' +
'}' +
'.json-boolean {' +
'color: #6f42c1;' +
'}' +
'.json-null {' +
'color: #6a737d;' +
'}' +
'.json-toggle {' +
'cursor: pointer;' +
'user-select: none;' +
'display: inline-block;' +
'width: 20px;' +
'color: #666;' +
'font-weight: bold;' +
'}' +
'.json-toggle:hover {' +
'color: #0645ad;' +
'}' +
'.json-collapsed {' +
'color: #666;' +
'}' +
'.json-children {' +
'margin-left: 20px;' +
'border-left: 1px solid #e1e5e9;' +
'padding-left: 10px;' +
'}' +
'.json-children.hidden {' +
'display: none;' +
'}' +
'.btn {' +
'display: inline-block;' +
'padding: 6px 12px;' +
'margin: 0 5px 5px 0;' +
'font-size: 14px;' +
'font-weight: normal;' +
'line-height: 1.42857143;' +
'text-align: center;' +
'white-space: nowrap;' +
'vertical-align: middle;' +
'cursor: pointer;' +
'border: 1px solid transparent;' +
'border-radius: 4px;' +
'text-decoration: none;' +
'}' +
'.btn-primary {' +
'color: #fff;' +
'background-color: #0645ad;' +
'border-color: #0645ad;' +
'}' +
'.btn-success {' +
'color: #fff;' +
'background-color: #28a745;' +
'border-color: #28a745;' +
'}' +
'.btn-danger {' +
'color: #fff;' +
'background-color: #dc3545;' +
'border-color: #dc3545;' +
'}' +
'.btn:hover {' +
'opacity: 0.8;' +
'}';
document.head.appendChild(style);
},
displayUserOptions: function(containerId) {
var statusDiv = document.getElementById('status');
var fetchBtn = document.getElementById('fetchBtn');
var self = this;
fetchBtn.disabled = true;
statusDiv.innerHTML = '<div style="color: #666; font-style: italic;">Fetching user options...</div>';
this.fetchUserOptions().done(function(data) {
statusDiv.innerHTML = '<div style="color: #28a745;">✓ User options loaded successfully</div>';
self.createJSONTree(containerId, data);
fetchBtn.disabled = false;
}).fail(function(error) {
statusDiv.innerHTML = '<div style="color: #d33; background: #ffeaea; padding: 10px; border-radius: 5px;">Error: ' + error + '</div>';
console.error('Fetch error:', error);
fetchBtn.disabled = false;
});
}
};
// Event listeners (only when on the correct page)
$('#fetchBtn').on('click', function() {
UserOptionsAPI.displayUserOptions('jsonResult');
});
$('#expandBtn').on('click', function() {
UserOptionsAPI.expandAll('jsonResult');
});
$('#collapseBtn').on('click', function() {
UserOptionsAPI.collapseAll('jsonResult');
});
// Auto-load on page load
UserOptionsAPI.displayUserOptions('jsonResult');
}
});
|