Application Log Monitor
I keep seeing the use of alert() for debug logging purpose in the forums posts. I like to suggest that user don't do this. First, the use of alert() can disrupts asynchronous code executions and create undesirable side effect in AJAX framework such as GI. Second, GI has a easy to use and configure log monitor that can even be configured to pop up only when you press a special hotkeys combination. Third, logging to the log monitor is as easy as calling "jsx3.log()" instead of "alert()".
To enable the log monitor, follow these steps
- Locate under your "gi-3.8" the file "logger.xml", open this file for editing.
- Uncomment the <handler name="appMonitor1" ... section, while commenting out the "serverNamespace" property. This will enable the handler for any applications
<handler name="appMonitor1" class="jsx3.app.Monitor" require="true"> <!--property name="serverNamespace" value="myApp"/--> <property name="disableInIDE" eval="true" value="true"/> <property name="activateOnHotKey" eval="true" value="false"/> <property name="format" value="%t %n (%l) - %M"/> </handler>
Optional : you can change the property activateOnHotKey to true to allow the use of keys Ctrl+Alt+m to open the log monitor
- Also uncomment the global logger's handler reference
<logger name="global" level="INFO"> <handler-ref name="memory"/> <handler-ref name="console"/> <handler-ref name="ide"/> <handler-ref name="fatal"/> <handler-ref name="appMonitor1"/> </logger>
- Add jsx3.log("some log message"); to your code
- Run your project
Firebug and IE8 developer tools console
As most of the advanced users already know, one of the single most useful tool for web application developer is Firebug, which allows the developer to send message to its log console. Since GI 3.7.1, there is a standard "Console" log handler defined for GI log messages. There's no configuration changes needed to be done on the logger.xml file, simply opening Firebug or IE developer tool will show you the log messages logged by jsx3.log() (or your own jsx3.util.Logger instance)An even easier option
I've added something to GI 3.9 Builder that will make you happy if you use the JavaScript Test Utility (a.k.a. "the scriptlet pad") very much. Now every GI DOM object can be referenced by its name without writing jsx3.GO(), myApp.getJSXByName() or jsx3.ide.getSelected()[0].
Before you had to type:
jsx3.GO("block1").getWidth();
Now you can just type:
block1.getWidth();

Any object visible in the Component Hierarchy in the active component editor is exposed in this manner. If the current editor is not a component editor then no objects are exposed.
Two caveats:
- Only objects whose names are valid JavaScript variable names are exposed. The name must match [\$a-zA-Z_][\$\w]*.
- The behavior of name collisions is not defined. If you have two or more objects in the same component with the same name, the corresponding variable may reference either one.
Here is the JIRA ticket: http://www.generalinterface.org/bugs/browse/GI-705
Enjoy!
Since GI 3.0 debuted in 2005 with the Common Data Format (CDF), GI has enforced a standard XML data schema with a root element called data, nested elements called record and record attributes such as jsxid, jsxtext and jsximg. This schema applies to the classes that implement the jsx3.xml.CDF interface: Select, Tree, Menu, Table and Matrix (and previously List and Grid).
<data jsxid="jsxroot"> <record jsxid="1" jsxtext="One" jsximg="one.gif"/> <record jsxid="2" jsxtext="Two" jsximg="two.gif"/> ... </data>
There are a lot of benefits to a standard data schema like this such as simplicity and interoperability. However, a significant problem is that few services expose data as CDF unless they happened to be designed specifically for GI. Ever since 3.0 we've been coming up with new ways to work around this problem.
All of the CDF controls use XSLT to transform their XML data sources into HTML for rendering. GI 3.0 included the XSLURL, XSLId and XSLString properties (in jsx3.xml.Cacheable), which allowed the default XSLT template to be overridden for a particular instance of one of the CDF classes. So a developer could copy jsxtree.xsl to their project, change, for example, @jsxtext to @label and set an instance of Tree to use the modified template.
This approach had a number of problems, the most significant of which was that the template files were implicitly part of the API of each class and would need to be forward compatible with new releases. If we wanted to add support for a new CDF attribute like @jsxstyle (and then if Tree.js somehow depended on the new template behavior) all previously branched templates would break. When I realized this in the mid 3.x's we decided that supporting custom templates was clearly untenable and I deprecated the functionality.
At the same time I introduced a replacement called XSL transformers. This feature remains supported today though it has its own issues. Using XSL transformers a developer can define one or more XSL transformations to convert the source data to CDF before it goes into the XML application cache and is used to render a CDF control. This has the advantage of being completely declarative (compared with a custom JavaScript schema conversion). It can also modify the structure of the source XML so that the CDF ends up with more or fewer records than the source XML. However, it forces the developer to know XSL, which is not necessarily a common skill for front-end developers.
In 3.9 I've come up with a solution that I think is better than both of the previous approaches. It accomplishes 90% of what XML transformers does and is much simpler. It also enables scenarios that neither of the previous approaches did like:
- The core CDF schema elements and attributes data, record and jsxid can be renamed to anything
- A single data source can drive multiple CDF controls, each with its own view of the data
- No additional files need to be loaded over HTTP
Here's how it works. Every CDF control has a schema property of type jsx3.xml.CDFSchema. The value of this property defines how the control views its CDF datasource. In other words it defines its schema. If the schema property is not set then the control uses the default CDF schema, which is the same as the schema used in 3.0-3.8.
To implement this feature in 3.9 each CDF control, instead of querying its datasource for, let's say, the jsxtext attribute of a record, first queries its schema for the name of the text attribute and then queries its datasource for that attribute of a record. For example, in 3.8 jsx3.gui.Tree included many expressions like
this.getRecordNode(id).getAttribute("jsxtext")
In 3.9 this type of expression has been rewritten as
this.getRecordNode(id).getAttribute(this.getSchema().getProp("text"))
This additional level of indirection allows the CDFSchema object to control how each CDF control views its datasource. The default CDFSchema object returns "jsxtext" from a call to getProp("text"). However, you can modify the schema so that it returns "label" instead. This change would allow you to have a CDF datasource like
<data jsxid="jsxroot"> <record jsxid="1" label="One"/> ... </data>
In 3.9 you can control this new functionality from within Builder. To do so,
- Open or create a component with a CDF control in it, such as Matrix, Tree or Menu.
- Find the CDF Schema component in the Component Libraries palette and drag it onto the CDF control. It may be easier to drag it onto the corresponding node in the Component Hierarchy palette.
- Modify the properties of the schema object in the Properties Editor.
In the Properties Editor you'll find an editable property for each attribute in the default CDF schema. In general, the default value of property abc is jsxabc. CDFSchema also has a property called "record." This property allows you to change the element name of the records in the datasource. You can choose another name, such as "item" or you can use set it to "*" to indicate than any XML element should be interpreted as a data record.

For the CDF schema shown in the screenshot, I will have a datasource that looks like
<items id="jsxroot"> <item id="1" label="One"/> <thing id="2" label="Two"/> <object id="3" label="Three"/> ... </items>
Using the same datasource for two different controls is simply a matter of defining two different CDF schemas for the controls. I've put together a simple example project: GI-702.zip.
Enjoy, and leave any feedback here as a comment on this post or on the JIRA ticket.
