Example 2: Simple text input
Introduction
This topic describes the different steps to implement a simple gICAPI-based web component.
In this example, we will implement a simple text editor based on a
textarea
HTML element.
The dialog code implements a couple of triggers to show how the WEBCOMPONENT
field interacts with the program.
The HTML file is described in detail, and complete code example with program and form file is available at the end of this topic.
HTML code description
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html" charset="utf-8" />
<meta name='viewport' content='initial-scale=1.0, maximum-scale=1.0' />
<style>
html,body {
height:100%;
padding:0;
margin:0;
border:0;
overflow:hidden;
}
textarea#value {
font-weight: bold;
}
textarea {
display: block;
font-family: fixed;
font-size: 10px;
padding:0;
margin:0;
width: 99%;
}
</style>
</head>
<textarea>
element and references the
external JavaScript files in
<script>
elements:<body>
<textarea id="value"></textarea>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/wc_simple.js"></script>
</body>
</html>
The wc_simple.js file
The JavaScript code implementing the gICAPI web component starts with some global variables. These variables will hold information that must be persistent during the web component life:
var has_focus;
The global function onICHostReady()
will be called by the front end, when the
web component interface is ready. The version passed as parameter allows you to check that your
component code is compatible with the current gICAPI framework, and to define and assign the
gICAPI.on*
callback methods (these will be defined in the body of the
onICHostReady()
function:
var onICHostReady = function(version) {
if ( version != "1.0" ) {
alert('Invalid API version');
}
... see below for gICAPI interface functions ...
}
At this point, the gICAPI interface is ready and the gICAPI
object can be
used.
The gICAPI.onData()
function must be implemented to detect web component value
changes done in the program, and to acknowledge SetData()
calls:
gICAPI.onData = function(content) {
$('textarea#value').val(content);
}
onFocus()
function is used to detect that the web component has got or lost
the focus. If the focus is gained, we need to explicitly set the focus to the expected web
component
element: gICAPI.onFocus = function(polarity) {
has_focus = polarity;
if (has_focus) {
$('textarea#value').focus();
}
}
onFocus(true)
is called.window.resize()
event in order to reset the size of
the textarea
element:var wc_resize = function() {
var h = document.body.clientHeight;
try {
var log_height = $('textarea#log').height();
$('textarea#value').height(h - log_height - 10);
} catch (err) {
}
}
...
$(window).resize(function() {
wc_resize();
});
textarea
element gets the focus, we ask the focus to the runtime
system: $("textarea#value").on("focus", function() {
gICAPI.SetFocus();
});
gICAPI.onFlushData()
function, to provide textarea content, when
the front-end needs to send the field value to the runtime
system: gICAPI.onFlushData = function() {
gICAPI.SetData( $('textarea#value').val() );
};
gICAPI.onStateChanged()
function: gICAPI.onStateChanged = function(ps) {
var params = JSON.parse(ps);
if ( params.active ) {
$('textarea#value').attr('disabled', false);
} else {
$('textarea#value').attr('disabled', true);
}
};
onICHostReady()
function, we perform an initial
resize: wc_resize(); // Force adjustment when starting ...
}
Complete source code
File webcomp.per:
LAYOUT (TEXT="Simple web component")
GRID
{
Id: [id ]
[wc ]
[ ]
[ ]
[ ]
[ ]
[tx ]
[ ]
[ ]
[ ]
}
END
END
ATTRIBUTES
EDIT id = FORMONLY.id;
WEBCOMPONENT wc = FORMONLY.wc,
COMPONENTTYPE = "wc_simple",
SCROLLBARS = NONE,
STRETCH = BOTH;
TEXTEDIT tx = FORMONLY.info;
END
File webcomp.4gl:
MAIN
DEFINE rec
RECORD
id INTEGER,
wc STRING,
info STRING
END RECORD
OPTIONS INPUT WRAP, FIELD ORDER FORM
OPEN FORM f1 FROM "webcomp"
DISPLAY FORM f1
LET rec.id = 123
LET rec.wc = "Hello, world!"
INPUT BY NAME rec.* ATTRIBUTES(UNBUFFERED, WITHOUT DEFAULTS)
BEFORE FIELD wc
LET rec.info = "BEFORE FIELD wc=\n", rec.wc
ON CHANGE wc
LET rec.info = "ON CHANGE wc =\n", rec.wc
AFTER FIELD wc
LET rec.info = "AFTER FIELD wc =\n", rec.wc
ON ACTION show
LET rec.info = "ON ACTION show wc=\n", rec.wc
ON ACTION disable
CALL DIALOG.setFieldActive("wc", FALSE)
ON ACTION enable
CALL DIALOG.setFieldActive("wc", TRUE)
ON IDLE 2
LET rec.info = "ON IDLE wc=\n ", rec.wc
END INPUT
END MAIN
File wc_simple.html:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html" charset="utf-8" />
<meta name='viewport' content='initial-scale=1.0, maximum-scale=1.0' />
<style>
html,body {
height:100%;
padding:0;
margin:0;
border:0;
overflow:hidden;
}
textarea#value {
font-weight: bold;
}
textarea {
display: block;
font-family: fixed;
font-size: 10px;
padding:0;
margin:0;
width: 99%;
}
</style>
</head>
<body>
<textarea id="value"></textarea>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/wc_simple.js"></script>
</body>
</html>
File wc_simple.js:
var has_focus = false;
var wc_resize = function() {
var h = document.body.clientHeight;
try {
var log_height = $('textarea#log').height();
$('textarea#value').height(h - log_height - 10);
} catch (err) {
}
}
var onICHostReady = function(version) {
if ( version != "1.0" ) {
alert('Invalid API version');
}
gICAPI.onData = function(content) {
$('textarea#value').val(content);
};
gICAPI.onFocus = function(polarity) {
has_focus = polarity;
if (has_focus) {
$('textarea#value').focus();
}
};
$(window).resize(function() {
wc_resize();
});
$("textarea#value").on("focus", function() {
gICAPI.SetFocus();
});
// $("textarea#value").on("change keyup paste cut", function() {
// gICAPI.SetData( $(this).val() );
// });
gICAPI.onFlushData = function() {
gICAPI.SetFlushedData( $('textarea#value').val() );
};
gICAPI.onStateChanged = function(params) {
var params = JSON.parse(ps);
if ( params.active ) {
$('textarea#value').disabled = false;
} else {
$('textarea#value').disabled = true;
}
};
wc_resize(); // Force adjustment when starting ...
}