0

I have been looking with no success to see if I can dynamically apply a css style to JSF component or div using javascript. Is this possible.

This is pseudo code

<div style="myJSStyleFunction("#{myBean.value}")"> stuff </div>

And the function would return something like "position:relative;left:25px;"

I've had no luck and maybe it can't be done but would like a second opinion.

Edit:


I'm trying to see if I can keep a separation / reduce the coupling between the presentation/view and the model/controller. This is for indenting commenting or product reviews (to nest replies to comments or reviews). The most I really want to track is an integer on how deep a reply is. First level = 0 second level = 1, and so on. So a comment or product review would be 0 deep, a reply to the comment or review would be 1 and so on.

Then in the EL I wanted to call a javascript function and do something like

<script>
    myJSStyleFunction(depth){
        if(depth<=5){
            var nest=20*depth;
            var style="position:relative;left:" + nest + "px;";
            return style;
        }
    }
</script>

And then then say for a third level comment (a reply to a reply) it would look like this:

<div style="position:relative;left:40px;"> stuff </div>

where

#{myBean.value}

evaluates to 2

I suspect like Daniel says I'll have to tightly couple the view but I'd rather not have to. I'd think there has to be a way. But maybe not.

4
  • What is the final rendered output HTML? Commented Nov 7, 2012 at 21:13
  • @Dai I added more info as you asked, take a look at my updated question. Commented Nov 7, 2012 at 22:06
  • What do you mean by dynamically apply a css style? What is the event? Do you mean when page loading? Commented Nov 8, 2012 at 3:33
  • @prageeth Yes, when the page is loading. As the comments are being loaded from the database via the managed bean the style is being applied for each comment depending on one of the properties of each comment (the depth) property) which is an integer. Is that understandable? Commented Nov 8, 2012 at 3:40

2 Answers 2

2

I don't know where there are cleaner solutions for this. However this is one suggestion.
Assume your page looks like below and myBean.getValue() method returns an integer.

<h:form id="frm">
   <div style="#{myBean.value}"> div1 </div>
   <div style="#{myBean.value}"> div2 </div>
</h:form>

So you can do something like this at 'window.onload'.

<head>
<script>
window.onload = function() {
   var childList = document.forms['frm'].childNodes;
   for(var i = 0; i &lt; childList.length; i++) {
      if(childList[i].nodeName == 'DIV') {
         var _div = childList[i];
         var depth = _div.getAttribute('style');
         _div.setAttribute('style', 'position:relative;left:' +(depth *20)+ 'px;');
      }
   }
}
</script>
</head>

Note:
1. In above sample code I assume all the DIVs inside the form should be indented.
2. For IE you may need to use _div.style.setAttribute('cssText','position:relative;left:' +(depth *20)+ 'px;')
3. Another solution for your question is using <script> tags immediately after your divs and putting the js part inside them. In this way you don't have to use fake styling style="#{myBean.value}" or window.onload event because you can directly call #{myBean.value} in your script.

Sign up to request clarification or add additional context in comments.

2 Comments

Your idea looks very interesting but I've had an idea on how to do this without javascript. I think I like your idea in point 3 too. Right now I'm having some trouble with the hierarchal query for the solution. Once I figure that out, I'll try my solution and post it if it works, and then give your solution a try.
I'll give one for the response. Not sure if it works as I have decided not to use javascript for now. Will still try this out when I have time but it might be several weeks or a month or two down the road. I have decided on a simpler root since I already track comment depth when the comments are added, so I am just retrieving them and concatenating the value to a 'base name' for the css class. I posted what I am doing as an answer.
0

I decided to skip the javascript approach and settled on a simpler and I think cleaner method to create the dynamic css classes for my situation. I already capture/calculate the depth value for each comment when it is entered. So I am just returning that value in EL and concatenating it to a 'base name' for the css class like so:

<div class="indent_#{(comment.commentDepth le 5) ? comment.commentDepth : 5}" >
    comment comment blah blah blah
</div>

"indent_" is the base name for the css class. So for a 0 level comment it will have a class="indent_0". A reply to that comment will have class="indent_1".

I use the ternary so that if there are lot of replies under a given comment it doesn't indent right off the right hand side of the page. Even though you can keep going deeper, it will only indent up to 5 levels.

For my case at the moment, this is a simpler and cleaner method of adding some dynamically generated css class names. Right now I have to define 6 classes for this in the css file, but perhaps I'll figure out how to nest the boxes but it isn't a priority this works just fine for me for now.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.