alert in SSJS Library - xpages

I have a function in SSJS Library. I would like get Client Side alert in Library. What i tried was not worked. I think I miss something. :(
function docAlive()
{
try
{
var otherDoc:NotesDocument= null;
if (funcDoc.getItemValueString("DocUNID")!="")
{
var otherDoc:NotesDocument = dbKontak.getDocumentByUNID(funcDoc.getItemValueString("DocUNID"))
if (otherDoc==null)
{
hataKod = "10001";
hataMsg = "There is no document :( Created One";
print (hataKod +": "+hataMsg);
view.postScript("alert('"+hataKod + " - " +hataMsg+"');");
}
}
return otherDoc;
}
catch (e)
{
e.toString();
}
}

view.postScript() will trigger a client-side alert, but as Tim Tripcony mentions, not in all events. And the alert will only be triggered after the function and any other code for the partial refresh has completed. At that point the HTML to trigger the (Client-Side) JavaScript alert will be posted back to the browser and the browser will action it.
If you want to throw an error back to the browser, I would strongly recommend XPages OpenLog Logger (and not just because I contribute and support it on OpenNTF). openLogBean.addError(e) will log the error to OpenLog and post an error message back to the browser.
The message is passed to the server using facesMessage.addMessage(), as documented here http://www.intec.co.uk/returning-error-messages-from-ssjs-through-the-facescontext/. I believe there are additional options for managing different message levels (e.g. WARNING, CONFIRMATION). FacesMessage is a standard Java (in this case, JSF) construct, so the documentation for it on the web is valid for XPages as well.

Related

using javascript pompt when closing page

I work with onbeforeunload to display a message with text area when closing pages, the problem is I am getting the message but not the text. The code I am using is :
window.addEventListener("beforeunload", function(event) {
var response = prompt("Whay this page isn't good for YOU ?", "");
//put the response in log file
//Exit the page
});
i tried so hard to get the prompt but no result.
You can actually short hand it using window.onbeforeunload = yourfunction and then create your function which prompts the user.
EDIT
Apologies, it seems as though ASP.NET is allowing me to do something a bit weird, it seems like the easiest way to go about this is to append your function at the end of that as such: window.onbeforeunload = function(){ return "Say what you want!" } This will display a prompt before the window is closing, I'm sure you can replace it for whatever you like.

Can't publish options with RabbitMQ message?

I'm using ampq.node for my RabbitMQ access in my Node code. I'm trying to use either the publish or sendToQueue methods to include some metadata with my published message (namely timestamp and content type), using the options parameter.
But whatever I'm passing to options is completely ignored. I think I'm missing some formatting, or a field name, but I cannot find any reliable documentation (beyond the one provided here which does not seem to do the job).
Below is my publish function code:
var publish = function(queueName, message) {
let content;
let options = {
persistent: true,
noAck: false,
timestamp: Date.now(),
contentEncoding: 'utf-8'
};
if(typeof message === 'object') {
content = new Buffer(JSON.stringify(message));
options.contentType = 'application/json';
}
else if(typeof message === 'string') {
content = new Buffer(message);
options.contentType = 'text/plain';
}
else { //message is already a buffer?
content = message;
}
return Channel.sendToQueue(queueName, content, options); //Channel defined and opened elsewhere
};
What am I missing?
Update:
Turns out if you choose to use a ConfirmChannel, you must provide the callback function as the last parameter, or else, the options object is ignored. So once I changed the code to the following, I started seeing the options correctly:
Channel.sendToQueue(queueName, content, options, (err, result) => {...});
Somehow, I can't seem to get your example publish to work... though I don't see anything particularly wrong with it. I'm not sure why I wasn't able to get your example code working.
But I was able to modify a version of my own amqplib intro code, and got it working with your options just fine.
Here is the complete code for my example:
// test.js file
var amqplib = require("amqplib");
var server = "amqp://test:password#localhost/test-app";
var connection, channel;
function reportError(err){
console.log("Error happened!! OH NOES!!!!");
console.log(err.stack);
process.exit(1);
}
function createChannel(conn){
console.log("creating channel");
connection = conn;
return connection.createChannel();
}
function sendMessage(ch){
channel = ch;
console.log("sending message");
var msg = process.argv[2];
var message = new Buffer(msg);
var options = {
persistent: true,
noAck: false,
timestamp: Date.now(),
contentEncoding: "utf-8",
contentType: "text/plain"
};
channel.sendToQueue("test.q", message, options);
return channel.close();
}
console.log("connecting");
amqplib.connect(server)
.then(createChannel)
.then(sendMessage)
.then(process.exit, reportError);
to run this, open a command line and do:
node test.js "example text message"
After running that, you'll see the message show up in your "test.q" queue (assuming you have that queue created) in your "test-app" vhost.
Here's a screenshot of the resulting message from the RMQ Management plugin:
side notes:
I recommend not using sendToQueue. As I say in my RabbitMQ Patterns email course / ebook:
It took a while for me to realize this, but I now see the "send to queue" feature of RabbitMQ as an anti-pattern.
Sure, it's built in to the library and protocol. And it's convenient, right? But that doesn't mean you should use it. It's one of those features that exists to make demos simple and to handle some specific scenarios. But generally speaking, "send to queue" is an anti-pattern.
When you're a message producer, you only care about sending the message to the right exchange with the right routing key. When you're a message consumer, you care about the message destination - the queue to which you are subscribed. A message may be sent to the same exchange, with the same routing key, every day, thousands of times per day. But, that doesn't mean it will arrive in the same queue every time.
As message consumers come online and go offline, they can create new queues and bindings and remove old queues and bindings. This perspective of message producers and consumers informs the nature of queues: postal boxes that can change when they need to.
I also recommend not using amqplib directly. It's a great library, but it lacks a lot of usability. Instead, look for a good library on top of amqplib.
I prefer wascally, by LeanKit. It's a much easier abstraction on top of amqplib and provides a lot of great features and functionality.
Lastly, if you're struggling with other details in getting RMQ up and running with Node.js, designing your app to work with it, etc., check out my RabbitMQ For Devs course - it goes from zero to hero, fast. :)
this may help others, but the key name to use for content type is contentType in the javascript code. Using the web Gui for rabbitMQ, they use content_type as the key name. different key names to declare options, so make sure to use the right one in the right context.

Calling an XAgent from a traditional Domino web app via AJAX

I have an XAgent I have created that works just fine via window.location but I can't get it to work via AJAX. This agent is called from a delete button on a popup div, so rather than writing to my responseStream in my XAgent, I'd prefer to just run my agent and close my popup via javascript when it is finished.
My XAgent is called by the URL doc.$DBPath.value + "/xAgent_DeleteDemand.xsp?open&id=" + doc.$DocUNID.value and looks like this:
javascript:importPackage(foo);
try {
var url:java.lang.String = context.getUrl().toString();
print(url);
if (param.containsKey("id")) {
var unid = param.get("id");
} else {
throw "No unid given";
}
XAgent.deleteDemand(unid);
} catch (e) {
print(e);
}
My actual code is in the foo package but that doesn't seem relevant because I'm not even getting my URL printed. I can say the the URL being generated and called works just fine using window.location so it is safe to assume that the problem is elsewhere.
I have a sneaking suspicion that maybe context doesn't have any meaning when called via AJAX from a non XPage app, but I don't know for sure.
I don't think there is anything special about my AJAX code but here it is just in case. It has been working fine for a long time.
function createAJAXRequest(retrievalURL, responseFunction) {
if (window.ActiveXObject) {
AJAXReq = new ActiveXObject("Microsoft.XMLHTTP");
} else if (window.XMLHttpRequest) {
AJAXReq = new XMLHttpRequest();
}
showHideIndicator("block")
var currentTime = new Date()
AJAXReq.open("GET", retrievalURL + "&z=" + currentTime.getTime());
AJAXReq.onreadystatechange = eval(responseFunction);
AJAXReq.send(null);
}
I'm not sure what the immediate problem would be, but as some troubleshooting steps:
The resultant URL is just server-relative and not on a different server+protocol combination, right?
Do you see anything on the browser's debug console when clicking the button?
Is there an entry in the browser's debug Network panel for the request at all?

Choosing strategy to handle response from asynchronous API call

There is a web application which does not have any own database, but communicates with remote through API. Performing a call to API takes some time and we do it asynchronously. The responsiveness of the application must be high from the user point of view.
Let's assume that the user is changing some data. To store the data we need to make a call. We start showing the new data right after making the call. But what can we do if the response of the call is unsuccessful? We need to restore the old values and show some kind of warning to the user. But the user may leave the page, where data were changed and see completely different page. What are general patterns to handle such situations?
If you are using .Net 4.5 you can do this using async/await. If your web client that you are calling provides an asynchronous API that returns a Task you can simply await the call inside a try/catch block. The await will cause the method to return immediately so the user will continue to observe the old data while it is executing. Once the we client call completes the method "resumes" after the await and you can update your data.
If the web client call causes an exception, the method will resume in the catch block and you can display an error to the user.
public async Task CallAPI()
{
try
{
var client = ...
await client.CallAPI();
}
catch(Exception ex)
{
// show warning message
}
}
If your web client does not provide an asynchronous API you can achieve the equivalent with the Task Parallel Library.
public void CallAPI1()
{
Task.Factory.StartNew( () =>
{
var client = ...
client.CallAPI();
}).ContinueWith( t =>
{
if(t.Exception != null)
{
// display error
}
else
{
// update web page with
}
},
null,
CancellationToken.None, TaskScheduler.FromCurrentSynchronizationContext());
}
This article has more information on async/await. And this one has some of the best practices to follow.

How to detect unsaved data in form when user leaves the page?

I need to detect unsaved data in form when user leaves the page without submitting the form. I would like to implement that without adding a value change listener to each input.
This is the functional requirement:
"User open a page than click on any link if values in the page changed an alert message popup to notify user that he need to save changed data, but if did not change any thing system continue without notify user".
I tried to compare array method to compare both DTO coming for DB and the bind DTO, but it gives me a lot of problems in array length, and byte comparison.
This is normally implemented in the client side with help of JavaScript, because it's not nicely possible to intercept on beforeunload event from the server side on when the enduser leaves the page.
Here's a concrete example with help of the JavaScript library jQuery (otherwise you would end up with 10 times as much code to make it properly crossbrowser compatible and work seamlessly together with ajax re-renders):
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
$(function() {
// Set the unload message whenever any input element get changed.
$(':input').on('change', function() {
setConfirmUnload(true);
});
// Turn off the unload message whenever a form get submitted properly.
$('form').on('submit', function() {
setConfirmUnload(false);
});
});
function setConfirmUnload(on) {
var message = "You have unsaved data. Are you sure to leave the page?";
window.onbeforeunload = (on) ? function() { return message; } : null;
}
</script>
Just paste this in your <h:head> template or just put it in some script.js file which you include by <h:outputScript>.
This worked for me.
$(function() {
// Set the unload message whenever any input element get changed.
$('input').change(function() {
setConfirmUnload(true);
});
// Turn off the unload message whenever a form get submitted properly.
$('form').submit(function() {
setConfirmUnload(false);
});
});
function setConfirmUnload(on) {
var message = "You have unsaved data. Are you sure to leave the page?";
window.onbeforeunload = (on) ? function() { return message; } : null;
}

Resources