CodeCoupler UI Application
An application is a class derived from the CodeCoupler base class Application
. An application is a
container that, in addition to a content area, optionally also has a title bar, a footer or other
elements. Every component can start an application, even an application itself.
If not maximized the application can be resized and dragged within a certain container. Depending on what component started the application, the container is different:
- If a stage starts an inline application, the container ist the new stage that this instance has created.
- If an application starts an inline application, the container is the content area of the application.
- If a widget starts an inline application, the container is the widget container (not the element).
- If the system starts a stage application, the container can be the current stage or the system container.
Applications started inside the system container, a widget container or inside of another application will started by default normalized and with a titlebar. Stage applications will not have explicit any default values for titlebar and start status. With this you can define in the system wide settings to open all stage applications maximized and without a titlebar and this will not affect only stage applications.
An application will trap the focus inside the focusable elements of the application. If there is no focusable element in the application panel, the panel itself gets focusable and receive the focus.
Start an Application
You cannot initialize an Application
class directly. An application can be started over the
application factory method app(appStart)
which is available in all components.
A system have more than one method to start an application. The default method app(appStart)
is
just a shortcut to start an application in the current stage, using the app
method of the
associated stage instance. Furthermore the method waits for the initialization of the system before
the application is started. This method should be generally used to start an application in the
current stage. The method is accessible from all components with this.env.system.app(appStart)
.
If you do not need to wait for the initialization of the system you can use another method of a
system forceApp(appStart)
. This should be used carefully and will be explained later.
Another method of a system to start systemApp(appStart)
which starts the application inwith the
system container and not the current stage.
Using the factory method in the following situations is problematic:
- Calling
this.app(appStart)
inside theinit
method of an stage instance will throw an exception because the new stage is not ready yet. If needed you should use the method inside thestart
method. Basically you should always pay attention if you start an application inside a stage instance. In case that after this stage an additional stage will be initialized would throw an error because the new stage you created is not empty anymore. - Calling
this.app(appStart)
inside theinit
method of an application instance will throw an exception because the application panel is not ready yet. If needed you should use the method inside thestart
method. - Calling
await this.app(appStart)
inside theboot
method of a system instance will not work because the method will wait for the system initialization and you will wait for the application initialization. Everyone is waiting and nothing happens. You can useawait this.forceApp(appStart)
if really needed. - You should avoid calling
this.app(appStart)
inside theinit
andstart
methods of a system. In case that after thestart
method a stage initialization would throw an error because the current stage is not empty anymore.
The application start definition object appStart
used as argument is optional. If you omit this
just a generic appilcation will be started. The start definition object must be an object and can
have the following properties:
id
: String (Optional)-
If you define an id, no other application with the same id can be started. However, this is only valid in relation to the starting component. Each system, widget, stage or application can start and use their own id's.
If you specify an id which already exists, the method
app()
will return the running app.Instead of using the method
app()
to get an already running application instance, you can use the getterapps
which provide every component to access all applications of the component. app
: Application (Optional)-
The CodeCoupler application class to start. If you omit this just a generic appilcation will be started.
modal
: Boolean (Optional)-
If set to true, the application will be started modal.
options
: Any (Optional)-
The options for the application.
panel
: Object (Optional)-
Configuratin for the jsPanel creation, norally returned by the
init
method of the application. The values here override most of the values defined in the system wide settings and the values returned by theinit
method of the application. More details will be explained later here. ui
: Object (Optional)-
Options that should override the application default value defined in the static
ui
property, for representing the app in the UI. splash
: Object | Boolean (Optional)-
The both splash screen while initializing and while starting the application can be disabled setting the following properties to
false
:1 2 3 4
{ init: false, start: false }
To disable both you can also set
splash
directly tofalse
. settings
: Object (Optional)-
Override here the system wide settings for this application and all child components.
on
: Object (Optional)-
Early bind callbacks to events. In some cases the application fires events within the initialization phase. Instead of using
instance.on("eventname",callback)
after initialization (what would be too late) you can define here callbacks which will be early binded to be able to react to this events.Define just an object with the eventnames as properties and callback functions as values:
1 2 3
on: { eventname: callback }
container
: Internally used-
This property cannot be set and will be used and internally.
container
is the parent HTMLElement of the panel.
Error Handling
If any error occurs the initializing process will stop and an error will be thrown. The application panel will be blocked with a message. If the panel was not created yet, an error hint will be showed.
The error message can be modified in the system wide setting messages.APP.ERROR_INIT
.
In case that the error occurs during the system initialization, the parent system will catch the and handle this error. Please read the chapter "Error Handling" in [./system] for furher informations.
Implement an Application
To implement a new application you have to define a which extends the CodeCoupler class
Application
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
The methods you can provide (all are optional) are splash
, init
and start
.
Initialization and Starting Process
The application will perform the following steps after it has started:
- Start splash screen for the
init
phase. - Call
init
method and wait for the panel configuration object. - Create panel and block it.
- Close first splash screen and start splash screen for the
start
phase. - Call
start
method and wait for the result. - Close second splash screen and unblock panel.
An application is considered initialized once the start
method has been successfully executed.
The Panel Configuration Object
The init
method have to return a panel configuration object which will be be used to create the
application panel. Basically you can use almost all
options for creating a jsPanel with some modifications
explained here.
Default Values and Precedence
The default values of all options will be taken from the system wide settings defined in panel
.
The return value of the init
method can override these option values, but the start definition
object can in turn overwrite those from the init
function.
This generally rule does not apply to all options. In the case of the array based callback options, the return values of the init function have priority. Specifically, these are the following options:
Array based callback options that can be used
onbeforeminimize
, onbeforemaximize
, onbeforenormalize
, onbeforesmallify
,
onbeforeunsmallify
, onfronted
, onminimized
, onmaximized
, onnormalized
,
onsmallified
, onunsmallified
, onstatuschange
, onclosed
Array based callback options will be merged and their functions executed in the following order:
- Callback defined in the return value of the
init
method. - Callback defined in the start defintion object.
- Callback defined in the system wide settings.
Any of these callbacks can return false
to prevent executing any following callback.
The idea behind of this order, is that an application developer should use these functions to implement relevant logic and leave all other options mostly untouched. All the other options mainly concern the appearance of the application. And this should be left to the user of your application.
Special handled Options
The following options can not be set or will be handled in a special way:
dragit
-
Will be set to
false
ifsetStatus
is set tomaximized
andheader
tofalse
. resizeit
-
Will be set to
false
ifsetStatus
is set tomaximized
andheader
tofalse
. If this is not the case and the merged value is notfalse
, all callbacksresizeit.resize
will be merged into an array (start definition object, return value of theinit
method and system wide settings). onbeforeclose
-
Cannot be used. Use instead the component method
async destroy()
. callback
,minimizeTo
,container
,syncMargins
,onwindowresize
andid
-
Cannot be used!
headerTitle
-
Will be set to the name of the application unless otherwise defined. The name will be taken from the
ui
property of the application or the starting definition object. footerToolbar
-
If you specify the property
footerToolbar
as a string, or a function that returns a string you can use shortcuts to create predifined buttons. Read more about this below in "The Footer Toolbar Buttons".
The Panel
In the start
method you have access to the panel via this.panel
. This is basically a jsPanel
object and you can use all the functions provided by the library:
[https://jspanel.de/?#global/overview].
Over this.panel
you have access to the library methods however, it is also the DOM element at the
same time. With this.$panel
you can get this DOM element as a jQuery object.
Some modificatons to the default panel was implemented:
The panel content area is styled with overflow: hidden; isolation: isolate;
. The content area is
not intended to be filled with content. At most, a rigid structure should be built here, otherwise
content should only be provided via widgets. The most simple way ist to initialize one widget in the
container `this.panel.content.
The height of the titlebar will be controlled via font-size
. Set the desired font size directly on
the panel or in the sub-element with the class .jsPanel-headerbar
.
All font sizes in all panel elements will be inherited from the parent DOM settings. Changing the font size in the document should change the font-size in all elements of the panel normally.
The UI Representation
An application class can provide a static field ui
which contains properties of how the
application should be presented. This is used in for displaying the app in titles, launching buttons
or other UI elements. Because these informations are needed before the application is created it is
a static property.
For now only name
and iconHtml
is supported:
1 2 3 4 |
|
name
: String-
The name of the application.
iconHtml
: String-
The html element should inherit the font-size. If you use FontAwesome, you should always add the
fa-fw
class.
Because an application developer maybe do not specify all properties in its application you cannot
just read the static property ui
to get all informations. All applications have a static function
$ui()
which will merge the values of all parent classes. To get the ui informations of an
application use ApplcationClass.$ui()
instead ApplicationClass.ui
.
The Splash Screen
The splash screen will be started twice. The first splash screen starts centered in the container of the application (the current stage for example). The second splash screen starts centered in the application panel and at the same time blocks the panel.
If an inline application starts a splash screen for the init
phase while the parent application
shows also a splash screen, the splash screen of the parent application will temporarly hidden. It
will unhidden as soon as the inline application close its splash screen.
You can modify or disable the splash screens with the method async splash(mode, options)
. The
mode
argument can have the values init
and start
and indicates which of the two screens should
be started. The options
argument contain the option with which the application was started.
The method have to return an object which is basically just a config object of jsPanel hint extension. You can set all options documentation except for the following:
1 2 3 4 5 6 7 |
|
The most simple splash modification is to return an object with one property content
which only
modify the content of the splash screen. The property callback
may also be helpful if you want to
change the content after it has been generated.
1 2 3 4 5 6 7 8 9 10 11 |
|
To disable a splash screen return false
:
1 2 3 |
|
A splash screen works as a "sticky blocking layer". Any other blocking layer will not overlay a splash screen.
If you disable the start
splash screen the application will be blocked using the message from the
system wide setting messages.APP.LOADING
. This blocking works as any other "normal blocking
layer". Any other blocking will be placed over this.
The Footer Toolbar Buttons
Default Buttons
The string in footerToolbar
of the panel configuration returned by the init
method can contain
one of the following placeholders which will be replaced by buttons:
[refresh]
-
Calling
refreshDataUI()
. The defult text of the button is defined as a function and retrieve the value from system wide settingmessages.BUTTONS.REFRESH
. [cancel]
-
Call
cancelDataUI()
and close the application on success. The defult text of the button is defined as a function and retrieve the value from system wide settingmessages.BUTTONS.CANCEL
. [reset]
-
Like [cancel] without closing the application. The defult text of the button is defined as a function and retrieve the value from system wide setting
messages.BUTTONS.RESET
. [saveclose]
-
Call
saveDataUI()
and close the application on success. The defult text of the button is defined as a function and retrieve the value from system wide settingmessages.BUTTONS.SAVECLOSE
. [save]
-
Like [saveclose] without closing the application. The defult text of the button is defined as a function and retrieve the value from system wide setting
messages.BUTTONS.SAVE
. [close]
-
A button which will close the panel. IMPORTANT: Button will just close the panel! There is no check if data is modified!
The defult text of the button is defined as a function and retrieve the value from system wide setting
messages.BUTTONS.CLOSE
. [data]
-
An alias for
[refresh][cancel][reset][save][saveclose]
Button Configuration
You can define own button shortcuts or modify the existing in the system wide setting buttons
.
This is an object with two properties shortcuts
and templates
. Over this.settings
you modify
only the settings which only affect this component.
The buttons that can be used are defined as properties of the object shortcuts
. Use as property
only the name without the bracets. Example: The button that can be used in the footer toolbar as
[refresh]
is defined in the system wide settings under buttons.shortcuts.refresh
.
1 2 3 4 5 6 7 8 9 |
|
If you want to reuse default functions but want to add some functionality to them you can "extend" them by the following way:
1 2 3 4 5 |
|
A button definition have to be an object with the following properties:
class
: String | Function-
Specify here one of the Bootstrap color theme tokens
primary
,success
,warning
,danger
etc. The default button template use this string as suffix tobtn-
for a class name that will be assigned to the button.
The property can be a function that returns the value that have to be used. The function will be executed in the context of the application instance and additionally the instance will be used as first argument.
html
: String | Function-
The inner HTML of the button. The string can contain placeholders like
{0}
,{1}
etc. The string ofhtml
will be merged withtext
like inprintf
functions. If you have defined more than one placeholder you can use an array intext
. You can also omithtml
completely.The property can be a function that returns the value that have to be used. The function will be executed in the context of the application instance and additionally the instance will be used as first argument.
text
: (Mandatory) String | Array | Function-
You have to specify
text
orreplace
to make the shortcut working. If you specify both onlytext
is taken into account.If you have specified
html
this will be the replacement of the placeholders defined inhtml
. In this case it can be an array to define multiple text replacements.If you did not defined
html
you can specify here a simple string that will be used as label for the button.The property can be a function that returns the value that have to be used. The function will be executed in the context of the application instance and additionally the instance will be used as first argument.
click
: async Function(component)-
Specify an async function to call on button click. The function must be async and the application will be blocked while the function is executing. You can disable the blocking with the property
block
.
The function will be executed in the context of the application instance and additionally the instance will be used as first argument.
replace
: String-
You have to specify
text
orreplace
to make the shortcut working. If you specify both onlytext
is taken into account.If you specify this property the button shortcut will just replaced with with string. The string can contain itself button shortcuts that will be interpreted.
This is usefull to define a group of buttons like in the
data
shortcut:1 2 3 4 5 6
{ data: { replace: "[refresh][cancel][reset][save][saveclose]" } }
template
:-
You can define multiple templates which produce from a button configuration a button. If you do not specify a template
default
will be used. See next chapter for more details. block
: String | False-
If you set this to
false
the application will not be blocked while executing the function defined inclick
.Otherwise you can define here the message that will be shown while blocking the application.
If you do not specify
block
the message from the system wide settingsmessages.BUTTONS.BLOCK
will be used.
Button Templates
You can define own templates or modify the existing in the system wide setting buttons.templates
.
The default template that is included is named default
and looks like this:
1 2 3 4 5 6 7 8 9 10 |
|
As you can see a template is a simple string with the placeholders {0}
to {2}
which will be used
as follows:
{0}
-
The string defined in
class
. {1}
-
The name of the button shortcut which have to be used at least in a
data-role
attribute of an element that is clickable. Based on this attribute the click handler will be attached to the element. {2}
-
The content for the button build from
html
andtext
. Thetext
will be HTML escaped, even all elements oftext
if it is an array. {3}
-
HTML escaped
text
. Iftext
is an array all escaped elements joined with a comma.
Some remarks:
- The class
jsPanel-ftr-btn
should be used on a button to avoid acting as drag handle. - The buttons shortcuts will be replaced without any additional spaces around them. Keep this in
mind and define eventual margins (like in the default template with
my-1 mx-2
).
Reference
In addition to the common instance members described in [./component.md] an application has the following:
Instance Events
fronted
,unfronted
-
Will be fired if the panel is set in front of other application panels. In contrast to the "onfronted" event of the panel it will only fired once. The "onfronted" event of the panel will be fired everytime you click inside the panel for example, even if it was allready in front.
As argument the event will have the application instance.
The first "fronted" event will be fired inside of the initialization phase. To catch this first event you have to specify your callback in the start definition object in the property
on
.Every component can have only one application which is fronted. If one application gets fronted all the other applications of this component fire the event
unfronted
.
Instance Methods
close()
,closeForce()
-
Calls the destroy method and closes the panel. These methods are in contrast to the
destroy
method not asynchronous.
The close
method will ask the user if the method hasChanges
do not return false
if he really
want to close the application and loose all changes. The message came from the system wide setting
messages.APP.CONFIRM_CLOSE
.
The application component provide the following ways to close an application:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Instance Getter
panel
-
Returns the current panel of the application.
$panel
-
Returns the current panel of the application as a jsPanel object.
fronted
-
Returns
true
if panel is currently fronted, otherwisefalse
.
Further Topics
Styling
TODO
- Content has "overflow: hidden; isolation: isolate"
Inline Applications of Stages
If you use inline applications in stages you have to pay attention that minimized panels will be attached to the bottom of the stage element. In some cases this could match with the bottom of the current stage. In the bottom area of the current stage will be attached the minimized system applications. The minimized stage applications would thus overlap the minimized system applications.
To avoid this you could define in your stage an explicit area in where the panels should be minimized and make sure that this area do not overlap the bottom of the current stage.
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 8 9 10 |
|
This newly defined area must not have an height defined. If no application is minized the area will collapse and will not be visible.
To define this area you have to insert just a <div>
with the following attributes:
1 |
|