JSBridge examples
Resco JavaScript Bridge |
---|
This article describes use-case specific examples using the JSBridge.
MessageBox too short - text gets cut off
When displaying text using a MessageBox alert, you might encounter an issue where the text is cut off due to its length. A practical solution to this problem is to use an iframe within a modal window instead of a standard alert. This approach allows for displaying content in a scrollable iframe, which can be interacted with like a typical HTML page. Additionally, this method enables the use of CSS and JavaScript for enhanced presentation and functionality.
JavaScript function for modal iframe
The code begins with a JavaScript function named alert. This function makes a request to the MobileCRM.Configuration object to fetch configuration settings. Using these settings, it sets up and displays an iframe as a modal window. The iframe loads an HTML document from a specified path, and text content (var messageText) is passed to it, overcoming MessageBox's text capacity limitation.
function showAlert() {
MobileCRM.Configuration.requestObject(function (config) {
var messageText = `Lorem ipsum`; // Consider parameterizing this if the text changes
var documentPath = config.storageDirectory + "/WWW/index.html";
var options = {
text: messageText
};
MobileCRM.UI.IFrameForm.showModal("TestIframe", documentPath, options);
});
}
HTML structure and JavaScript for content display
After the JavaScript function, we define the HTML document to be loaded in the iframe. This document includes a basic HTML structure with a heading and a paragraph tag. The included JavaScript script in this HTML is responsible for dynamically handling and displaying the content within the iframe. In this example, we divide the input text into individual lines. You can format the input text as necessary for your scenario.
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- Head contents... -->
</head>
<body>
<h1>List of something</h1>
<p id="iframeText"></p>
<script>
window.onload = function () {
MobileCRM.UI.IFrameForm.requestObject(function (iFrame) {
var textContent = iFrame.options.text || '';
var eachLine = textContent.split('\n');
var textParagraph = document.getElementById('iframeText');
eachLine.forEach(function (line) {
textParagraph.innerHTML += line + "<br>";
});
}, MobileCRM.bridge.alert, null);
}
</script>
</body>
</html>
Is the question answered? - IsAnswered property
The IsAnswered property of the MobileCRM.UI.QuestionnaireForm.Question object allows for checking if a question in a questionnaire form has been answered.
In practice, the MobileCRM.UI.QuestionnaireForm.onChange method is used to listen for changes within the form. If the "imagemedia" question is changed and detected as answered, it triggers predefined custom logic for further action:
MobileCRM.UI.QuestionnaireForm.onChange((qForm) => {
var changedItem = qForm.context.changedItem;
if (changedItem == "imagemedia") {
var imageQuestion = qForm.findQuestionByName("imagemedia");
if (imageQuestion.isAnswered === true) {
// Implement custom logic here
}
}
}, true, null);
This approach utilizes the IsAnswered property to trigger specific actions when certain questions are answered, simplifying dynamic responses.
Load image from annotation, use it as answer
This script dynamically loads an image from an annotation related to the record in the regarding lookup question. When the resco_regardingid field changes, indicating a new or different entity (such as an asset, account, or contact), the script automatically fetches the associated annotation that contains an image. This image is then set as the answer to a designated image question within the form. In this example, we load an image from the annotation related to the contact.
OnChange listener and function handleRegardIdChange
We use the MobileCRM.UI.QuestionnaireForm.onChange function as a listener for a change in the resco_regarding field and call the handleRegardIdChange function. In this function, we assign the record ID from resco_regardingid to the regardingid variable and call clearImageAnswerIfPresent and fetchAnnotationAndSetImage functions.
MobileCRM.UI.QuestionnaireForm.onChange(function(qForm) {
var context = qForm.context;
if (context.changedItem == "resco_regardingid") {
handleRegardIdChange(qForm);
}
}, true, null);
function handleRegardIdChange(qForm) {
var regardingid = qForm.questionnaire.properties.resco_regardingid;
clearImageAnswerIfPresent(qForm);
fetchAnnotationAndSetImage(regardingid);
}
function clearImageAnswerIfPresent
This function checks whether the imagemedia question is answered (contains image). If it is, it uses the MobileCRM.UI.QuestionnaireForm.trySetImageAnswer method with null parameters to delete the image.
function clearImageAnswerIfPresent(qForm) {
var imageQuestion = qForm.findQuestionByName("imagemedia");
if (imageQuestion && imageQuestion.isAnswered === true) {
MobileCRM.UI.QuestionnaireForm.trySetImageAnswer("imagemedia", null, null, function(errorMsg) {
if (errorMsg) {
MobileCRM.bridge.alert("Error setting image: " + errorMsg);
} else {
console.log("Image deleted successfully.");
}
});
}
}
function fetchAnnotationAndSetImage
This function fetches the annotation related to the regarding entity and calls loadDocumentAndSetImage.
function fetchAnnotationAndSetImage(regardingid) {
var fetchEntity = new MobileCRM.FetchXml.Entity("annotation");
fetchEntity.addAttributes();
var filter = new MobileCRM.FetchXml.Filter();
filter.type = "and";
var cond1 = new MobileCRM.FetchXml.Condition();
cond1.attribute = "objectid";
cond1.operator = "eq";
cond1.value = regardingid;
filter.conditions.push(cond1);
fetchEntity.filter = filter;
var fetch = new MobileCRM.FetchXml.Fetch(fetchEntity);
fetch.executeAsync("DynamicEntities").then(function(result) {
if (result.length < 1) {
MobileCRM.bridge.alert("No images related.");
} else {
var annotation = result[0];
var annotationid = annotation.id;
var mimetype = annotation.properties.mimetype;
loadDocumentAndSetImage(annotationid, mimetype);
}
}, function(error) {
MobileCRM.bridge.alert("Fetch failed: " + error);
});
}
function loadDocumentAndSetImage
This function uses the MobileCRM.DynamicEntity.loadDocumentBody method to load documentbody from the annotation. We use this method as we cannot fetch documentbody in the offline mode. This way, the script can work both online and offline. Right after, we use the MobileCRM.UI.QuestionnaireForm.trySetImageAnswer method to load the image into the question.
function loadDocumentAndSetImage(annotationid, mimetype) {
MobileCRM.DynamicEntity.loadDocumentBody("annotation", annotationid, function(base64str) {
MobileCRM.UI.QuestionnaireForm.trySetImageAnswer("imagemedia", base64str, mimetype, function(errorMsg) {
if (errorMsg) {
MobileCRM.bridge.alert("Error setting image: " + errorMsg);
} else {
console.log("Image set successfully.");
}
});
}, function(error) {
MobileCRM.bridge.alert("Error loading document: " + error);
});
}
RFID scanning with Zebra
Here is a simple example of using a Zebra RFID scanner on a custom HTML page in Resco Mobile CRM.
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Empty Offline HTML page</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="initial-scale=1, user-scalable=no" />
<script src="JSBridge.js"></script>
</head>
<body>
<script>
// ---------------------------------------------------
// Here is a simple example of using Zebra Scanner in a custom HTML page in Resco Mobile CRM.
// This example uses the Zebra Scanner to scan RFID tags and then fetch the check items linked to an asset with a matching tag ID.
// In your case, you will need to modify the entities and attributes that are used as well as implement additional logic where needed.
// For example, when handling tag IDs found on the rig but not supposed to be there, etc.
// ---------------------------------------------------
const LINE_STATUS_VERIFIED = 204800000;
window.onload = function () {
// Try to connect to the Zebra device when the iFrame is loaded (Zebra Scanner needs to be connected to the device via Bluetooth)
// After this function was called, the Zebra device can be used for scanning as long as the Form (and the iFrame on the form) is open
MobileCRM.Services.ZebraScanner.connect(
function () {
// Optionally, show an alert that the connection was established successfully
MobileCRM.bridge.alert("Zebra connection active.");
},
function (err) {
MobileCRM.bridge.alert("Failed to connect to Zebra: " + err);
},
null
);
};
MobileCRM.Services.ZebraScanner.onScan(
// When the scanning button is released, the scanned data is passed to the function as an array of strings tags[]
function (tags) {
if (tags.length > 0) {
// I have the scanned tag IDs; now I need to fetch the check items that are linked to an asset with a matching tag ID
// the rig id is stored in the "matejdev_rigasset" entity, "matejdev_rfidtagnumber" attribute
let entity = new MobileCRM.FetchXml.Entity("matejdev_rigcheckitem");
entity.addAttributes();
var assetLink = new MobileCRM.FetchXml.LinkEntity(
"matejdev_rigasset"
);
assetLink.alias = "linkAsset";
assetLink.from = "matejdev_rigassetid";
assetLink.to = "matejdev_rigasset";
let filter = new MobileCRM.FetchXml.Filter();
filter.type = "or";
tags.forEach((tag) => {
filter.where("matejdev_rfidtagnumber", "eq", tag);
});
assetLink.filter = filter;
entity.linkentities.push(assetLink);
let fetch = new MobileCRM.FetchXml.Fetch(entity);
fetch
.executeAsync("DynamicEntities")
.then((auditLines) => {
// this fetch query returned list of check items with matching tag id in an MobileCRM.DynamicEntity array auditLines[]
let updatedAuditLines = [];
auditLines.forEach((auditLine) => {
// We will update the status for the check items with matching tag ID to "Verified"
auditLine.properties.matejdev_status = LINE_STATUS_VERIFIED;
updatedAuditLines.push(auditLine);
});
// ---------------------
// Here, you could do additional processing tag IDs, that were found while scanning, but there is no matching check item (with asset) for them
// ---------------------
if (updatedAuditLines.length > 0) {
// We save the update check items; assets are not being modified
MobileCRM.DynamicEntity.saveMultiple(
updatedAuditLines,
false,
() => {
/*success*/
MobileCRM.bridge.alert(
updatedAuditLines.length + " check items updated!"
);
},
(err) => {
MobileCRM.bridge.alert(
"Error while saving asset check lines: " + err
);
}
);
}
})
.catch((err) => {
MobileCRM.bridge.alert(
"Error fetching asset check lines: " + err
);
});
}
},
true,
null
);
</script>
</body>
</html>