(function() {
var INSTANCE = ''; // same instance, relative API calls
var href = decodeURIComponent(window.location.href);
var sysIdMatch = href.match(/sys_id[=%3D]+([a-f0-9]{32})/i);
if (!sysIdMatch) { alert('Could not find a record sys_id. Open an Incident or RITM first.'); return; }
var recordSysId = sysIdMatch[1];
var tableMap = { 'sc_req_item': 'sc_req_item', 'sc_task': 'sc_task', 'change_request': 'change_request', 'incident': 'incident' };
var currentTable = 'incident';
Object.keys(tableMap).forEach(function(t) { if (href.indexOf(t) !== -1) currentTable = tableMap[t]; });
var overlay = document.createElement('div');
overlay.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.65);z-index:99999;display:flex;align-items:center;justify-content:center;font-family:sans-serif;';
var box = document.createElement('div');
box.style.cssText = 'background:#fff;border-radius:8px;padding:24px;width:500px;display:flex;flex-direction:column;box-shadow:0 4px 28px rgba(0,0,0,0.35);';
var title = document.createElement('div');
title.textContent = 'Attach KB Article as Work Note';
title.style.cssText = 'font-size:16px;font-weight:bold;margin-bottom:6px;color:#1a1a1a;';
var subtitle = document.createElement('div');
subtitle.textContent = 'Record: ' + currentTable.toUpperCase();
subtitle.style.cssText = 'font-size:12px;color:#888;margin-bottom:16px;';
var inputLabel = document.createElement('label');
inputLabel.textContent = 'KB Article Number';
inputLabel.style.cssText = 'font-size:13px;font-weight:600;color:#333;margin-bottom:5px;display:block;';
var kbInput = document.createElement('input');
kbInput.type = 'text';
kbInput.placeholder = 'e.g. KB0012345';
kbInput.style.cssText = 'width:100%;padding:9px 12px;border:1px solid #ccc;border-radius:4px;font-size:14px;box-sizing:border-box;margin-bottom:14px;outline:none;';
var statusBox = document.createElement('div');
statusBox.style.cssText = 'font-size:12px;min-height:18px;margin-bottom:12px;color:#555;display:none;';
var previewWrap = document.createElement('div');
previewWrap.style.cssText = 'display:none;background:#f4f4f4;border-radius:4px;padding:10px;font-size:12px;font-family:monospace;word-break:break-all;margin-bottom:14px;color:#333;';
var btnRow = document.createElement('div');
btnRow.style.cssText = 'display:flex;gap:8px;justify-content:flex-end;';
var cancelBtn = document.createElement('button');
cancelBtn.textContent = 'Cancel';
cancelBtn.style.cssText = 'padding:8px 18px;background:#e0e0e0;color:#333;border:none;border-radius:4px;cursor:pointer;font-size:13px;';
cancelBtn.onclick = function() { document.body.removeChild(overlay); };
var attachBtn = document.createElement('button');
attachBtn.textContent = 'Attach as Work Note';
attachBtn.style.cssText = 'padding:8px 18px;background:#0070d2;color:#fff;border:none;border-radius:4px;cursor:pointer;font-size:13px;font-weight:600;';
btnRow.appendChild(cancelBtn); btnRow.appendChild(attachBtn);
box.appendChild(title); box.appendChild(subtitle); box.appendChild(inputLabel); box.appendChild(kbInput); box.appendChild(statusBox); box.appendChild(previewWrap); box.appendChild(btnRow);
overlay.appendChild(box); document.body.appendChild(overlay);
setTimeout(function() { kbInput.focus(); }, 100);
kbInput.addEventListener('keydown', function(e) { if (e.key === 'Enter') attachBtn.click(); });
function setStatus(msg, color) { statusBox.textContent = msg; statusBox.style.color = color || '#555'; statusBox.style.display = msg ? 'block' : 'none'; }
function resetBtn() { attachBtn.disabled = false; attachBtn.textContent = 'Attach as Work Note'; attachBtn.style.background = '#0070d2'; }
function onKbFound(kbSysId, kbTitle) {
var codeBlock = '[code]<a title="' + kbTitle + '" href=\'kb_view.do?sys_kb_id=' + kbSysId + '\' >' + kbInput.value.trim().toUpperCase() + ' : ' + kbTitle + '</a>[/code]';
previewWrap.textContent = codeBlock;
previewWrap.style.display = 'block';
setStatus('KB found: ' + kbTitle, '#2e7d32');
attachBtn.textContent = 'Posting Work Note...';
var patchXhr = new XMLHttpRequest();
patchXhr.open('PATCH', INSTANCE + '/api/now/table/' + currentTable + '/' + recordSysId, true);
patchXhr.setRequestHeader('Content-Type', 'application/json');
patchXhr.setRequestHeader('Accept', 'application/json');
patchXhr.setRequestHeader('X-UserToken', window.g_ck);
patchXhr.onload = function() {
if (patchXhr.status === 200) {
setStatus('Work note posted successfully.', '#2e7d32');
attachBtn.textContent = 'Done';
attachBtn.style.background = '#2e7d32';
setTimeout(function() { document.body.removeChild(overlay); window.location.reload(); }, 1500);
} else { setStatus('Failed to post work note (HTTP ' + patchXhr.status + ')', '#c62828'); resetBtn(); }
};
patchXhr.onerror = function() { setStatus('Network error posting work note.', '#c62828'); resetBtn(); };
patchXhr.send(JSON.stringify({ work_notes: codeBlock }));
}
function promptManualFallback(kbNumber) {
setStatus('', '');
previewWrap.style.display = 'none';
inputLabel.textContent = 'KB not found via API. Paste the KB sys_id manually:';
inputLabel.style.color = '#e65100';
kbInput.value = '';
kbInput.placeholder = 'e.g. c43d47123b35be10dde8037aa5e45ac1';
kbInput.focus();
attachBtn.disabled = false;
attachBtn.textContent = 'Use this sys_id';
attachBtn.style.background = '#e65100';
setStatus('Open the KB article, copy the sys_id from its URL, paste above.', '#e65100');
attachBtn.onclick = function() {
var manualSysId = kbInput.value.trim();
if (!/^[a-f0-9]{32}$/i.test(manualSysId)) { setStatus('That does not look like a valid sys_id (32 hex chars).', '#c62828'); return; }
attachBtn.disabled = true; attachBtn.textContent = 'Posting...';
onKbFound(manualSysId, kbNumber);
};
}
function tryAltLookup(kbNumber) {
setStatus('Trying alternate lookup...', '#0070d2');
var altUrl = INSTANCE + '/api/now/table/kb_knowledge?sysparm_query=' + encodeURIComponent('numberSTARTSWITH' + kbNumber + '^workflow_state=published') + '&sysparm_fields=sys_id,number,short_description&sysparm_limit=1&sysparm_suppress_pagination_header=true';
var altXhr = new XMLHttpRequest();
altXhr.open('GET', altUrl, true);
altXhr.setRequestHeader('Accept', 'application/json');
altXhr.setRequestHeader('X-UserToken', window.g_ck);
altXhr.onload = function() {
if (altXhr.status !== 200) { promptManualFallback(kbNumber); return; }
var results;
try { results = JSON.parse(altXhr.responseText).result; } catch(e) { results = []; }
if (!results || results.length === 0) { promptManualFallback(kbNumber); return; }
onKbFound(results[0].sys_id, results[0].short_description || kbNumber);
};
altXhr.onerror = function() { setStatus('Network error on alternate lookup.', '#c62828'); resetBtn(); };
altXhr.send();
}
attachBtn.onclick = function() {
var kbNumber = kbInput.value.trim().toUpperCase();
if (!kbNumber) { setStatus('Please enter a KB article number.', '#e65100'); kbInput.focus(); return; }
if (!/^KB\d+$/i.test(kbNumber)) { setStatus('Invalid format. Use KB followed by digits, e.g. KB0012345', '#e65100'); kbInput.focus(); return; }
attachBtn.disabled = true;
attachBtn.textContent = 'Looking up KB...';
previewWrap.style.display = 'none';
setStatus('Searching for ' + kbNumber + '...', '#0070d2');
var spUrl = INSTANCE + '/api/now/sp/search?q=' + encodeURIComponent(kbNumber) + '&kb=true&limit=10';
var spXhr = new XMLHttpRequest();
spXhr.open('GET', spUrl, true);
spXhr.setRequestHeader('Accept', 'application/json');
spXhr.setRequestHeader('X-UserToken', window.g_ck);
spXhr.onload = function() {
if (spXhr.status !== 200) { tryAltLookup(kbNumber); return; }
var data;
try { data = JSON.parse(spXhr.responseText); } catch(e) { tryAltLookup(kbNumber); return; }
var items = [];
if (data.result) {
if (Array.isArray(data.result)) items = data.result;
if (Array.isArray(data.result.kb_results)) items = items.concat(data.result.kb_results);
if (Array.isArray(data.result.search_results)) items = items.concat(data.result.search_results);
}
var kb = null;
items.forEach(function(item) { if (!kb && item.number && item.number.toUpperCase() === kbNumber) kb = item; });
if (!kb) { tryAltLookup(kbNumber); return; }
var kbSysId = kb.sys_id;
if (!kbSysId && kb.link) { var m = kb.link.match(/([a-f0-9]{32})/i); if (m) kbSysId = m[1]; }
if (!kbSysId) { tryAltLookup(kbNumber); return; }
onKbFound(kbSysId, kb.short_description || kb.title || kbNumber);
};
spXhr.onerror = function() { tryAltLookup(kbNumber); };
spXhr.send();
};
})();
Attach KB Article
Hint: Look up a KB article by number and attach it as a work note
Trigger: \kbattach