Author Topic: Unable to change generated HTML using API  (Read 10317 times)

m2med

  • Newbie
  • *
  • Posts: 17
    • View Profile
Unable to change generated HTML using API
« on: July 29, 2015, 10:38:14 AM »
While testing out our JApplet in AjaxSwing we came across a few instances where we wanted to customize, repair, or improve the generated HTML output. As an example we have JButtons that have no background and appear as text links. But the code to change the mouse cursor to the pointer didn't work and that makes it difficult for a user to understand it was a button. This isn't the best example as we can easily add a style attribute to the custom CSS file for any JButton to set the cursor(which we did), but there are other instances where this isn't possible or not the proper solution. So we looked into modifying the HTML and came across the following few methods. Agile Engine Custom Component Renderers, CreamTec ComponentUtils.getHtmlAttributes(), Adding a ClientProperty directly to the JButton. None of these seemed to have any effect on the generated HTML and we had a few other issues using the custom component renderers method.

First we started with trying the jButton.putClientProperty like so
Code: [Select]
jComponent.putClientProperty("style", "cursor:pointer;");We tried calling that after and before setting the visibility of the jComponent, but it appeared to have no effect on the output. Is there a certain condition that must be met for those changes to be applied?

Next we tried using the ComponentUtils.getHtmlAttributes() to set the style tag, or append the cursor style to an existing tag
Code: [Select]
Map attributes = ComponentUtils.getHtmlAttributes(jComponent);
String style = "style";

String styleTag = (String) attributes.get(style);
if(styleTag == null) {
     attributes.put(style, "cursor:pointer");
} else {
     String styleAppend = styleTag + ";cursor:pointer";
     attributes.put(style, styleAppend);
}
And this also had no effect and the attribute map that was returned seemed to always be empty.

Finally we created a custom component renderer. We didn't want to rewrite all the existing rendering code for the JButton to only change one aspect of the rendering so we attempted to use the default renderer. In the property file we set our custom button we wanted to modify the HTML generated to use this CustomButtonRenderer
Code: [Select]
renderer.com.m2.ajaxswing.demo.MouseButton=com.m2.ajaxswing.demo.CustomButtonRenderer
Code: [Select]
public class CustomButtonRenderer extends DefaultComponentProcessor {

    @Override
    public void renderComponent(ComponentGraphics componentGraphics, Component component) throws Exception {
        System.out.println("Enter CustomButtonRenderer");

        // Render using default rules
        super.renderComponent(componentGraphics,component);
    }
}

This didn't appear to ever be called by AjaxSwing and the button was not visible.

We then changed the class and implemented the ComponentRenderer interface instead. We wanted to duplicate exactly the code used to render the JButton component for the MouseButton as MouseButton just extended JButton and is used only to differentiate between the two buttons in the example. To duplicate the rendering we got the PageRenderer from the ComponentGraphics and then called pageRenderer.getComponentRenderer using the standard JButton class name. We then called the render method of the renderer for the JButton with our MouseButton. This appeared to be called but also had no effect and didn't render the button to the screen.
Code: [Select]
public class CustomButtonRenderer implements ComponentRenderer {

    @Override
    public void initialize() {

    }

    @Override
    public void renderComponent(ComponentGraphics componentGraphics, Component component) throws Exception {
        System.out.println("Enter CustomButtonRenderer");

        System.out.println("renderComponent" + component.getName());
        MouseButton button = (MouseButton) component;

        HTMLPageRenderer pageRenderer = componentGraphics.getPage().getPageRenderer();
        ComponentRenderer defaultRenderer = pageRenderer.getComponentRenderer(JButton.class.getName());
        defaultRenderer.renderComponent(componentGraphics, button);
    }
}
Note that I also tried using JButton.class instead of JButton.class.getName() but it didn't render the button either.

adding the following line of code did render something to the screen when placed inside the renderComponent method posted above, but only rendered the top and left border, and started at the wrong position(bottom right vs. top left). I used this to test to make sure the custom renderer was being used by AjaxSwing
Code: [Select]
componentGraphics.drawRect(button.getX(),button.getY(), button.getWidth(), button.getHeight());

