Menu

Pseudo classes

sjuschka
2013-04-25
2013-10-26
  • sjuschka

    sjuschka - 2013-04-25

    Pseudo classes

    Hi,
    i tried to use css pseudo classes like ":hover" or ":active" within my css delarations, but the NodeData is always null. e.g. for

    NodeData data = decl.get(element, PseudoDeclaration.HOVER);
    

    So i checked out the trunk from svn and saw that all pseudo classes, except the ":link" for "a"-tags are filtered out because of the following code:

    Selector.java

    public enum PseudoDeclaration
    {
        ACTIVE("active", false),
        FOCUS("focus", false),
        HOVER("hover", false),
        LINK("link", false),
    ...
        private PseudoDeclaration(String value, boolean isElement) {
            this.value = value;
            this.element = isElement;
        }
    
        public String value() {return value;}
    
        public boolean isPseudoElement() {return element;}
    

    SelectorImpl.java

    default:
        if (declaration.isPseudoElement() || //match all pseudo elements and the LINK pseudo class for links
                (e.getTagName().equalsIgnoreCase("a") && declaration == PseudoDeclaration.LINK))
        return true;
    

    Are there any reasons for that? I tried the following and it works fine:

    • set HOVER("hover", true) in Selector.java
    • extended the "data/advanced/style.css" with "#bp:hover { background: center left; }"
    • extended the AdvancedCSS.testBP() with the line "NodeData data2 = decl.get(bp, PseudoDeclaration.HOVER);"
    • data2 contains the expected hover background declarations
     
  • Radek Burget

    Radek Burget - 2013-04-28

    Hi, thanks for mentioning this. It seems that this part of the code is a bit outdated. I will take a closer look on this and will fix this. Or if you have already some solution, I will be grateful for a patch.

     
    • sjuschka

      sjuschka - 2013-04-29

      a quick solution would be to just change this in Selector.java:

      from

      public enum PseudoDeclaration
      {
          ACTIVE("active", false),
          FOCUS("focus", false),
          HOVER("hover", false),
          LINK("link", false),
          VISITED("visited", false),
      

      to

      public enum PseudoDeclaration
      {
          ACTIVE("active", true),
          FOCUS("focus", true),
          HOVER("hover", true),
          LINK("link", true),
          VISITED("visited", true),
      

      but i'm not sure, if there are any side-effects

       
  • sjuschka

    sjuschka - 2013-06-21

    is there any progress on this topic, can you adapt my approach? thx lot!

     
  • Radek Burget

    Radek Burget - 2013-06-23

    I am sorry for the delay, I have been quite busy recently. Unfortunately, it is necessary to distinguish between the pseudoclasses and pseudoelements using the true/false flags because of the rule specificity computation. But it shouldn't be too difficult to implement the functionality properly. I'll try to do this asap.

     
    • sjuschka

      sjuschka - 2013-06-28

      thx, that would be nice :-)

       
  • Radek Burget

    Radek Burget - 2013-07-02

    Could you please provide more details about your use-case? Mainly how do you obtain element and decl? I have some solution prepared but I would like to see if it is usable in your case. Thanks.

     
  • sjuschka

    sjuschka - 2013-07-04

    the code in my first post is simply an additional line in your test class AdvancedCSS.testBP():

    https://sourceforge.net/p/cssbox/jstyleparser/code/764/tree/trunk/src/test/AdvancedCSS.java

    as described i changed the following to get it working:

    • set HOVER("hover", true) in Selector.java
    • extended the "data/advanced/style.css" with "#bp:hover { background: center left; }"
    • extended the AdvancedCSS.testBP() with the line "NodeData data2 = decl.get(bp, PseudoDeclaration.HOVER);"
    • data2 contains the expected hover background declarations

    so if you fixed something the following should work now:

    • extend the "data/advanced/style.css" with "#bp:hover { background: center left; }"
    • extend the AdvancedCSS.testBP() with the line "NodeData data2 = decl.get(bp, PseudoDeclaration.HOVER);"
    • data2 contains the expected hover background declarations

    Important
    * :focus, :hover and :active should work an ALL html tags, not only on "a"-tags.

     

    Last edit: sjuschka 2013-07-04
  • Radek Burget

    Radek Burget - 2013-07-12

    Hi,
    I have implemented a solution in trunk and I have updated the manual accordingly. It also contains an explanation why the pseudo-classes cannot be solved the same way as the pseudo-elements. The manual may be ontained in
    svn repository here.

    I have also written a new test PseudoClasses that shows how it works.

    Comments are welcome (but please allow certain delays in my responses during summer).

     
  • sjuschka

    sjuschka - 2013-07-29

    thank you! i'm also on holiday, but will try it right after.

     
  • sjuschka

    sjuschka - 2013-08-15

    Hi, i took a deeper look into the PseudoClasses test, but from my point of view the current solution is not sufficient and not usable or i'm thinking in the wrong direction.

    I expected, that i can get the NodeData for multiple different declarations for the SAME element, like

    NodeData data = decl.get(elements.getElementById("l1"));
    NodeData dataHover = decl.get(elements.getElementById("l1"), PseudoDeclaration.HOVER);
    NodeData dataActive = decl.get(elements.getElementById("l1"), PseudoDeclaration.ACTIVE);
    

    In your test you just get the "link"-NodeData for "l1" or the "hover"-NodeData for "l2", always by calling:

    NodeData data = decl.get(elements.getElementById(id));
    

    You never use

    NodeData data = decl.get(elements.getElementById(id), PseudoDeclaration.HOVER);
    

    Isn't it possible to call StypeMap.get(E el, P pseudo) with PseudoDeclaration.HOVER or PseudoDeclaration.VISITED and so on?
    I think it isn't possible because these PseudoDeclarations were never put into the "pseudoMap", because the are always filtered out in this method in SelectorImpl.java

    public PseudoDeclaration getPseudoElement() {
        PseudoDeclaration ret = null;
        for(SelectorPart item : list) {
            if(item instanceof PseudoPage)
            {
                ret = ((PseudoPage)item).getDeclaration();
                if (ret.isPseudoElement())
                    break; //pseudo-elements may only be appended after the last simple selector of the selector
                else
                    ret = null; //not interested in pseudo-classes
            }
        }
        return ret;
    }
    

    if i change it to

    public PseudoDeclaration getPseudoElement() {
        PseudoDeclaration ret = null;
        for (SelectorPart item : this.list) {
            if (item instanceof PseudoPage) {
                return ((PseudoPage)item).getDeclaration();
            }
        }
        return ret;
    }
    

    it works for me when i add MatchingConditions like this:

        MatchConditionOnElements cond = new MatchConditionOnElements("a", PseudoDeclaration.LINK);
        cond.addMatch("a", PseudoDeclaration.HOVER);
        cond.addMatch("a", PseudoDeclaration.VISITED);
        cond.addMatch("a", PseudoDeclaration.ACTIVE);
        cond.addMatch("div", PseudoDeclaration.HOVER);
        cond.addMatch("div", PseudoDeclaration.ACTIVE);
    
        CSSFactory.registerDefaultMatchCondition(cond);
    
     
  • Radek Burget

    Radek Burget - 2013-09-28

    Hi, I've been thinking about it once again. Your solution may be working for your application but it's not applicable for all situations. For structured selectors, there is an important difference between the pseudo elements and pseudo classes in CSS. The pseudo elements may be used in the last selector only; you may write

    h1 span:first-letter { ... }
    

    but you may not use something like

    h1:first-letter span { ... }
    

    In this case, you may use the decl.get(elem, pseudo) method because it's always clear which CSS rules should be taken into account (i.e. those that end with the appropriate pseudo-element).

    On the other hand, you may use many pseudo-classes in all the selectors. For example, the style of a link a may be given by the following rules in the same time:

    a { ... }
    div a:visited { ... }
    div:hover a { ... }
    div:hover a:link { ... }
    

    That means, for computing the style of a particular element a, we have to know the pseudo-classes for its ancestors as well. And the result may be different for different a elements in the document depending on the pseudo-classes of their ancestors.

    Therefore, it is now required to specify the pseudo classes for the individual elements before the style is computed. It is not realistic to pre-compute all the possible combinations in order to specify the pseudo-classes afterwards when the get() method is used.

     
  • sjuschka

    sjuschka - 2013-10-17

    ok, i understand. but i'm not sure how to work with jstyleparser concerning pseudo classes. how to get the computed styles e.g. for "div:hover a:active" in the moment when the user hovers the div and clicks the link? maybe there is simply a thinking blockade in my head. what would you suggest? thx

     
  • Radek Burget

    Radek Burget - 2013-10-26

    Unfortunately, you have to recompute the styles when the pseudo class assignment changes. I.e. change the MatchCondition and call assignDom() or evaluateDom() again. E.g. when a particular link is hovered:

    Element linkElement = ... obtain the hovered element ...
    cond.addMatch(linkElement, PseudoDeclaration.HOVER)
    decl = CSSFactory.assignDOM(...)
    

    In this case, you should match a single DOM element, not the element name such as "a" (the condition would apply to all the links which is not what we want).

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.