Retrieving the error elements in Pega 8.1 Tree Navigation Flow - javascript

I am currently working on Pega. I am basically new in it. Pega version which I am working is 8.1.
Actually in the flow while submitting a form whenever there are validation errors in the required fields there an alert pops up. But as far as UI and UX the window needs to scroll with a subtle animation to the error fields, this I can do perfectly for any HTML page using jquery, but as I am new to Pega, I am facing a problem to get the error fields.
What I find, the error fields are appending on the relevant fields whenever there are validations, but catching those elements are going undefined.
I am sharing the simple code which I have written:
var validateScroll = function(){
var getErrors = function(){
this.parent = "";
}
getErrors.prototype.getErrorfn = function(node){
this.parent = $(node);
var errorLabels = this.parent.find('.dynamic-icon-error');
console.log(errorLabels.attr('class'))
}
var a = new getErrors();
var scrollfn = function(){
var forms = $(document).find('form')[0];
var _FORM = $(forms);
_FORM.on('submit',a.getErrorfn(_FORM));
}
return{
init:function(){
scrollfn();
}
}
}();
$(document).ready(function(){
validateScroll.init();
})
The result I am getting is "undefined", since those are appending and not caught in the DOM.
Can anyone please suggest me any process? Is there any API to get the error fields in javascript. I have searched their Javascript API, but couldn't find any such API.
I have also asked this on PDN but got no reply.
Thanks in advance.

Related

Cannot get ExecuteScriptAsync() to work as expected

I'm trying to set a HTML input to read-only using ExecuteScriptAsync. I can make it work, but it's not an ideal scenario, so I'm wondering if anyone knows why it doesn't work the way I would expect it to.
I'm using Cef3, version 63.
I tried to see if it's a timing issue and doesn't appear to be.
I tried invalidating the view of the browser but that doesn't seem to help.
The code I currently have, which works:
public void SetReadOnly()
{
var script = #"
(function(){
var labelTags = document.getElementsByTagName('label');
var searchingText = 'Notification Initiator';
var found;
for (var i=0; i<labelTags.length; i++)
{
if(labelTags[i].textContent == searchingText)
{
found = labelTags[i]
break;
}
}
if(found)
{
found.innerHTML='Notification Initiator (Automatic)';
var input;
input = found.nextElementSibling;
if(input)
{
input.setAttribute('readonly', 'readonly');
}
}})()
";
_viewer.Browser.ExecuteScriptAsync(script);
_viewer.Browser.ExecuteScriptAsync(script);
}
now, if I remove
found.innerHTML='Notification Initiator (Automatic)';
the input is no longer shown as read-only. The HTML source of the loaded webpage does show it as read-only, but it seems like the frame doesn't get re-rendered once that property is set.
Another issue is that I'm executing the script twice. If I run it only once I don't get the desired result. I'm thinking this could be a problem with V8 Context that is required for the script to run. Apparently running the script will create the context, so that could be the reason why running it twice works.
I have been trying to figure this out for hours, haven't found anything that would explain this weird behaviour. Does anyone have a clue?
Thanks!

AngularJs controller .appendChild() adding up each time view is visited