We also tried using the getHtmlAttributes method and the putClientProperty methods inside the renderComponent method, but again had no effect.

And for reference here is our demo JApplet
Code: [Select]
public class ButtonStyling extends JApplet {

    MouseButton styledButton = new MouseButton("Mouse style");
    JButton basicButton = new JButton("Basic button");

    @Override
    public void init() {
        getContentPane().setLayout(new FlowLayout());

        styledButton.setSize(200,100);
        basicButton.setSize(200,100);

        getContentPane().add(styledButton);
        getContentPane().add(basicButton);

        this.setVisible(true);
        styledButton.setVisible(true);
        basicButton.setVisible(true);
    }

    @Override
    public void start() {
        // Apply before or after visibility?
        //DemoUtils.applyCursorAttribute(styledButton);

    }

}

The license page License Matrix states that the standard edition does not have full access to the rendering API, but I have been told otherwise which caused some initial confusion as we assumed the attempts above didn't work due to removed functionality.

So what are we doing wrong? Are we trying to call methods to adjust rendering at incorrect states? Have those methods been deprecated? And why is it that the default renderer doesn't have any effect on the ComponentGraphics object when called? Is there another way to extend, append, or modify the existing rendering logic in Java without rewriting it ourselves?

We are also unsure of how to use the AjaxSwing browser resize for our JApplet. I did see this example Custom Request Filter but I thought resize functionality was already implemented?

Support Team

  • Administrator
  • Hero Member
  • *****
  • Posts: 1074
    • View Profile
Re: Unable to change generated HTML using API
« Reply #1 on: July 29, 2015, 12:10:56 PM »
Hi,

Looks like you've done some good reading and are mostly on the right track. Sorry that some things are not as intuitive, but let me try to help you get the results.

First, I think the issue you are having is that AjaxSwing treats "style" as a special HTML attribute, because it auto-generates it itself. If you want to add custom style properties to components the right way to do it on the web is via external CSS. Give you component an ID and then you can set style properties using #id reference.

If you do want to add something programmatically, you can do it with code like

Code: [Select]
        jComponent.putClientProperty(AjaxSwingProperties.COMPONENT_CSS_STYLE, "cursor:pointer");

Custom renderer - your class seems correct. Look at the log file (you may want to use TraceMgr instead of System.out) of AjaxSwing web server and client processes. Depending on how you configured it it may end up in different files. Double check that there is a log message of AjaxSwing loading your renderer. Free edition only allows 1 custom renderer at a time.

Finally, trying to edit the generated HTML is tricky. AjaxSwing doesn't send the entire page back to the browser, it only sends updated parts in JSON format. You can implement one of the RequestFilter interfaces and tweak HTML there, but it's probably a harder to maintain solution. Although if all you need is a few tweaks and you want them all in one place that's an option too.

Support Team

  • Administrator
  • Hero Member
  • *****
  • Posts: 1074
    • View Profile
Re: Unable to change generated HTML using API
« Reply #2 on: July 29, 2015, 12:11:43 PM »
You should also consider getting a license and requesting source code. Will make your investigations a lot easier.

m2med

  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: Unable to change generated HTML using API
« Reply #3 on: July 29, 2015, 02:08:06 PM »
Quote
First, I think the issue you are having is that AjaxSwing treats "style" as a special HTML attribute, because it auto-generates it itself. If you want to add custom style properties to components the right way to do it on the web is via external CSS. Give you component an ID and then you can set style properties using #id reference.
So for this button example it is relating to the style attribute and is easily doable using the custom CSS as I said we are doing.
Quote
This isn't the best example as we can easily add a style attribute to the custom CSS file for any JButton to set the cursor(which we did), but there are other instances where this isn't possible or not the proper solution.
So I will find a different attribute that will need modifications and attempt to modify those.

