Dynamic Informational Message Box
-
- Experienced User
- Posts: 165
- Joined: Wed Dec 11, 2013 10:40 am
- First Name: Dave
- Last Name: Clark
- Company Name: WinWholesale, Inc.
- Phone: 937-294-5331
- Address 1: 31101 Kettering Blvd.
- City: Dayton
- State / Province: Outside Canada/USA
- Zip / Postal Code: 45439
- Country: United States
- Contact:
Dynamic Informational Message Box
We have need of a dynamic informational message box which all of our applications can use. We can't use the widget-based message support built into Profound UI or the screen-based message support because those always show up as error messages.
We may want just an informational message or one that isn't tied to a widget. I know we could manually create such a message box in each screen, but we'd prefer that this be done dynamically just by calling a function in our custom.js file. So, we get to my question...
What would be the recommended means of creating such a dynamic widget within the Profound UI page? Note that I do have advanced JavaScript skills which I can use to create advanced HTML structures on the fly. But, I want this to also work well with Profound UI. Your recommendation? Thanks.
We may want just an informational message or one that isn't tied to a widget. I know we could manually create such a message box in each screen, but we'd prefer that this be done dynamically just by calling a function in our custom.js file. So, we get to my question...
What would be the recommended means of creating such a dynamic widget within the Profound UI page? Note that I do have advanced JavaScript skills which I can use to create advanced HTML structures on the fly. But, I want this to also work well with Profound UI. Your recommendation? Thanks.
-
- Experienced User
- Posts: 2711
- Joined: Wed Aug 01, 2012 8:58 am
- First Name: Scott
- Last Name: Klement
- Company Name: Profound Logic
- City: Milwaukee
- State / Province: Wisconsin
Re: Dynamic Informational Message Box
There are a bunch of different options here. Not exactly sure what you're after? By "widget based message support", I assume you're referring to the "error messages" property on the widgets? Yes, that's always styled as an error message. But, it is hardly the only way to display messages... you could simply use an output field... or an output field on a dialog with an OK button, etc.
So, if you want to drive this from RPG (which is the way most of our customers would do it, and seems the most practical) you could write an RPG program that just takes the message as a parameter... maybe the message type (info, warning, error, whatever) and maybe also returns replies, if that's desired. (I'm thinking like the MessageBox() API in Windows). So this would just be a standalone RPG progam you can CALL when you want to show a message box. The RPG program would have it's own display file with just the one record format you need to display this, and it would have keywords like "assume" and "Show as window" to make it overlay existing screens. This is probably the best approach.
If you wanted to drive this from JavaScript, (which I don't think is ideal here, since the flow of the application may change based on the response, and it just makes more sense to drive the flow of the application from RPG vs. JavaScript) then you could simply use standard DOM calls to whack a div into the screen, position it, etc. Standard dynamic HTML stuff... and return the result from your function so that JS routines could use it... This might make sense if you're coding a lot of the program logic into the display file with JavaScript for some reason.
So, if you want to drive this from RPG (which is the way most of our customers would do it, and seems the most practical) you could write an RPG program that just takes the message as a parameter... maybe the message type (info, warning, error, whatever) and maybe also returns replies, if that's desired. (I'm thinking like the MessageBox() API in Windows). So this would just be a standalone RPG progam you can CALL when you want to show a message box. The RPG program would have it's own display file with just the one record format you need to display this, and it would have keywords like "assume" and "Show as window" to make it overlay existing screens. This is probably the best approach.
If you wanted to drive this from JavaScript, (which I don't think is ideal here, since the flow of the application may change based on the response, and it just makes more sense to drive the flow of the application from RPG vs. JavaScript) then you could simply use standard DOM calls to whack a div into the screen, position it, etc. Standard dynamic HTML stuff... and return the result from your function so that JS routines could use it... This might make sense if you're coding a lot of the program logic into the display file with JavaScript for some reason.
-
- Experienced User
- Posts: 165
- Joined: Wed Dec 11, 2013 10:40 am
- First Name: Dave
- Last Name: Clark
- Company Name: WinWholesale, Inc.
- Phone: 937-294-5331
- Address 1: 31101 Kettering Blvd.
- City: Dayton
- State / Province: Outside Canada/USA
- Zip / Postal Code: 45439
- Country: United States
- Contact:
Re: Dynamic Informational Message Box
OK, I've started down the road of a native JavaScript solution. It *is* driven by RPG; but, not directly. There will be a hidden text box which can receive a string of HTML from RPG. In the onload event for the screen, I have this code:
The reason for the empty first parm is because this function will serve double-duty. The first parm is for a widget id that the programmer chose to code directly into their screen. Thus, if a value for that parm is omitted, then the function will build its own, dynamic widget. The third parm is for a jQuery fadeout() and the fourth parameter is for positioning. Options include 'top', 'bottom', 'left', 'right', and 'center' in addition to the 'mouse' option shown.
Still working on the positioning, but this is what I have for building it so far:
Note that I am placing it in the "5250" container. What is the name of the container when there is no Genie session? ...or, is there a PUI-provided means of obtaining the container name currently in use so that I don't have to hard-code it? Thanks.
Code: Select all
if (get("htmlMessage") > '')
{
wob.displayMessageText('', get("htmlMessage"), 3000, 'mouse');
}
Still working on the positioning, but this is what I have for building it so far:
Code: Select all
dyno = document.createElement("div"); // then, (re)create it
dyno.setAttribute("id", dynoId);
dyno.setAttribute("class", "dropShadow");
dyno.style.position = "absolute";
dyno.style.left = "0px";
dyno.style.top = "0px";
dyno.style.background = "no-repeat white";
dyno.style.border = "3px solid green";
dyno.style.borderRadius = "3px";
dyno.style.font = "bold normal 12px 'Arial, sans-serif'";
dyno.style.padding = "0px 5px 5px 0px"; // bottom, left, right, top
dyno.style.width = "200px";
dyno.style.zIndex = "200";
dyno.innerHTML = messageText; // set value of dynamic widget
getObj("5250").appendChild(dyno); // add to page
$("#" + dynoId).fadeOut(fadeDuration); // jQuery method to fade object
- David
- Profound Logic Staff Member
- Posts: 690
- Joined: Fri Jan 04, 2008 12:11 pm
- First Name: David
- Last Name: Russo
- Company Name: Profound Logic Software
- Contact:
Re: Dynamic Informational Message Box
You'll want to use 'pui.runtimeContainer', rather than referencing the div "5250" by id. The div is called something else when running outside of Genie. This property always has a reference to the correct div element, regardless of how you run the session.
-
- Experienced User
- Posts: 165
- Joined: Wed Dec 11, 2013 10:40 am
- First Name: Dave
- Last Name: Clark
- Company Name: WinWholesale, Inc.
- Phone: 937-294-5331
- Address 1: 31101 Kettering Blvd.
- City: Dayton
- State / Province: Outside Canada/USA
- Zip / Postal Code: 45439
- Country: United States
- Contact:
Re: Dynamic Informational Message Box
So I can code the following?
Code: Select all
pui.runtimeContainer.appendChild(dyno); // add to page
-
- Experienced User
- Posts: 165
- Joined: Wed Dec 11, 2013 10:40 am
- First Name: Dave
- Last Name: Clark
- Company Name: WinWholesale, Inc.
- Phone: 937-294-5331
- Address 1: 31101 Kettering Blvd.
- City: Dayton
- State / Province: Outside Canada/USA
- Zip / Postal Code: 45439
- Country: United States
- Contact:
Re: Dynamic Informational Message Box
I tried that and it is working. Thanks.
-
- Experienced User
- Posts: 165
- Joined: Wed Dec 11, 2013 10:40 am
- First Name: Dave
- Last Name: Clark
- Company Name: WinWholesale, Inc.
- Phone: 937-294-5331
- Address 1: 31101 Kettering Blvd.
- City: Dayton
- State / Province: Outside Canada/USA
- Zip / Postal Code: 45439
- Country: United States
- Contact:
Re: Dynamic Informational Message Box
If anyone is interested, I'm attaching the code I created for this. It can be used in three ways -- to load and animate an existing message widget defined in the page, to animate a dynamic widget driven from your RPG code, and to animate a dynamic widget driven by JavaScript only. There is also a couple of CSS definitions that go with it. Lastly, jQuery™ is required for the fade animation effects.
NOTE: "wob" is the name of our Genie skin so you can change that part to what you want.
To use the dynamic widget driven from your RPG code, you can use something similar to the following in your screen "onload" event -- which this code uses txtMessage as a hidden text box bound to your RPG.
To use the dynamic widget driven by JavaScript only, the following is an example using the grid onrowclick event. In my case, the function I call here is one which counts the currently selected grid rows and if more than one is selected the dynamic message function is called.
These are the CSS definitions:
These are all the functions required:
NOTE: "wob" is the name of our Genie skin so you can change that part to what you want.
To use the dynamic widget driven from your RPG code, you can use something similar to the following in your screen "onload" event -- which this code uses txtMessage as a hidden text box bound to your RPG.
Code: Select all
wob.displayMessageText(null, getObj("txtMessage"), 0, 'center');
Code: Select all
window.setTimeout(function()
{
var cnt = wob.countGridRowSelections("ACLKUV1S", "*IN30");
if (cnt > 1)
{
changeElementValue("txtMessage", cnt + " selections active.");
wob.displayMessageText(null, getObj("txtMessage"), 0, "mouse", event);
}
}, 100);
Code: Select all
.dropShadow {
-moz-box-shadow: 5px 5px 3px #333;
-webkit-box-shadow: 5px 5px 3px #333;
box-shadow: 5px 5px 3px #333;
}
#dynoInfoBox {
background: no-repeat white;
border: 3px solid green;
border-radius: 3px;
color: black;
font-family: Arial, sans-serif;
font-size: 12px;
font-weight: bold;
padding: 5px 10px 5px 10px; /* top, left, bottom, right */
z-index: 200;
}
Code: Select all
/* ================================================================================
displayMessageText() sets the value of a widget to the specified message text,
makes the widget visible, and then fades the widget to
invisibility -- ready for the next go-round. If you do
NOT want a fade effect, specify -1 for the fade duration.
Optionally, the first parm can be supplied as null and
this causes a dynamic message box to be built, displayed,
and faded automatically. The position and event parms
apply only to this dynamic message box; where: position
can be specified as 'center', 'top', 'bottom', 'left',
or 'right'. Alternatively, if there is an associated
mouse event, then position may be specified as 'mouse'
to align the popup message with the mouse at the time
the mouse event occurred. Supply the event object parm
in this case.
*/
wob.displayMessageText = function(widgetId, msgSource, fadeDuration, position, event)
{
var messageText = get(msgSource.id); // get any message text
changeElementValue(msgSource.id, ""); // clear any message text
if (messageText <= " ") return; // if no message text, then exit
var fadeDefault = 2000 + (Math.ceil((messageText.split(/\s+/)).length / 2) * 1000);
fadeDuration = (fadeDuration) ? fadeDuration : fadeDefault; // set default if missing
if (widgetId) // if Profound widget identified
{
changeElementValue(widgetId, messageText); // set value of widget
applyProperty(widgetId, "visibility", "visible"); // show the widget
$("#"+widgetId).fadeIn(0); // jQuery method to show object
if (fadeDuration > 0) // if fade out requested
{
$("#"+widgetId).fadeOut(fadeDuration); // jQuery method to fade object
}
}
else // else, create dynamic widget
{
fadeDuration = (fadeDuration > 0) ? fadeDuration : fadeDefault; // force a fadeout
position = (!position) ? 'center'
: (event && position == 'mouse') ? position
: (('top,bottom,left,right,center').indexOf(position) > -1) ? position
: 'center'; // need a default position?
var offsets = wob.getContainerOffsets(msgSource.parentNode, event); // get page and mouse offsets
var dynoId = "dynoInfoBox"; // set id of dynamic widget
var dyno = document.getElementById(dynoId); // get pointer to dynamic widget
if (dyno && dyno.id == dynoId) // if dynamic widget already exists
{
dyno.parentNode.removeChild(dyno); // trash it
}
dyno = document.createElement("div"); // then, (re)create it
dyno.setAttribute("id", dynoId);
dyno.setAttribute("class", "dropShadow");
dyno.style.position = "absolute";
dyno.style.left = "300px";
dyno.style.top = "200px";
if (messageText.length > 50) // if this is a long message
{
dyno.style.width = "280px"; // limit width of message box
dyno.style.whiteSpace = "pre-wrap"; // and perform word wrap
}
else // else default width to length of text
{
dyno.style.whiteSpace = "nowrap"; // and no word wrap
}
dyno.style.visibility = "hidden"; // initial setting to allow repositioning
dyno.innerHTML = '<img style="float: none; width: 16px; height: 16px; vertical-align: text-bottom;"'
+ ' src="/profoundui/proddata/images/icons/information.png"></img> ';
dyno.innerHTML += messageText; // set value of dynamic widget
dyno = msgSource.parentNode.appendChild(dyno); // add to container
switch (position)
{
case 'mouse':
dyno.style.left = (offsets.mouseLeft + 10) + "px";
dyno.style.top = (offsets.mouseTop - dyno.offsetHeight - 10) + "px";
break;
case 'center':
dyno.style.left = (Math.floor(offsets.width / 2) - Math.floor(dyno.offsetWidth / 2)) + "px";
dyno.style.top = (Math.floor(offsets.height / 2) - dyno.offsetHeight) + "px";
break;
case 'top':
dyno.style.left = (Math.floor(offsets.width / 2) - Math.floor(dyno.offsetWidth / 2)) + "px";
dyno.style.top = "5px";
break;
case 'left':
dyno.style.left = "5px";
dyno.style.top = (Math.floor(offsets.height / 2) - dyno.offsetHeight) + "px";
break;
case 'bottom':
dyno.style.left = (Math.floor(offsets.width / 2) - Math.floor(dyno.offsetWidth / 2)) + "px";
dyno.style.top = (offsets.height - dyno.offsetHeight - 5) + "px";
break;
case 'right':
dyno.style.left = (offsets.width - dyno.offsetWidth - 5) + "px";
dyno.style.top = (Math.floor(offsets.height / 2) - dyno.offsetHeight) + "px";
break;
default:
}
dyno.style.visibility = "visible";
$("#" + dynoId).fadeIn(0).fadeOut(fadeDuration); // jQuery method to fade object
}
}
/* ================================================================================
getContainerOffsets() returns an object describing various dimension and
position attributes for the specified container object.
Optionally, if the event object parameter is passed, the
returned object also includes adjusted mouse offsets.
*/
wob.getContainerOffsets = function(container, event)
{
var offsets = wob.browserPageOffsets(); // get scrolled offset of page
offsets.client = wob.browserClientArea(); // get client area of page
var ele = container; // starting from the container
do // calculate container's offsets
{
offsets.left += ele.offsetLeft; // include left offset
offsets.top += ele.offsetTop; // include top offset
}
while (ele = ele.offsetParent); // which includes all offset parents
var coord = pui.getDimensions(container); // get coordinates of effective container dimensions
offsets.width = coord.x2 - coord.x1; // calculate container width
offsets.height = coord.y2 - coord.y1; // calculate container height
if (event) // if an event object was included
{ // then set offset for mouse coordinates
offsets.mouseLeft = getMouseX(event) - offsets.left;
offsets.mouseTop = getMouseY(event) - offsets.top;
}
return offsets; // return offsets to caller
}
/* ================================================================================
browserClientArea() returns the width and height of the displayable area of the
browser page that does not require scrolling.
*/
wob.browserClientArea = function()
{
if (document.documentElement
&& typeof document.documentElement.clientWidth != 'undefined')
{
return { width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight };
}
if (typeof self.innerWidth != 'undefined')
{
return { width: self.innerWidth,
height: self.innerHeight };
}
if (document.body
&& typeof document.body.clientWidth != 'undefined')
{
return { width: document.body.clientWidth,
height: document.body.clientHeight };
}
return null;
}
/* ================================================================================
browserPageOffsets() returns the left, top, width, and height offsets of the
scrolled browser page: where, left and top will be zero
if the page is not scrolled.
*/
wob.browserPageOffsets = function()
{
if (document.documentElement
&& typeof document.documentElement.scrollTop != 'undefined')
{
return { left: document.documentElement.scrollLeft,
top: document.documentElement.scrollTop,
width: document.documentElement.scrollWidth,
height: document.documentElement.scrollHeight };
}
if (typeof self.pageXOffset != 'undefined')
{
return { left: self.pageXOffset,
top: self.pageYOffset,
width: document.width,
height: document.height };
}
if (document.body
&& typeof document.body.scrollLeft != 'undefined')
{
return { left: document.body.scrollLeft,
top: document.body.scrollTop,
width: document.body.scrollWidth,
height: document.body.scrollHeight };
}
return null;
}
Last edited by DaveLClarkI on Fri Jan 24, 2014 10:52 am, edited 2 times in total.
-
- Experienced User
- Posts: 165
- Joined: Wed Dec 11, 2013 10:40 am
- First Name: Dave
- Last Name: Clark
- Company Name: WinWholesale, Inc.
- Phone: 937-294-5331
- Address 1: 31101 Kettering Blvd.
- City: Dayton
- State / Province: Outside Canada/USA
- Zip / Postal Code: 45439
- Country: United States
- Contact:
Re: Dynamic Informational Message Box
The above post has been corrected as a result of new things I've learned in this process.
Who is online
Users browsing this forum: No registered users and 0 guests