Script Include and UI Action return error Cannot read properties of null (reading 'createElement')
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-05-2025 09:46 AM
I have this code in this UI Action
//remover alerts e logs teste
function getSelectedHardwares() {
alert('Function executed!'); // Debugging
var entries = g_list.getChecked();
if (!entries) {
alert('Nenhum consumível selecionado.');
} else {
alert('Consumíveis selecionados: ' + entries);
// Chamando a UI Action Server-side com os IDs selecionados
var ga = new GlideAjax('ConsumableBarcodeGenerator');
ga.addParam('sysparm_name', 'generateBarcode2');
// Test parameter
//ga.addParam('sysparm_user_name', '<OP10000>');
//ga.addParam('sysparm_selected_ids', entries.join(','));
ga.addParam('sysparm_selected_ids', JSON.stringify(entries));
// ga.addParam('sysparm_ui_action_source', 'alm_hardware');
// ga.addParam('sysparm_id', 'serial_number');
ga.getXML(ConsumableBarcodeGeneratorParse);
}
function ConsumableBarcodeGeneratorParse(response) {
var answerFromXML = response.responseXML.documentElement.getAttribute('answer');
alert("outro texto"+answerFromXML);
//PARA receber codigo para links download na ui action
try {
var jsonResponse = JSON.parse(answerFromXML);
//alert("jsonResponse"+ jsonResponse.barcode_links.length);
if (jsonResponse.status === "success" && jsonResponse.barcode_links.length > 0) {
startAutoDownload(jsonResponse.barcode_links);
} else {
alert('Nenhum código de barras gerado.');
}
} catch (e) {
alert('Erro ao processar resposta JSON: ' + e.message);
}
}
//funcao para fazer o auto download dos barcodes attachments
function startAutoDownload(barcodeLinks) {
barcodeLinks.forEach(function(url) {
//alert("objetos de barcodes:"+barcodeLinks);
try {
var a = document.createElement('a');
a.href = url;
a.download = ''; // Ensures browser download behavior
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
} catch (e) {
alert('Erro reconstruir a: ' + e.message);
}
});
alert('Download automático iniciado.');
}
}
and this Script Include,
//remover gs.infos e alerts returns no final
var ConsumableBarcodeGenerator = Class.create();
ConsumableBarcodeGenerator.prototype = Object.extendsObject(AbstractAjaxProcessor, {
generateBarcode: function() {
gs.info('Script Include chamado!');
// Obtém os IDs enviados via GlideAjax
var selectedIdsRaw = this.getParameter('sysparm_selected_ids');
var uiActionSource = this.getParameter('sysparm_ui_action_source');
var idItem = this.getParameter('sysparm_id');
// Verifica se os IDs foram realmente recebidos
if (!selectedIdsRaw || selectedIdsRaw.trim() === '') {
gs.info('Nenhum ID recebido.');
return JSON.stringify({
status: "error",
message: "Nennhum consumível selecionado"
});
}
// Divide os IDs em um array para processamento
//var sysIds = selectedIds.split(',').map(id => id.trim());
var selectedIds;
try {
selectedIds = JSON.parse(selectedIdsRaw);
} catch (e) {
gs.error('Erro ao converter JSON: ' + e.message);
return JSON.stringify({
status: "error",
message: "Erro ao processar JSON recebido."
});
}
var selectedIdsArray = Array.isArray(selectedIds) ? selectedIds : selectedIds.split(',').map(id => id.trim());
selectedIdsArray.forEach(function(id) {
gs.info('ID recebido: ' + id);
});
var consumiveisEncontrados = [];
var attachmentLinks = []; // Store generated barcode URLs (ENVIAR URLS PARA ui action download auto)
// Itera sobre cada ID e consulta na base de dados
selectedIdsArray.forEach(function(id) {
var targetConsumsGr = new GlideRecord(uiActionSource);
targetConsumsGr.addQuery('sys_id', id); // Consulta cada ID individualmente
targetConsumsGr.query();
if (!targetConsumsGr.hasNext()) {
gs.info('Consumível com ID ' + id + ' não encontrado.');
return; // Se não encontrar, segue para o próximo
}
while (targetConsumsGr.next()) {
gs.info('Consumível encontrado: ' + targetConsumsGr.display_name);
consumiveisEncontrados.push(targetConsumsGr.sys_id.toString()); // Armazena IDs encontrados
var assetSysId = targetConsumsGr.sys_id;
// model name to para o attachment name
var model;
if (idItem == 'model.display_name') {
model = targetConsumsGr.model.display_name;
} else if (idItem == 'serial_number') {
model = targetConsumsGr.serial_number;
}
// model name to para o barcode url
var encodedModel = encodeURIComponent(model);
// Verifica se este consumível já possui um anexo de código de barras
var attachmentGr = new GlideRecord('sys_attachment');
attachmentGr.addQuery('table_name', uiActionSource);
//forma de criar tambem download auto para anexos já existentes
attachmentGr.orderByDesc('sys_created_on'); // Obtém o último anexo criado
attachmentGr.addQuery('table_sys_id', assetSysId);
attachmentGr.query();
if (attachmentGr.next()) {
gs.info('Consumível já tem código de barras. Adicionado á lista de downlaods');
var sysIdAttachment = attachmentGr.sys_id;
var attachmentLink = gs.getProperty('glide.servlet.uri') + 'sys_attachment.do?sys_id=' + sysIdAttachment;
attachmentLinks.push(attachmentLink); // Adiciona à lista de downloads
// Skip creating new barcode as one already exists
continue;
//codigo para seguir e ignorar auto download de anexos(barcodes) ja existentes, apenas contiinuue
//continue; // **Ignora este ID e passa para o próximo**
}
var imageUrl = 'https://quickchart.io/barcode?type=code128&includeText=true&text=' + encodedModel + '&format=png';
//var imageUrl = 'https://barcode.tec-it.com/barcode.ashx?data='+serialNumber+'& code=Code128&dpi=96';
//teste
//gs.info("O valor do model é: " + model);
//gs.info("Model Name: " + model);
//gs.info("Encoded Model: " + encodedModel);
//gs.info("Barcode URL: " + imageUrl);
//gs.info("sys_id Capturado: "+assetSysId);
// 1. Create temporary record for initial attachment storage
var tempRec = new GlideRecord('sys_attachment');
tempRec.initialize();
tempRec.file_name = model + '_temp.png';
tempRec.table_name = uiActionSource;
tempRec.insert(); // Create temporary holder record
// 2. Fetch and save image to temporary record
var request = new sn_ws.RESTMessageV2();
request.setHttpMethod("GET");
request.setEndpoint(imageUrl);
request.setRequestHeader("Accept", "image/png");
request.saveResponseBodyAsAttachment('sys_attachment', tempRec.sys_id, model + '_barcode.png');
var response = request.execute();
if (response.getStatusCode() === 200) {
// 3. Copy attachment to target asset record
var gsa = new GlideSysAttachment();
var grAsset = new GlideRecord(uiActionSource);
if (grAsset.get(assetSysId)) {
gsa.copy('sys_attachment', tempRec.sys_id, uiActionSource, grAsset.sys_id);
// Query sys_attachment again to get the correct sys_id of the newly created barcode
var finalAttachmentGr = new GlideRecord('sys_attachment');
finalAttachmentGr.addQuery('table_name', uiActionSource);
finalAttachmentGr.addQuery('table_sys_id', assetSysId);
finalAttachmentGr.orderByDesc('sys_created_on'); // Get the latest attachment
finalAttachmentGr.query();
if (finalAttachmentGr.next()) {
sysIdAttachment = finalAttachmentGr.sys_id;
attachmentLink = gs.getProperty('glide.servlet.uri') + 'sys_attachment.do?sys_id=' + sysIdAttachment;
attachmentLinks.push(attachmentLink);
}
// 4. Cleanup temporary record
tempRec.deleteRecord();
}
}
}
targetConsumsGr.update();
//despistar quantity bug
// // Instead of targetConsumsGr.update(); ensure these fields are not changed.
// var originalQuantity = targetConsumsGr.quantity;
// targetConsumsGr.update();
// targetConsumsGr.setValue('quantity', originalQuantity); // Explicitly preserve quantity
});
//fazer if para diferença entre hardware e consumable(generaBarcode/generateBarcode2)
var responseJSON = JSON.stringify({
status: "success",
barcode_links: attachmentLinks
});
return responseJSON;
},
//})
generateBarcode2: function() {
gs.info('Script Include chamado!');
// Obtém os IDs enviados via GlideAjax
var selectedIdsRaw = this.getParameter('sysparm_selected_ids');
// Verifica se os IDs foram realmente recebidos
if (!selectedIdsRaw || selectedIdsRaw.trim() === '') {
gs.info('Nenhum ID recebido.');
return JSON.stringify({ status: "error", message: "Nennhum consumível selecionado"});
}
// Divide os IDs em um array para processamento
//var sysIds = selectedIds.split(',').map(id => id.trim());
var selectedIds;
try {
selectedIds = JSON.parse(selectedIdsRaw);
} catch (e) {
gs.error('Erro ao converter JSON: ' + e.message);
return JSON.stringify({ status: "error", message: "Erro ao processar JSON recebido." });
}
var selectedIdsArray = Array.isArray(selectedIds) ? selectedIds : selectedIds.split(',').map(id => id.trim());
selectedIdsArray.forEach(function(id) {
gs.info('ID recebido: ' + id);
});
var consumiveisEncontrados = [];
var attachmentLinks = []; // Store generated barcode URLs (ENVIAR URLS PARA ui action download auto)
// Itera sobre cada ID e consulta na base de dados
selectedIdsArray.forEach(function(id) {
var targetConsumsGr = new GlideRecord('alm_hardware');
targetConsumsGr.addQuery('sys_id', id); // Consulta cada ID individualmente
targetConsumsGr.query();
if (!targetConsumsGr.hasNext()) {
gs.info('Consumível com ID ' + id + ' não encontrado.');
return; // Se não encontrar, segue para o próximo
}
while (targetConsumsGr.next()) {
gs.info('Consumível encontrado: ' + targetConsumsGr.display_name);
consumiveisEncontrados.push(targetConsumsGr.sys_id.toString()); // Armazena IDs encontrados
var assetSysId = targetConsumsGr.sys_id;
// model name to para o attachment name
var model = targetConsumsGr.serial_number;
// model name to para o barcode url
var encodedModel = encodeURIComponent(model);
// Verifica se este consumível já possui um anexo de código de barras
var attachmentGr = new GlideRecord('sys_attachment');
attachmentGr.addQuery('table_name', 'alm_hardware');
attachmentGr.addQuery('table_sys_id', assetSysId);
attachmentGr.query();
if (attachmentGr.next()) {
gs.info('Consumível já tem código de barras. SEgue...');
continue; // **Ignora este ID e passa para o próximo**
}
var imageUrl = 'https://quickchart.io/barcode?type=code128&includeText=true&text=' + encodedModel + '&format=png';
//var imageUrl = 'https://barcode.tec-it.com/barcode.ashx?data='+serialNumber+'& code=Code128&dpi=96';
//teste
//gs.info("O valor do model é: " + model);
//gs.info("Model Name: " + model);
//gs.info("Encoded Model: " + encodedModel);
//gs.info("Barcode URL: " + imageUrl);
//gs.info("sys_id Capturado: "+assetSysId);
// 1. Create temporary record for initial attachment storage
var tempRec = new GlideRecord('sys_attachment');
tempRec.initialize();
tempRec.file_name = model + '_temp.png';
tempRec.table_name = 'alm_hardware';
tempRec.insert(); // Create temporary holder record
// 2. Fetch and save image to temporary record
var request = new sn_ws.RESTMessageV2();
request.setHttpMethod("GET");
request.setEndpoint(imageUrl);
request.setRequestHeader("Accept", "image/png");
request.saveResponseBodyAsAttachment('sys_attachment', tempRec.sys_id, model + '_barcode.png');
var response = request.execute();
if (response.getStatusCode() === 200) {
// 3. Copy attachment to target asset record
var gsa = new GlideSysAttachment();
var grAsset = new GlideRecord('alm_hardware');
if (grAsset.get(assetSysId)) {
gsa.copy('sys_attachment', tempRec.sys_id, 'alm_hardware', grAsset.sys_id);
// Query sys_attachment again to get the correct sys_id of the newly created barcode
var finalAttachmentGr = new GlideRecord('sys_attachment');
finalAttachmentGr.addQuery('table_name', 'alm_hardware');
finalAttachmentGr.addQuery('table_sys_id', assetSysId);
finalAttachmentGr.orderByDesc('sys_created_on'); // Get the latest attachment
finalAttachmentGr.query();
if (finalAttachmentGr.next()) {
var sysIdAttachment = finalAttachmentGr.sys_id;
var attachmentLink = gs.getProperty('glide.servlet.uri') + 'sys_attachment.do?sys_id=' + sysIdAttachment;
attachmentLinks.push(attachmentLink);
}
// 4. Cleanup temporary record
tempRec.deleteRecord();
}
}
}
targetConsumsGr.update();
});
var responseJSON = JSON.stringify({
status: "success",
barcode_links: attachmentLinks
});
return responseJSON;
},
type: 'ConsumableBarcodeGenerator'
});
When I'm in list view I select one or more rows and then select the UI Action to generate a Barcode Image and download it automatically.
Everything works as expected, except the auto-download, I get the error: Cannot read properties of null (reading 'createElement') when the code enters the function startAutoDownload.
Can you please help?
I leave the UI Action in the attachments.
1 REPLY 1
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
05-28-2025 02:05 AM
Could only find a workarround using
g_navigation in the hardware UI ACTION to auto donwload