I didn't include the test of me trying the
Code: [Select]
jComponent.putClientProperty(AjaxSwingProperties.COMPONENT_CSS_STYLE, "cursor:pointer"); but I did attempt that, and once again just now to no avail. What should I be doing to debug the ignored putClientProperty?

As for the custom renderer I didn't see any log line relating to the loading of the custom renderer class but I did see my trace manager log statement
Code: [Select]
2015/07/29 13:47:48:858 : AWT-EventQueue-1 : Enter CustomButtonRenderer
So that still leaves the question as to why the default component renderer does not render anything to the screen?

And even though the entire page isn't sent back in the JSON request to the browser I am not sure how that should affect the logic inside a custom component renderer as AjaxSwing handles the incremental updates to the browser? Parsing generated HTML and making modifications to it is not a feasible solution. And not being able to call existing HTML generation code for common components will slow down development as we will need to reimplement existing functionality in house. Is it possible to send over a single source code file for the default rendering component to help us investigate the issue?

Currently we are walking through and trying to get a feel for the API and how maintainable of a solution AjaxSwing provides for repairing and updating custom swing components. This is what will go into the decision making process of purchasing a license.

Support Team

  • Administrator
  • Hero Member
  • *****
  • Posts: 1074
    • View Profile
Re: Unable to change generated HTML using API
« Reply #4 on: July 31, 2015, 07:36:06 AM »
Quote
I didn't include the test of me trying the
Code: [Select]
jComponent.putClientProperty(AjaxSwingProperties.COMPONENT_CSS_STYLE, "cursor:pointer"); but I did attempt that, and once again just now to no avail. What should I be doing to debug the ignored putClientProperty?
This feature was available in AjaxSwing v.3. We're going to add it in the next release of v.4

Quote

As for the custom renderer I didn't see any log line relating to the loading of the custom renderer class but I did see my trace manager log statement
Code: [Select]
2015/07/29 13:47:48:858 : AWT-EventQueue-1 : Enter CustomButtonRenderer
So that still leaves the question as to why the default component renderer does not render anything to the screen?

And even though the entire page isn't sent back in the JSON request to the browser I am not sure how that should affect the logic inside a custom component renderer as AjaxSwing handles the incremental updates to the browser? Parsing generated HTML and making modifications to it is not a feasible solution. And not being able to call existing HTML generation code for common components will slow down development as we will need to reimplement existing functionality in house. Is it possible to send over a single source code file for the default rendering component to help us investigate the issue?

If you set trace level to 10, you should see in the log file smth. like:
Quote
2015/07/31 14:32:51:501 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Initializing custom renderers...
2015/07/31 14:32:51:502 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Loading custom renderer com.creamtec.ajaxswing.v4.render.SnapshotRenderer for class r.net.sf.jasperreports.view.JRViewer$PageRenderer
2015/07/31 14:32:51:512 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Sucessfully registered renderer
2015/07/31 14:32:51:512 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Loading custom renderer com.creamtec.ajaxswing.v4.render.SnapshotRenderer for class r.org.jfree.chart.ChartPanel
2015/07/31 14:32:51:516 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Sucessfully registered renderer
2015/07/31 14:32:51:518 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Loading custom renderer com.creamtec.ajaxswing.v4.render.DefaultComponentProcessor for class r.java.awt.Component
2015/07/31 14:32:51:542 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Sucessfully registered renderer
2015/07/31 14:32:51:604 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Loading custom renderer com.creamtec.ajaxswing.v4.render.DefaultJFileChooserProcessor for class r.javax.swing.JFileChooser
2015/07/31 14:32:51:606 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Sucessfully registered renderer

m2med

  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: Unable to change generated HTML using API
« Reply #5 on: August 10, 2015, 09:57:48 AM »

Quote

As for the custom renderer I didn't see any log line relating to the loading of the custom renderer class but I did see my trace manager log statement
Code: [Select]
2015/07/29 13:47:48:858 : AWT-EventQueue-1 : Enter CustomButtonRenderer
So that still leaves the question as to why the default component renderer does not render anything to the screen?

