Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Output of SmartGWT Img as HTML <object> instead of HTML <img>

    Hi Isomorphic,

    could you output SmartGWT com.smartgwt.client.widgets.Img as HTML <object> instead of HTML <img>?

    The reason behind this:
    My application is multi tenant, where every tenant has the application in their CI, meaning their logo in the top left and all icons in their company color.
    Currently a war-generation for all customers is done like this:
    • 1x javac
    • 1x gwtc
    • ​for every customer​
      • adjust server.properties
      • adjust skin_styles.css
      • create & replace images with a batch job
        • search&replace color strings in svgs
        • call inkscape for svg->png conversion
      • build war
    This image part is only because I currently can't skin SVGs. This is discussed a bit in this old thread.
    What's written there still holds. Additionally it is clear now that browser behavior won't change. See e.g. here and the links in the post.

    Now, if you could output the com.smartgwt.client.widgets.Img (optionally) as <object>, one could style SVGs. see this test case:

    test.svg:
    Code:
    <?xml-stylesheet type="text/css" href="svg-stylesheet.css" ?>
    <svg xmlns="http://www.w3.org/2000/svg"
        xmlns:xlink="http://www.w3.org/1999/xlink">
        <circle cx="25" cy="25" r="24" />
    </svg>

    test.html:
    Code:
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>SVG test</title>
        <link rel="stylesheet" type="text/css" href="svg-stylesheet.css" />
    </head>
    <body>
        <img width=50 height=50 src="test.svg" />
        <object width=50 height=50 data="test.svg" />
    </body>
    </html>

    svg-stylesheet.css:
    Code:
    body    {    border: 0;
                padding: 0;
                margin: 0;
            }
    
    circle    {
                stroke: #006600;
                fill:   #f00;
            }
    In all browsers, this result in this image: Click image for larger version

