CSS and Dynamic Content - javascript

UPDATE: Messed up with my CSS, as nothing to do with dynamic content.!
The answer is very informative though!
I'm creating tags and inserting content with handlebars:
Handlebars code:
{{#each docs}}
<article class="first">
<p class="date">
{{#date}} {{date}}
</p>
<h4 class="header">{{#venue.title}} {{venue.title}}
- {{#venue.city}} {{venue.city}}</h4>
<p class="details">
{{#description}} {{description}}
</p>
</article>
{{/each}}
If I just list articles, the CSS works - but when I let handlebars dynamically create them, it won't apply.
CSS code:
div.gig-items{
article: nth-of-type(n +2);
height: 0;
padding: 0;
}
Is there a way to first create the content and then apply CSS or some more elegant solution?

The CSS is applied automatically at each repaint. So inserting your code in the source html or dynamically with js doesn't matter, the css will be applied correctly.
The problem come for sure from your code which has several errors...
First the CSS
You want to style every div elements with class gig-items, but
there is no div and no class gig-items in your template...
You define a property article with value nth-of-type(n+2), but this is not a property, this is a selector
you should use it like :
article:nth-of-type(n+2) {
color: blue;
}
Then in your handlebar template :
I assume you want to insert values by their names, but you use the
prefix # which is reserved for handlebar's loop values like
#index or #keys
Another error is that you write double handlebar
block to display the value. One is enough.
The correct way to insert value is :
<p class="date">{{date}}</p>

Related

How can we add before after css code dynamically with vue?

I am trying to solve a problem which I actually never faced. I am trying apply dynamic color from my data inside v-for loop. Now normal css properties are easily appliable. I need to apply css for after. I tried
<div class="_tmln_shdl_crd_itm" v-for="(t, i) in timeLine" v-if="timeLine.length">
<div class="_tmln_shdl_itm_lft">
<p :style="`color:${t.color}`">{{t.time}}</p> // THIS WORKS
</div>
<style>
._tmln_shdl_itm_r8_one h4:after{ // TRIED TO WRITE CSS WITH FOR LOOP BUT FAILED :D
color: t.color
}
</style>
<div>
So how can I make it work for ._tmln_shdl_itm_r8_one h4:after ?
Any solution?
Thank you.
The style you create in the loop creates CSS for the same selector every time. The browser only has one applicable CSS styling for this selector.
With the same selector, the newest CSS wins and is applied. This is CSS Specificity ("When multiple declarations have equal specificity, the last declaration found in the CSS is applied to the element.").
You can create classes dynamically:
<div class="_tmln_shdl_crd_itm" v-for="(t, i) in timeLine" v-if="timeLine.length">
<div :class="`_tmln_shdl_itm_lft _tmln_shdl_itm_lft-${i}`">
<h4>{{ t.time }}</h4>
</div>
<style>
._tmln_shdl_itm_lft-{{ i }} h4:after{
color: {{ t.color }};
}
</style>
<div>
Something like that should work. Making the class dynamic with ._tmln_shdl_itm_lft-{{ i }} makes the magic work.
This also adds a lot of CSS fluff to the page which is probably not what you want in a live environment.
Remarks:
You also should output t.color like this (probably just a mistake in your example):
color: {{ t.color }};
There is also no h4 tag in your example code that the CSS could apply for, but that's probably somewhere else in your page.. hopefully?

Flex, AngularJS + Masonry, akoenig/angular-deckgrid and more [duplicate]

This question already has answers here:
How to Create Grid/Tile View? [duplicate]
(8 answers)
Closed 6 years ago.
I've been sending this emails:
I'm about to release an application for web application security which requires the use of a grid like Masonry. I've tried all, and every single angular module, directives, and different approaches, including CSS based techniques, pure Vanilla JS, and your solution is, one of the best options available online. I found, however a main issue, that affects not only your approach, but every single Angular module or addon.
Issue #1:
Your solution, as any other solution, is based on an array of information that is already handled by angular. In your example case, it would be source="photos". Now, the problem comes when there's 2 different groups of elements. Let's assume, that I have a group of elements that where previously defined in the DOM. In other words:
<div angular-grid>
<p class="angular-grid-elem">This content is already here from the beginning, in the DOM, directly in the HTML, and I want to apply a Masonry like style on it.</p>
<div class="angular-grid-elem" style="height:500px">Same happens with this content.</div>
<!-- and here comes more content, which is loaded from an array of information -->
<div class="angular-grid-elem" ng-repeat="data in data_array">
<p>{{data.header}}</p>
<p>{{data.details}}</p>
</div>
</div>
Now, as you can see in the example, the content inside the main div, , should be all, affected by the masonry layout. Of course, this is pseudo code and I'm aware that the sintaxis of your approach is different. However what I'm trying to represent here, is that your module, would be way better, if you would be able to apply the masonry like grid, including elements which are already present in the DOM/HTML in first place, with elements that are coming from an array.
Issue #2:
There's a second issue I found in multiple angular modules and approaches. What happens if I have 2, 3 or let's say even 16 divs which all of them, present the same masonry like behaviour? I have to admit, I didn't try it with your module, as I couldn't solve the initial problem, that requires the proper handling of the combination of elements that are (1) pre-defined in the HTML, and (2) coming from and ng-repeat function.
A possible approach:
In order to solve the second problem and the first one, at the same time, I have thought that the best approach might be to make use of element classes and elements ids to handle the situation? Why? Because it can easily applied into elements that are already there in the DOM in first place, as well, to elements that are joining or leaving dynamically by the use of a ng-repeat or any other of the angular functions.
Here's an example of what I'm saying:
<div class="angular-grid-dad-one" ng-grid="{'dad': 'angular-grid-dad-one', 'childs': 'angular-grid-elem'}" >
<p class="angular-grid-elem">This content is already here from the beginning, in the DOM, directly in the HTML, and I want to apply a Masonry like style on it.</p>
<div class="angular-grid-elem" style="height:500px">Same happens with this content.</div>
<!-- and here comes more content, which is loaded from an array of information -->
<div class="angular-grid-elem" ng-repeat="data in data_array">
<p>{{data.header}}</p>
<p>{{data.details}}</p>
</div>
</div>
In this case, the main div defines itself as id="angular-grid-dad-one",
And also tells the Angular module, that the element angular-grid-dad-one is a container div of a masonry like structure,
And that it's childs are marked as angular-grid-elem.
As we could see on this line.
ng-grid="{'dad': 'angular-grid-dad-one', 'childs': 'angular-grid-elem'}"
This way, it allow us to make use of the Angular module in multiple instances. For example.
<div class="seccion_01" ng-grid="{'dad': 'seccion_01', 'childs': 'seccion_01_child'}" ng-show="seccion == '1'">
<p class="seccion_01_child">This content is already here from the beginning, in the DOM, directly in the HTML, and I want to apply a Masonry like style on it.</p>
<div class="seccion_01_child" style="height:500px">Same happens with this content.</div>
<!-- and here comes more content, which is loaded from an array of information -->
<div class="seccion_01_child" ng-repeat="data in data_array">
<p>{{data.header}}</p>
<p>{{data.details}}</p>
</div>
</div>
<div class="another_container" ng-grid="{'dad': 'another_container', 'childs': 'child_of_container'}" ng-show="seccion == '2'">
<p class="child_of_container">This content is already here from the beginning, in the DOM, directly in the HTML, and I want to apply a Masonry like style on it.</p>
<div class="child_of_container" style="height:500px">Same happens with this content.</div>
<!-- and here comes more content, which is loaded from an array of information -->
<div class="child_of_container" ng-repeat="data in data_array">
<p>{{data.header}}</p>
<p>{{data.details}}</p>
</div>
</div>
<div class="redundant_example" ng-grid="{'dad': 'redundant_example', 'childs': 'childs_of_redundancy'}" ng-show="seccion == '3'">
<p class="childs_of_redundancy">This content is already here from the beginning, in the DOM, directly in the HTML, and I want to apply a Masonry like style on it.</p>
<div class="childs_of_redundancy" style="height:500px">Same happens with this content.</div>
<!-- and here comes more content, which is loaded from an array of information -->
<div class="childs_of_redundancy" ng-repeat="data in data_array">
<p>{{data.header}}</p>
<p>{{data.details}}</p>
</div>
</div>
I have used a Json styled instruction in the ng-grid value in order to explain my point, but it doesn't really have to be Json. It even could be 2 different paramenters:
<div class="dad" ng-grid-dad="dad" ng-grid-childs="childs" ng-show="seccion == '3'">
<p class="childs">This content is already here from the beginning, in the DOM, directly in the HTML, and I want to apply a Masonry like style on it.</p>
<div class="childs" style="height:500px">Same happens with this content.</div>
<!-- and here comes more content, which is loaded from an array of information -->
<div class="childs" ng-repeat="data in data_array">
<p>{{data.header}}</p>
<p>{{data.details}}</p>
</div>
</div>
As well, regarding the infinite scroll that you have created, you would be able to load more elements, triggering the infinite scroll, and loading only elements from one specific array, of course.
Please let me know if I can help further, I would like to integrate your module into my application.
And let's hope that by the next implementation of HTML and CSS we have this situation fully under control by the next generation of browsers, I'm aware of the work it takes to make this grids in Javascript.
Actually, I am gonna go out on a limb and say that flex-wrap: wrap will fix the issue.
.holder {
flex-wrap: wrap
-moz-columns: 2 auto;
box-sizing: border-box;
display: flex;
padding: 0 40px;
width: 100%;
}

Formatting dynamically formed HTML elements created after Script is run

So this is actually a very tricky concept to portray so here is my attempt.
I am utilizing an HTML form template in LANDesk Service Desk - tool is irrelevant but important to note that there is back-end code that I cannot touch that is generating HTML.
So basically, the tool is pulling data from a back-end database containing a list of objects. It then inputs this data into an HTML form template that I have created using variables as placeholders for the objects. The HTML is then built on the fly with however many objects are in the database. Thus, I have no way of accessing the head - (which means native JS, and inline CSS).
My template looks like this...
<div class="my-template">
<a class="my-template my-link">My Link</a>
</div>
<script>
var myLinks = document.getElementsByClassName('my-link');
for (var i = 0 ; i < myLinks.length ; i++) {
myLinks[i].style.display = "none";
}
</script>
When I view the source on the loaded page it looks something like this...
<body>
<!--misc. page stuff-->
<!--First Item-->
<div class="auto-create">
<div class="my-template">
<a class="my-template my-link">My-Link</a>
</div>
</div>
<!--Second Item-->
<div class="auto-create">
<div class="my-template">
<a class="my-template my-link">My-Link</a>
</div>
</div>
</body>
All of the elements are formatted the way I want them to be...besides the last element on each page. I have determined that this is because each time the tool is running the object through the template, it is running the script. The issue is, there is a stupid default button that they place at the bottom of each object that is broken. (This is why I have the script changing the style to display: none..should have mentioned this earlier). Basically I want to delay the execution of the script until not only the object has been run through the template...but the entire page has loaded...but I can't seem to get the last button to go away.
I know that this is a lot of poorly written words trying to form an explanation, but I really think this is impossible...but I am convinced there has to be a way. (Also, the company isn't providing us with any help in finding a workaround, so I had to basically MacGyver this one

JS Only apply if condition to relevant item

I have a small group of items as shown below.
<div class="item">
<div class="date">2013-08-08</div>
<div class="headline"><a data="normal" href="#">Title</a></div>
</div>
<div class="item">
<div class="date">2013-10-08</div>
<div class="headline"><a data="special" href="#">Title</a></div>
</div>
If the title has a data attribute of special, I want to make the date bold for that item only.
I have the below code to try and do this.
<script>
if ($(".headline a [data='special']")){
$( ".date" ).wrap( "<b></b>" );
}
</script>
However this makes all items bold if the condition is true.
I am familiar with using this in JS but not sure how to relate it to another div above.
What is the best way to do this?
I am happy to change the html structure if required as well.
Try the following:
$(".headline a[data='special']").parent().siblings(".date").wrap("<b></b>");
The parent() function will select the div.headline for a matching <a> tag; then, siblings(".date") will select children of the parent of div.headline (which are called siblings) that have the date class.
It sounds like you'd like to select the .date element in .item elements which contain .headline a[data="special"] elements.
$('.item:has(.headline a[data="special"]) .date')
will select the correct .date elements for my given assumptions, you can then call .wrap('<b></b>').
Also note: [data] is not a valid [data-*] attribute. You must have a hyphen and a name for custom data attributes.

CSS Multiple ID with Same Name Work Around?

First I realize ID's should be unique. But right now I can't do much about that. I have a javascript plug-in that is generating ID names and for one page it works great. The issue is in creating another page, it will start over using the same naming convention. For example:
Page 1
<ul id="1">
Page 2
<ul id="1">
So if I am trying to style ul#1 on Page 1 it will also style ul#1 on Page 2. So, any suggestions on how to separate our the two id's? This html is generated by the JS, otherwise I would just attach a class to it.
Thanks.
First, the unique ID suggestion is restricted to a page. It is perfectly fine to have multiple ID's on different pages. The best way to overcome this is to add a ID to the body.
Page1
<body id="Page1">
<ul id="1">
<li></li>
</ul>
</body>
Page2
<body id="Page2">
<ul id="1">
<li></li>
</ul>
</body>
CSS
#Page1 #1
{
//Some style for page 1, ID 1
}
#Page2 #1
{
//Some style for page 2, ID 1
}
Can you attach a class around it ? Have a div or span some other element surround your code that does the generation and assign a class to it.
I'd say you have to use different style sheets on each page if you need different styles for the same ids, but this will be a pain to maintain as you make styling changes.
Alternatively you could you assign a class to one of the page's UL tags and then create a style for that class.
First of all, the plugin is still not generating the correct ids because ids can't be numbers. To answer your question, try to figure out some parent element that might be different between the two pages probably in which case you can use CSS such as this:
#parent ul#1{
/* styles here */
}
#parent2 ul#1{
/* styles here */
}
page1:
<div id="parent">
<ul id="1">
............
page2:
<div id="parent2">
<ul id="1">
............
So you need to find out a some parent element of ul which is not common between the two pages. This is the only possibility that comes to my mind where you have no control over changing the ids or replacing them with classes since they are being generated by the plugin.
You need something to distinguish them if you want them styled separately. If you cannot modify those tag you could probably use some parent container like:
<div id="parent1">
<ul id="id1" />
</div>
<div id="parent2">
<ul id="id1" />
</div>
and then:
#parent1 ul {
...
}
#parent2 ul {
...
}
Also notice that an id cannot start with a number as in your case. You should probably consider switching/modifying this plugin.
One thing I commonly do is attach a class to the body for each page. <body class="home_section"> and then you could style based on that class .home_section ul#1 {}.
Also, IDs must begin with a letter.

Categories

Resources