And even though the entire page isn't sent back in the JSON request to the browser I am not sure how that should affect the logic inside a custom component renderer as AjaxSwing handles the incremental updates to the browser? Parsing generated HTML and making modifications to it is not a feasible solution. And not being able to call existing HTML generation code for common components will slow down development as we will need to reimplement existing functionality in house. Is it possible to send over a single source code file for the default rendering component to help us investigate the issue?

If you set trace level to 10, you should see in the log file smth. like:
Quote
2015/07/31 14:32:51:501 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Initializing custom renderers...
2015/07/31 14:32:51:502 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Loading custom renderer com.creamtec.ajaxswing.v4.render.SnapshotRenderer for class r.net.sf.jasperreports.view.JRViewer$PageRenderer
2015/07/31 14:32:51:512 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Sucessfully registered renderer
2015/07/31 14:32:51:512 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Loading custom renderer com.creamtec.ajaxswing.v4.render.SnapshotRenderer for class r.org.jfree.chart.ChartPanel
2015/07/31 14:32:51:516 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Sucessfully registered renderer
2015/07/31 14:32:51:518 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Loading custom renderer com.creamtec.ajaxswing.v4.render.DefaultComponentProcessor for class r.java.awt.Component
2015/07/31 14:32:51:542 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Sucessfully registered renderer
2015/07/31 14:32:51:604 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Loading custom renderer com.creamtec.ajaxswing.v4.render.DefaultJFileChooserProcessor for class r.javax.swing.JFileChooser
2015/07/31 14:32:51:606 : http-8041-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Sucessfully registered renderer

I do see this in the logs
Code: [Select]
2015/08/10 09:53:09:435 : http-8040-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Loading custom renderer com.medfx.ajaxswing.demo.CustomButtonRenderer for class r.com.medfx.ajaxswing.demo.MouseButton
2015/08/10 09:53:09:437 : http-8040-1 : [com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer] Sucessfully registered renderer

And I see custom logging statements added to the renderComponent method

Code: [Select]
2015/08/10 09:53:23:592 : AWT-EventQueue-1 : class com.medfx.ajaxswing.demo.CustomButtonRenderer: Enter CustomButtonRenderer
2015/08/10 09:53:23:592 : AWT-EventQueue-1 : class com.medfx.ajaxswing.demo.CustomButtonRenderer: renderComponent StyleButton
2015/08/10 09:53:23:592 : AWT-EventQueue-1 : class com.medfx.ajaxswing.demo.CustomButtonRenderer: com.creamtec.ajaxswing.rendering.html.positioned.AjaxPageRenderer@2388f2c1
2015/08/10 09:53:23:592 : AWT-EventQueue-1 : class com.medfx.ajaxswing.demo.CustomButtonRenderer: com.creamtec.ajaxswing.v4.render.DefaultComponentProcessor@73f96f20
2015/08/10 09:53:23:592 : AWT-EventQueue-1 : class com.medfx.ajaxswing.demo.CustomButtonRenderer: com.creamtec.ajaxswing.v4.ComponentGraphics[font=javax.swing.plaf.FontUIResource[family=Dialog,name=Dialog,style=bold,size=12],color=sun.swing.PrintColorUIResource[r=51,g=51,b=51]]

Any other ideas why I cannot extend or duplicate the default functionality? Do I need to call the initialize method of the default rendering class?

jyonkheel@yahoo.com

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: Unable to change generated HTML using API
« Reply #6 on: August 11, 2015, 01:52:13 PM »
probably because JDK 7 does not support all your programming needs, also don't buy the licence i learned that the hard way the company i am working for are shifting now to JSP/HTML5, the proper way to support mobile and web at the same time

m2med

  • Newbie
  • *
  • Posts: 17
    • View Profile
Re: Unable to change generated HTML using API
« Reply #7 on: August 25, 2015, 03:07:47 PM »
Along the same vein is it not possible to add a class to a generated div element? I need to use a class to add a custom css icon and adding the class after using jQuery is not maintainable and has to be applied after the page has been loaded.