1

On my page, if I change the attributes of an element such as

<div class="showInitially"></div>

by setting

$(".showInitially").hide()

then any elements added dynamically afterwards like

container.append("<div class='showInitially'>text</div>");

do not inherit the changes.

I know I can re-apply all the changes after I add another element but somehow this seems inefficient and hacky, especially if there are a number of changes to styles made. So, is there another way to add elements to the page that will automatically have the inherited style and attribute changes applied to them?

I've tried

container.trigger("create");

but this does nothing. An example is shown in the snippet below:

var container=$("#container");
var buttons = $("button")
var allDivs = $("#container .showInitially")

buttons.on("click", function(){
  buttons.addClass("alt");
  allDivs.addClass("alt");
  allDivs.hide();
  addButton();
})

function addButton(){
 container.append("<div><button>Change another color</button></div> <div class='showInitially'>text</div>");
}
body {
  background: #cccccc;
  padding: 20px;
  font-family: Helvetica;
}

button {
  background: #0084ff;
  border: none;
  border-radius: 5px;
  padding: 8px 14px;
  font-size: 15px;
  color: #fff;
}

div{
  color:black;
}

.alt{
  background: red;
}

.showInitially{
  color:orange;
  display:inline;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container" >
  <button>Change color</button> <div class="showInitially">text</div>
</div>
Tibrogargan
  • 4,508
  • 3
  • 19
  • 38
DeclanMcD
  • 1,518
  • 4
  • 22
  • 41
  • 2
    `.showInitially{ display: none; }` simple CSS is enough – Pranav C Balan Jun 07 '19 at 07:16
  • Modify the css rules directly. See [this](/questions/324486/how-do-you-read-css-rule-values-with-javascript) – Tibrogargan Jun 07 '19 at 07:24
  • @Pranav I don't quite understand that. Can you show how that applies in the fiddle example? If I had a style attribute of { display: none; } then it defeats the purpose because any divs already on the page with that style would be hidden...initially - not desired – DeclanMcD Jun 07 '19 at 07:26
  • @DeclanMcD : use a different class then... and toggle between classes – Pranav C Balan Jun 07 '19 at 07:27
  • @Pranav - that won't work because the newly added elements will have the initial style attributes (for example an initial colour of purple). If I toggle the style then it changes those on the page to the new style (say colour yellow) but any new elements added after get the initial style (of purple) – DeclanMcD Jun 07 '19 at 07:32
  • The way you add elements to a page and inherit styles is quite literally by using CSS rules. When a new element is created the CSS rules are used to generate the style applied to the new instance. If you want a new instance to inherit attributes in some other manner, you will need to copy existing instances that have the style you want. What you're trying to do is usually done through having additional classes in the CSS rules and applying the classes dynamically. You are trying to reinvent CSS – Tibrogargan Jun 07 '19 at 16:31

1 Answers1

0

Modify the CSS rule dynamically.

Blatantly ripped off from How do you read CSS rule values with JavaScript? and modify a css rule object with javascript and then cobbled together.

Part of the issue with your code was that your on click only attached the click handler to buttons that already existed. Any new button would not get a click handler, so I moved the handler to the document and added a selector.

var container=$("#container");
var buttons = $("button")
var allDivs = $("#container .showInitially")

$(document).on("click", "button", function(){
  buttons.addClass("alt");
  allDivs.addClass("alt");
  modStyle('.showInitially', 'display', 'none');
  //allDivs.hide();
  addButton();
})

function addButton(){
 container.append("<div><button>Change another color</button></div> <div class='showInitially'>text</div>");
}

function modStyle(className, foo, bar) {
    var classes = document.styleSheets[0].rules || document.styleSheets[0].cssRules;
    for (var x = 0; x < classes.length; x++) {
        if (classes[x].selectorText == className) {
            (classes[x].cssText) ? classes[x].style[foo] = bar : classes[x].style[foo] = bar;
        }
    }
}
body {
  background: #cccccc;
  padding: 20px;
  font-family: Helvetica;
}

button {
  background: #0084ff;
  border: none;
  border-radius: 5px;
  padding: 8px 14px;
  font-size: 15px;
  color: #fff;
}

div{
  color:black;
}

.alt{
  background: red;
}

.showInitially{
  color:orange;
  display:inline;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container" >
  <button>Change color</button> <div class="showInitially">text</div>
</div>
Tibrogargan
  • 4,508
  • 3
  • 19
  • 38
  • I was hoping to have to avoid doing a re-apply of all the styles. Your example is fine if I just had to apply a show/hide state, but it doesn't account for any other changes that have been made to the styles such as the colour changes. – DeclanMcD Jun 07 '19 at 08:51
  • Not sure what you mean. It literally just changes the `display` style, it does not replace the whole style – Tibrogargan Jun 07 '19 at 16:11