I have created a chat feature recently and I notice a curious bug. The following is the code I am using in my controller:
myFirebase.on('child_added', function(snapshot) {
var msg = snapshot.val();
var msgUsernameElement = document.createElement("b");
msgUsernameElement.textContent = msg.user;
var msgTextElement = document.createElement("p");
msgTextElement.textContent = msg.message;
var msgElement = document.createElement("div");
msgElement.appendChild(msgUsernameElement);
msgElement.appendChild(msgTextElement);
document.getElementById("messages").append(msgElement);
});
Suppose we enter the Chat view for the first time, then when I chat, the .appendChild() is working perfectly fine and the typed message shows up in the div 'messages'. Now Suppose we leave the Chat view and re-enter it, and type and send another chat message, then the .appendChild() is executed twice and the same message is appears twice in the div 'messages'. This continues linearly so if we re-enter the controller for the fifth time and send a message, the message is appended to the div 'messages' five times...
What is going on here?
I am using the Ionic Framework and the ready-made app template 'Tabs'. My chat feature is in the chat-details controller.
The problem is because the event handler is being added twice, once when you first visit the chat page, and again when you come back. To confirm that, visit it a third time, and you should see it 3x.
The solution is to put in an $onDestroy handler to remove the event handler. If the event handler can't be removed (ie it doesn't have an off method), then you should set a variable to tell you that it is initialised, and you check that on initialising the page (to prevent you doing it twice)
So Mikkel gave the right suggestion to initialize a variable and basically use that as a flag to make sure that my event handler is not called multiple times, given multiple entries to the Chat view, but only once. The following is my solution:
if (window.localStorage.getItem("notVisited") == null){ //This initilizes a variable in localstorage
window.localStorage.setItem("notVisited","true");
}
var startListening = function() {
myFirebase.on('child_added', function(snapshot) {
var msg = snapshot.val();
var msgUsernameElement = document.createElement("b");
msgUsernameElement.textContent = msg.user;
var msgTextElement = document.createElement("p");
msgTextElement.textContent = msg.message;
var msgElement = document.createElement("div");
msgElement.appendChild(msgUsernameElement);
msgElement.appendChild(msgTextElement);
document.getElementById("messages").append(msgElement);
});
window.localStorage.setItem("notVisited","false");
}
if (window.localStorage.getItem("notVisited") == "true") {
startListening();
}
Now after implementing this, I ran into a new problem which was that with this new code, each time I re-entered the view, the previous chat messages would not show up. So I added this:
if (window.localStorage.getItem("notVisited") == "false"){
$http({
url: "https://uniff-f4136.firebaseio.com/" + chatKey + ".json",
method: "GET"
}).then(function (response) {
for (var i in response.data){
var msgUsernameElement = document.createElement("b");
msgUsernameElement.textContent = response.data[i].user;
var msgTextElement = document.createElement("p");
msgTextElement.textContent = response.data[i].message;
var msgElement = document.createElement("div");
msgElement.appendChild(msgUsernameElement);
msgElement.appendChild(msgTextElement);
document.getElementById("messages").append(msgElement);
}
});
}
In the end, this made my chat work though I do not like the repetition of code. I hope others find this insightful.
Finally, to learn about using firebase to build a real time web chat app, visit this Google CodeLabs link: https://codelabs.developers.google.com/codelabs/cloud-firebase-chat/#4

Handling javascript onchange events with Mechanize rubygem

I have been trying to write a script that fetches results from my university website. Someone suggested that I use Mechanize and it does look really promising.
In order to get the result, one has to first enter the roll number and then select the session.
Simulating the first part has been easy with Mechanize, but with the second part I'm having problems as it is actually a JavaScript onchange event.
I read the function definition in the JavaScript and this is what I have come up with so far. Mechanize can't handle the onchange event and also when I pass the values that are actually changed by the JavaScript function manually, the same page is returned.
Here's the javaScript Code
function __doPostBack(eventTarget, eventArgument) {
var theform;
if (window.navigator.appName.toLowerCase().indexOf("microsoft") > -1) {
theform = document.Form1;
}
else {
theform = document.forms["Form1"];
}
theform.__EVENTTARGET.value = eventTarget.split("$").join(":");
theform.__EVENTARGUMENT.value = eventArgument;
theform.submit();
}
I set a breakpoint in firebug and found the value of __EVENTTARGET to be 'Dt1', whereas __EVENTARGUMENT stays ''.
The ruby script that I have written to do this is
require 'mechanize'
#set up the agent to mimic firefox on windows
agent = Mechanize.new
agent.keep_alive = true
agent.user_agent = 'Windows Mozilla'
page = agent.get('http://www.nitt.edu/prm/nitreg/ShowRes.aspx')
#using mechanize to get us past the first form presented
result_form = page.form('Form1')
result_form.TextBox1 = '205110018'
page = agent.submit( result_form, result_form.buttons.first )
#the second hurdle that we encounter,
#here i'm trying to get past the JavaScript by doing what it does manually
result_form = page.form('Form1')
result_form.field_with('Dt1').options.find { |opt| opt.value == '66' }.select
result_form.field_with( :name => '__EVENTTARGET' ).value = 'Dt1'
#here i should have got the page with the results
page = agent.submit(result_form)
pp page
Can anyone tell me what I'm doing wrong?
It looks like you have it working already! Try using puts page.body instead of pp page and you'll see the contents of the page. You can use Mechanize search functions to scrape the data from the page.
Also, you could simplify that code to:
result_form['__EVENTTARGET'] = 'Dt1'
result_form['Dt1'] = '66'

error with javascript globals and jquery call back functions