Name:	SVG_test.png
Views:	331
Size:	1.2 KB
ID:	242873



    If you could change the generated tag, I'd just incorporate the code from svg-stylesheet.css in skin_styles or generate it dynamically at runtime as svg-stylesheet.css.jsp.

    Best regards
    Blama
    Last edited by Blama; 16 Feb 2017, 04:33. Reason: Typos removed

    #2
    This is a handy feature, and looks pretty easy to add to the framework in a generic way (we would basically just allow the SCImgURL type to end in .svg, and this would cause an <object> tag to be generated).

    Just to clarify your comments about behavior not changing: you're saying that browsers will continue to enforce additional restrictions on SVG loaded via an <img> tag that they do not impose on SVG for an <object> tag?

    Also, have you already tested the earliest browser versions that support styling SVG content in this way?

    Comment


      #3
      Hi Isomorphic,

      yes and no.

      As a note:
      The object-tag does not allow the no-content shorthand, see this HTML (css as above, where you will only see one row of SVGs):
      Code:
      <!DOCTYPE html>
      <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
          <title>SVG test</title>
          <link rel="stylesheet" type="text/css" href="svg-stylesheet.css" />
      </head>
      <body>
          <div>
              <img width=50 height=50 src="test.svg" />
              <object width=50 height=50 data="test.svg"/>
          </div>
          <div>
              <img width=50 height=50 src="test.svg" />
              <object width=50 height=50 data="test.svg" />
          </div>
      </body>
      </html>
      MDN reference:
      Tag omission: None, both the starting and ending tag are mandatory.
      Best regards
      Blama

      Comment


        #4
        Regarding browsers:
        I did only test current GC56, FF26 and IE Edge 14. According to caniuse.com, it should work with IE9+ and all other browsers.

        Nevertheless it might be a good idea to output the <img>-tag as fallback-content for the <object>-tag, see here.
        Of course this only makes sense as an option because it only helps if the fallback-PNG is available.

        Best regards
        Blama

        Comment


          #5
          Hi Isomorphic,

          can you tell me if you think that this one will make it to 6.1?
          Are there any blockers I was not aware of? It would be really handy.

          Best regards
          Blama

          Comment


            #6
            Hi Blama
            Yes - this change should make it into 6.1. We're currently doing some unrelated work in this same area and should get this sorted out as part of that change.

            We'll follow up here when this is available for you.

            Regards
            Isomorphic Software

            Comment


              #7
              Hi Isomorphic,

              any update on the status here? I did not test it, but can do so.

              Best regards
              Blama

              Comment


                #8
                Hi Isomorphic,

                I just found this in an unrelated thread:
                Originally posted by Isomorphic View Post
                You should already be able to use real SVGs (with <object> tags being generated rather than <img>) in 6.1 - which version are you testing?
                Thanks a lot,
                Blama

                Comment


                  #9
                  Hi Isomorphic,

                  according to your #7 and the post of yours I linked in #8, this should be working now (using v11.1p_2018-02-21). Unfortunately it does not for me, though.
                  Please see the generated markup for the attached BuiltInDS-based sample. In all three places (Img, ImgButton, MenuItem) the markup is an <img> tag.
                  Can you please double check that this is really working as intended?
                  Those three places and additionally FormItemIcon, SectionStackSection.setIcon(), TabSet.setIcon() are the places where I would want to use this.

                  BuiltInDS.java:
                  Code:
                  package com.smartgwt.sample.client;
                  
                  import com.google.gwt.core.client.EntryPoint;
                  import com.smartgwt.client.Version;
                  import com.smartgwt.client.core.KeyIdentifier;
                  import com.smartgwt.client.data.AdvancedCriteria;
                  import com.smartgwt.client.data.Criterion;
                  import com.smartgwt.client.data.DataSource;
                  import com.smartgwt.client.types.Alignment;
                  import com.smartgwt.client.types.OperatorId;
                  import com.smartgwt.client.util.Page;
                  import com.smartgwt.client.util.PageKeyHandler;
                  import com.smartgwt.client.util.SC;
                  import com.smartgwt.client.widgets.Canvas;
                  import com.smartgwt.client.widgets.IButton;
                  import com.smartgwt.client.widgets.Img;
                  import com.smartgwt.client.widgets.ImgButton;
                  import com.smartgwt.client.widgets.Window;
                  import com.smartgwt.client.widgets.events.ClickEvent;
                  import com.smartgwt.client.widgets.events.ClickHandler;
                  import com.smartgwt.client.widgets.grid.ListGrid;
                  import com.smartgwt.client.widgets.grid.ListGridField;
                  import com.smartgwt.client.widgets.grid.ListGridRecord;
                  import com.smartgwt.client.widgets.layout.HLayout;
                  import com.smartgwt.client.widgets.layout.VLayout;
                  import com.smartgwt.client.widgets.menu.IMenuButton;
                  import com.smartgwt.client.widgets.menu.Menu;
                  import com.smartgwt.client.widgets.menu.MenuItem;
                  
                  public class BuiltInDS extends VLayout implements EntryPoint {
                      private IButton recreateBtn;
                  
                      public void onModuleLoad() {
                          KeyIdentifier debugKey = new KeyIdentifier();
                          debugKey.setCtrlKey(true);
                          debugKey.setKeyName("D");
                  
                          Page.registerKey(debugKey, new PageKeyHandler() {
                              public void execute(String keyName) {
                                  SC.showConsole();
                              }
                          });
                  
                          setWidth100();
                          setHeight100();
                  
                          recreateBtn = new IButton("Recreate");
                          recreateBtn.addClickHandler(new ClickHandler() {
                              @Override
                              public void onClick(ClickEvent event) {
                                  new MyWindow().show();
                              }
                          });
                          addMember(recreateBtn);
                          new MyWindow().show();
                          draw();
                      }
                  
                      private class MyWindow extends Window {
                          public MyWindow() {
                              setWidth(400);
                              setHeight(300);
                              setMembersMargin(0);
                              setModalMaskOpacity(70);
                              setTitle(" (" + Version.getVersion() + "/" + Version.getSCVersionNumber() + ")");
                              setTitle("img- vs object-tag issue" + getTitle());
                              setShowMinimizeButton(false);
                              setIsModal(true);
                              setShowModalMask(true);
                              centerInPage();
                  
                              final ListGrid svgTest = new ListGrid() {
                                  {
                                      setShowRecordComponents(true);
                                      setShowRecordComponentsByCell(true);
                                      setRecordComponentHeight(22);
                                  }
                  
                                  @Override
                                  protected Canvas createRecordComponent(final ListGridRecord record, Integer colNum) {
                                      if ("ahl".equals(this.getField(colNum).getName())) {
                                          ActionHLayout ahl = new ActionHLayout();
                                          return ahl;
                                      }
                                      return null;
                                  };
                              };
                              svgTest.setDataSource(DataSource.get("animals"));
                  
                              ListGridField ahlLGF = new ListGridField("ahl", "SVG Test");
                              ListGridField commonNameLGF = new ListGridField("commonName");
                              ListGridField scientificNameLGF = new ListGridField("scientificName");
                              ListGridField lifeSpanLGF = new ListGridField("lifeSpan");
                              svgTest.setFields(ahlLGF, commonNameLGF, scientificNameLGF, lifeSpanLGF);
                              svgTest.fetchData(new AdvancedCriteria(new Criterion("commonName", OperatorId.ISTARTS_WITH, "A")));
                              addItem(svgTest);
                  
                              Menu mainMenu = new Menu();
                              mainMenu.setWidth(150);
                              MenuItem svgTestItem = new MenuItem("SVG Test");
                              svgTestItem.setIcon("[SKINIMG]dummy.svg");
                              mainMenu.setItems(svgTestItem);
                  
                              IMenuButton mainMenuButton = new IMenuButton("SVG Test", mainMenu);
                              mainMenuButton.setWidth(150);
                              addItem(mainMenuButton);
                  
                              Img svgTestImg = new Img("[SKINIMG]dummy.svg");
                              addItem(svgTestImg);
                          }
                      }
                  
                      public class ActionHLayout extends HLayout {
                          public ActionHLayout() {
                              super(3);
                              setHeight(22);
                              setWidth100();
                              setAlign(Alignment.CENTER);
                  
                              ImgButton svgTestIB = new ImgButton() {
                                  {
                                      setShowDown(false);
                                      setShowRollOver(false);
                                      setLayoutAlign(Alignment.CENTER);
                                      setSrc("[SKINIMG]dummy.SVG");
                                      setHeight(16);
                                      setWidth(16);
                                  }
                              };
                              addMember(svgTestIB);
                          }
                      }
                  }

                  Thank you & Best regards
                  Blama

                  Comment


                    #10
                    You're right - we've just fixed it for tomorrow's builds of 6.1/11.1+

                    Comment


                      #11
                      Hi Isomorphic,

                      using v11.1p_2018-02-25 I can see this is working in two of the cases of the sample. In the one where it is not working the extension is "SVG" (and not "svg"). Perhaps this check should be case insensitive.
                      I'll now test the feature itself (which is now more of a browser support question) and report back where it did work.

                      Best regards
                      Blama

                      Comment


                        #12
                        Yes, we'll fix so the extension is checked insensitively for tomorrow's builds

                        Comment


                          #13
                          Hi Isomorphic,

                          great. A quick check shows that it works as expected with IE11, IE Edge, FF26, Chromium 64, Opera (all Win 10).
                          For others finding this thread: The rule used is not
                          Code:
                          path {fill: red !important;}
                          but
                          Code:
                          svg > path {fill: red !important;}
                          Former one has the disadvantage that you need to be on the stroke itself, while with the latter one, the stroke gets also colored when you are on an empty are of the SVG.

                          This one does also work:
                          Code:
                          svg:hover > path {fill: red !important;}
                          But as I think I'll need more specific rules, as I need different behavior in different cases (e.g. SVG in main ListGrid which has no background color vs context menu, which has a background), I'll go for something like this and make use of the SmartGWT stateful classes:
                          Code:
                          .imgButtonOver > svg > path {fill: red !important;}
                          Best regards
                          Blama

                          Comment


                            #14
                            Hi Isomorphic,

                            it is working, but still has several problems.

                            Please see this sample and the two ImgButtons at the end, one with SVG and one with PNG.

                            The PNG-one does trigger the added click-handlers on click, the SVG-one does not.
                            The same is true for svgTestImg.setShowRollOver(true), which does not result in a CSS-class change on hover.
                            The sample is using images from Tahoe, so best run it in this skin.

                            Code:
                            package com.smartgwt.sample.client;
                            
                            import com.google.gwt.core.client.EntryPoint;
                            import com.smartgwt.client.Version;
                            import com.smartgwt.client.core.KeyIdentifier;
                            import com.smartgwt.client.data.AdvancedCriteria;
                            import com.smartgwt.client.data.Criterion;
                            import com.smartgwt.client.data.DataSource;
                            import com.smartgwt.client.types.Alignment;
                            import com.smartgwt.client.types.OperatorId;
                            import com.smartgwt.client.util.Page;
                            import com.smartgwt.client.util.PageKeyHandler;
                            import com.smartgwt.client.util.SC;
                            import com.smartgwt.client.widgets.Canvas;
                            import com.smartgwt.client.widgets.IButton;
                            import com.smartgwt.client.widgets.ImgButton;
                            import com.smartgwt.client.widgets.Window;
                            import com.smartgwt.client.widgets.events.ClickEvent;
                            import com.smartgwt.client.widgets.events.ClickHandler;
                            import com.smartgwt.client.widgets.events.RightMouseDownEvent;
                            import com.smartgwt.client.widgets.events.RightMouseDownHandler;
                            import com.smartgwt.client.widgets.grid.ListGrid;
                            import com.smartgwt.client.widgets.grid.ListGridField;
                            import com.smartgwt.client.widgets.grid.ListGridRecord;
                            import com.smartgwt.client.widgets.layout.HLayout;
                            import com.smartgwt.client.widgets.layout.VLayout;
                            import com.smartgwt.client.widgets.menu.IMenuButton;
                            import com.smartgwt.client.widgets.menu.Menu;
                            import com.smartgwt.client.widgets.menu.MenuItem;
                            
                            public class BuiltInDS extends VLayout implements EntryPoint {
                                private IButton recreateBtn;
                            
                                public void onModuleLoad() {
                                    KeyIdentifier debugKey = new KeyIdentifier();
                                    debugKey.setCtrlKey(true);
                                    debugKey.setKeyName("D");
                            
                                    Page.registerKey(debugKey, new PageKeyHandler() {
                                        public void execute(String keyName) {
                                            SC.showConsole();
                                        }
                                    });
                            
                                    setWidth100();
                                    setHeight100();
                            
                                    recreateBtn = new IButton("Recreate");
                                    recreateBtn.addClickHandler(new ClickHandler() {
                                        @Override
                                        public void onClick(ClickEvent event) {
                                            new MyWindow().show();
                                        }
                                    });
                                    addMember(recreateBtn);
                                    new MyWindow().show();
                                    draw();
                                }
                            
                                private class MyWindow extends Window {
                                    public MyWindow() {
                                        setWidth(400);
                                        setHeight(300);
                                        setMembersMargin(0);
                                        setModalMaskOpacity(70);
                                        setTitle(" (" + Version.getVersion() + "/" + Version.getSCVersionNumber() + ")");
                                        setTitle("img- vs object-tag issue" + getTitle());
                                        setShowMinimizeButton(false);
                                        setIsModal(true);
                                        setShowModalMask(true);
                                        centerInPage();
                            
                                        final ListGrid svgTest = new ListGrid() {
                                            {
                                                setShowRecordComponents(true);
                                                setShowRecordComponentsByCell(true);
                                                setRecordComponentHeight(22);
                                            }
                            
                                            @Override
                                            protected Canvas createRecordComponent(final ListGridRecord record, Integer colNum) {
                                                if ("ahl".equals(this.getField(colNum).getName())) {
                                                    ActionHLayout ahl = new ActionHLayout();
                                                    return ahl;
                                                }
                                                return null;
                                            };
                                        };
                                        svgTest.setDataSource(DataSource.get("animals"));
                            
                                        ListGridField ahlLGF = new ListGridField("ahl", "SVG Test");
                                        ListGridField commonNameLGF = new ListGridField("commonName");
                                        ListGridField scientificNameLGF = new ListGridField("scientificName");
                                        ListGridField lifeSpanLGF = new ListGridField("lifeSpan");
                                        svgTest.setFields(ahlLGF, commonNameLGF, scientificNameLGF, lifeSpanLGF);
                                        svgTest.fetchData(new AdvancedCriteria(new Criterion("commonName", OperatorId.ISTARTS_WITH, "A")));
                                        addItem(svgTest);
                            
                                        Menu mainMenu = new Menu();
                                        mainMenu.setWidth(150);
                                        MenuItem svgTestItem = new MenuItem("SVG Test");
                                        svgTestItem.setIcon("[SKINIMG]NavigationBar/miniNav_up.svg");
                                        mainMenu.setItems(svgTestItem);
                            
                                        IMenuButton mainMenuButton = new IMenuButton("SVG Test", mainMenu);
                                        mainMenuButton.setWidth(150);
                                        addItem(mainMenuButton);
                            
                                        ImgButton svgTestImg = new ImgButton();
                                        svgTestImg.setSrc("[SKINIMG]NavigationBar/miniNav_up.svg");
                                        svgTestImg.setShowDown(true);
                                        svgTestImg.setShowRollOver(true);
                                        svgTestImg.addClickHandler(new ClickHandler() {
                                            @Override
                                            public void onClick(ClickEvent event) {
                                                SC.say("Clicked SVG");
                                            }
                                        });
                                        svgTestImg.addRightMouseDownHandler(new RightMouseDownHandler() {
                                            @Override
                                            public void onRightMouseDown(RightMouseDownEvent event) {
                                                SC.say("Right-Clicked SVG");
                                            }
                                        });
                                        addItem(svgTestImg);
                            
                                        ImgButton pngTestImg = new ImgButton();
                                        pngTestImg.setSrc("[SKINIMG]DateChooser/arrow_left.png");
                                        pngTestImg.setShowDown(true);
                                        pngTestImg.setShowRollOver(true);
                                        pngTestImg.addClickHandler(new ClickHandler() {
                                            @Override
                                            public void onClick(ClickEvent event) {
                                                SC.say("Clicked PNG");
                                            }
                                        });
                                        pngTestImg.addRightMouseDownHandler(new RightMouseDownHandler() {
                                            @Override
                                            public void onRightMouseDown(RightMouseDownEvent event) {
                                                SC.say("Right-Clicked PNG");
                                            }
                                        });
                                        addItem(pngTestImg);
                                    }
                                }
                            
                                public class ActionHLayout extends HLayout {
                                    public ActionHLayout() {
                                        super(3);
                                        setHeight(22);
                                        setWidth100();
                                        setAlign(Alignment.CENTER);
                            
                                        ImgButton svgTestIB = new ImgButton() {
                                            {
                                                setShowDown(true);
                                                setShowRollOver(true);
                                                setLayoutAlign(Alignment.CENTER);
                                                setSrc("[SKINIMG]NavigationBar/miniNav_up.svg");
                                                setHeight(16);
                                                setWidth(16);
                                            }
                                        };
                                        addMember(svgTestIB);
                                    }
                                }
                            }
                            Best regards
                            Blama

                            Comment


                              #15
                              These have all been fixed for builds dated February 28 and later - SVG images will no longer consume mouse events, so framework handlers will function correctly.

                              Comment

                              Working...
                              X