-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Apache Royale Simple(jsonly) is a UI framework I created to take what I've learned working on the Royale project and make something that was strictly focused on HTML/JavaScript. Over the course of working on FlexJS, then Royale, I scribbled ideas and then, while working on the Flex MX emulation components, some ideas started to come together. I made some tentative components and flushed things out. Simple(jsonly) is the result. I have to say it was a liberating experience and quite a lot of fun.
I had three goals in mind:
- Make a framework independent of Basic and Express but based on the Core project work.
- Make a framework that focused on HTML/JavaScript.
- Use MXML to create the DOM, use ActionScript to handle events, and use CSS to make it look good and useful.
Simple(jsonly) achieves all three of these goals. I really wanted the Simple(jsonly) kit classes to generate the DOM structure and leave the layout and styling to CSS. While there is some of that in the code, it is very, very minimal.
I created royale-simple-jsonly repo separately from royale-asjs because I did not want to muck with or mess up the royale-asjs repo, even with a separate branch. I copied what was needed from ASJA and set Simple(jsonly) up to build independently. Once you have downloaded the repo you should be able to build it using ANT, including the examples.
At the moment, Simple(jsonly) does not build with maven, but it should just be a matter of adjusting the
pom.xmlfiles.
I also made some changes to frameworks/projects/Core, specifically to the IUIBase interface. I wound up extending it and consequently, some other classes that depended on it in the Core project were changed. Simple(jsonly) does not use UIBase, but rather UIComponent (name borrowed from Apache Flex) and all components descend from this class.
Once you have built the framework projects you can build the examples:
- ContainersExample shows the various configurations of the Container component.
- ControlsExample shows all of the controls currently in Simple(jsonly).
- ListExample shows DataList and DataTable.
- ShapesExample shows the SVG components.
- WeatherExample demonstrates a working application that retrieves current weather conditions.
There is some styling in the example applications, but most of it is in the themes/Simple/simple.css style sheet.
As of now, Simple(jsonly) has two dozen or so components and a handful of beads. I tried to make enough things to test out my hypothesis and to iron out the foundation. It is fairly easy to write controls and build up the structures. I found that once I got started, the controls were quick to construct, even complex ones like DataTable and DateChooser.
I tried to embrace HTML 5 when things were available on my target browsers: Safari, Chrome, and Firefox. For example, NumericStepper uses <input type="number"> because it is supported on those browsers. Had there not been that support, then NumericStepper would have been more complex (see DateField).
I have tested Simple(jsonly) and the examples on macOS High Sierra using Safari, Chrome, and Firefox browsers. I have not tested it on Windows or any mobile systems.
You will find that Simple(jsonly) has only a handful of beads: some layouts, a few accessories, and controllers mostly. That's because I eschewed view beads and did what many controls in ASJS/Basic do: create the native elements right in the component class. There is not anything in Simple(jsonly) that prevents view beads from existing and that might be how more complex components are created.
The Application has no initial view or view bead. As with Apache Flex, the main application file is itself a component.
There are also no model beads yet. I did not want to create model beads just for the sake of having them. And while it is a nice separation to have models available for data exchange between the component strand and, say a controller bead, I found that having the components use standard interfaces (e.g., ISelectable) worked well enough for me. That's not to say there cannot be models, but they did not make it into this version.
Simple(jsonly) is more "PAYG lite". Since the browser does so much for you, and the HTML elements - especially input - have much already built in, I included those features directly. Not all, but most. For example, there is a PasswordBead that just changes the native <input> element's type to "password". It is mostly to prove that this framework will support PAYG, but perhaps not as aggressively as ASJS/Basic.
My approach to styling and class selectors is pretty simple. Nearly everything can be styled in CSS and Simple(jsonly) relies on that, really. To help that along, I adopted the following policy with respect to the class selector:
- The components have a
classNameListwhich is built using the functions,setClassName(),addClassName(), andremoveClassName(). - The
setClassName()function replaces the classNameList, started it fresh. - The
addClassName()function appends the given class selector name to the end of the list. Most components use this so there is a chain of selectors. - The
replaceClassName()function removes the given name from the list. Using this function withaddClassName()is a convenient way to set and remove selection styles.
Finally, using className= in MXML (or c.className= in ActionScript) places this class selector name as the final name - always. This means if an app developer sets a class name they are sure to have its styles take precedence over any set for the component hierarchy.
A huge difference between Simple(jsonly) and ASJS/Basic is how lists and data are treated. For this, I went in a completely different direction and made use of the "delegate pattern" where the work to build the list is put off some place else, mainly on the shoulders of the app developer. In some ways, the DataItemRendererMapper classes in ASJS/Basic are delegates, but unlike them, Simple(jsonly) cares very little about your data.
When you want to use a DataList (single column) or DataTable (multiple columns) in your app, you build a class that supports the IItemRendererFactory interface. This interface not only provides an itemRenderer to use when needed, it also fills the itemRenderer's data property and provides the list with the number of items required. You can look at the Simple(jsonly) ListExample to see what I mean.
Having the app developer provide the itemRenderers allows the developer to decide which type of itemRenderer to return. For example, for all the rows except rows 3 and 7, an application might display a string, but for rows 3 and 7, maybe a much more complex itemRenderer is needed.
For the DataTable, the app developer also supplies the itemRenderer for the column headers, which can be different for each column. And there are two String-based itemRenderers to make things easy.
ItemRenderers can also be easily written in MXML which is how they are done in the examples.
There is another type of list in Simple(jsonly): list components that require very specific itemRenderers. These are the ButtonBar, SelectList, and ToggleButtonBar. For these lists, the app developer supplies a class that implements the IDataProvider interface. If you look at the ListExample you will see that the main Application is the implementor and provides the required functions.
I decided to take a simpler approach to Panel in Simple(jsonly). In Flex, the Panel was this container that provided a proxy for the internal container that really held the UI elements in the Panel. That is, if you did: panel.getChildAt(3) the Panel really pulled child 3 from its internal content area.
Panel in Simple(jsonly) does not work like that and is more open. Panel is just a shell with a TitleBar and optional ControlBar. You make the Panel's content area whatever you want it to be. If you look at the ContainersExample, you will see that Panel has a VBox as its content area child. If you want to access anything in the Panel, you address your own content area element directly.
<rf:Panel title="Example">
<rf:VBox id="myContent">
<!-- controls and such -->
</rf:VBox>
</rf:Panel>
In the Panel above, the content area is the "myContent" VBox and your ActionScript code interacts with it, not with Panel. You would probably never need to address the Panel itself unless you wanted to change its title dynamically.
Panels can also have content on the left and right sides of the title. You do this with the leftItems and rightItems properties.
<rf:Panel title="Example">
<rf:rightItems>
<rf:Button label="Close" click="closePanel()" />
</rf:rightItems>
<!-- panel content -->
</rf:Panel>
Since the app developer is supplying whatever controls that want in the TitleBar area, the app developer can connect the actions as needed.
HTML5 has the <input type="date"> (and variants) element, but this is not supported on all browsers yet, so I built DateChooser and DateField. These components are almost entirely composed of other Simple(jsonly) components.
The layout of DateChooser uses CSS Grid which is available on the browsers I tested (I did need to update to the latest Firefox revision) and makes it very easy to produce the calendar layout without having to do it in code; a real time saver.
DateField pops up a DateChooser. DateField makes use of the IPopUpHost implemented by Application. I did extend IPopUpHost to have functions to make it easier to pop-up and pop-down the components.
Simple(jsonly) has a small set of SVG components: Rectangle, Ellipse, Polygon, and Path. These components can be used in itemRenderers (the ListExample uses Ellipse) for charts (TBD). You can style (fill, stroke) the components using CSS.
I did not bring in data binding, it is on the to-do list. I modeled the WeatherExample after DataBindingExample (in royale-asjs), but used events in place of data binding.
There are a handful of things I would like to do or change, in no particular order.
- Add data binding.
- Implement row and column spanning as beads to the DataTable.
- Add forecast data to the WeatherExample.
- Add the divided box containers.
- Make iFrames available as a component and somehow allow the loaded app to have access to the main app.
- DataTree, an extension of DataTable.
- A GraphicsContainer to nest and group the SVG components.