i'm trying to make an array of value's to be checked to see if that value has been added before.
if it has show an alert.
if it hasn't added it to the array and conduct a post ajax query to the server to retrieve a corresponding table row.
i'm mostly a novice when it comes to javascript and i'm finding it hard to debug because a fault in syntax breaks the entire script.
here is my code if someone see's an error could u tell me how to fix it.
also if you know a program to help with debugging java-script that would be really helpful.
I know that the jquery calls work fine because i added in the array check afterwards.
var selectedProductsArray = new array();
var selectedProductsCount = 0;
$(function() {
$('.selectProductID').live('click', function(event) {
var count = 0;
var found = false;
while(count < selectedProductsCount)
{
if(selectedProductsArray[count] == $(this).val())
{
found = true;
break;
}
count++;
}
if(found)
{
alert("you can only add one line for each product.");
}else{
selectedProductsArray[selectedProductsCount] = $(this).val();
selectedProductsCount++;
$.post("order/getitem", "ProductID="+$(this).val(), function(data){
$("#orderItems tbody").append(data);
selectedProductsCount++;
});
}
return false;
});
});
Firstly, there is no "array" class so I'm surprised that you even getting passed that; you want:
var selectedProductsArray = new Array();
or
var selectedProductsArray = [ ];
Also, you don't need to keep computing $(this).val() over and over again, you should just say:
var count = 0;
var found = false;
var value = $(this).val();
above the while loop and reference value instead of $(this).val() in the rest. You're also incrementing selectedProductsCount twice when I think you only want to do it once, this will leave empty/null entries in your selectedProductsArray and that might confuse things later on.
I can't eye-ball any other glaring errors but that new array() one should be a show stopper. Hard to say without a fully functioning example.
Does order/getitem get called? Does it send anything back?
For debugging and trying things out:
Firebug
jsfiddle

Accessing contents of NativeWindow in a HTML AIR application?

I'm currently building a HTML/JS AIR application. The application needs to display to the user a different 'window' - dependant on whether this is the first time they've launched the application or not. This part is actually fine and I have the code below to do that:
if(!startUp()) { // this simply returns a boolean from a local preferences database that gets shipped with the .air
// do first time stuff
var windowOptions = new air.NativeWindowInitOptions();
windowOptions.systemChrome = 'none';
windowOptions.type = 'lightweight';
windowOptions.transparent = 'true';
windowOptions.resizable = 'false';
var windowBounds = new air.Rectangle(300, 300, 596, 490);
var newHtmlLoader = air.HTMLLoader.createRootWindow(true, windowOptions, true, windowBounds);
newHtmlLoader.load(new air.URLRequest('cover.html'));
}
else {
// display default window
// just set nativeWindow.visible = true (loaded from application.xml)
}
However, what I want to be able to do is manipulate the html content from within cover.html after it has loaded up. There seems to be plenty of tutorials online of how to move, resize, etc. the NativeWindow, but I simply want access to the NativeWindow's HTML content.
For example, how would I add a new paragraph to that page? I've tried the following:
newHtmlLoader.window.opener = window;
var doc = newHtmlLoader.window.opener.document.documentElement;
Using AIR's Introspector console, ....log(doc) returns [object HTMLHtmlElement].
Hmm, seems promising right? I then go on to try:
var p = document.createElement('p');
var t = document.createTextNode('Insert Me');
p.appendChild(t);
doc.appendChild(p);
...but nothing gets inserted. I've also tried the following replacements for doc:
var doc = newHtmlLoader.window.opener.document.body; // .log(doc) -> [object HTMLBodyElement]
var doc = newHtmlLoader.window.opener.document; // .log(doc) -> Error: HIERARCHY_REQUEST_ERR: DOM Exception 3
...as well as the following with jQuery:
$(doc).append('<p>Insert Me</p>'); // again, nothing
So, anyone had any experience in accessing a NativeWindow's inner content programmatically? Any help will be greatly appreciated.
Hmm, so I think I may have found out how to do it...If we amend the original code and add an event listener on the loader:
var newHtmlLoader = air.HTMLLoader.createRootWindow(true, windowOptions, true, windowBounds);
newHtmlLoader.addEventListener(air.Event.COMPLETE, doEventComplete);
newHtmlLoader.load(new air.URLRequest('cover.html'));
You can then interact (assuming you're using jQuery) with the contents of the newly created window by using:
function doEventComplete(event) {
doc = $(event.currentTarget.window.document.body);
doc.append('<p>Insert Me!</p>')
}
:)
I'm not sure this has the effect you intended:
newHtmlLoader.window.opener = window;
var doc = newHtmlLoader.window.opener.document.documentElement;
What is does is set var doc = window.document.documentElement;, so 'doc' is your local document, not the one in the other window.
I think what you want is
var doc = newHtmlLoader.window.document.documentElement;
Do note that this will not work until the document has loaded.

Categories

Resources