How to add different css class dynamically in a loop every 3 times - css

Basically what i need to do is looping all the posts and add css to article class like "cb-no-1" and the second one "cb-no-2" and the third one "cb-no-3" and repait it again until there's no post.
#foreach (var post in Model.Posts)
{
//First iteration
<article class= "cb-no-1">
</article>
//Second iteration
<article class= "cb-no-2">
</article>
//Third iteration
<article class= "cb-no-3">
</article>
//Fourth iteration
<article class= "cb-no-1">
</article>
//and so on.
}
How to achive it. Thanks in advance.

Use a variable and increment that in the loop and use this variable name to build the class name. When the variable reaches 3 (or your limit), reset it to initial value.
#{
var counter = 0;
}
#foreach (var post in Model.Posts)
{
if (counter >= 3)
{
counter = 0;
}
<article class= "cb-no-#(++counter)">#post.Title</article>
}

use a variable like as i inside the loop which is inited from 1 and increases in each loop and when it reachs the 4, reset it to 1
then use it for class name

Shyju, the first responder, has the right idea, but there are two modifications you need to make to his answer.
First, his code gives you a variable from 0 to 2. you asked for 1 to 3,. so the initialization needs to be "var counter = 1" and the "if" test needs to be just greater than 3, not greater than or equal to 3. Or you could change the 3 to a 4, such as: if (counter >= 4).
The second item left off of that code snippet is something to increment the counter. I'm not sure which dialect or language you are writing in but something like:
Counter+=1
or
counter = counter + 1
Modified, that code snippet would look like:
var counter = 1;
#foreach (var post in Model.Posts)
{
if (counter >= 4)
{
counter = 0;
}
<article class= "cb-no-#(++counter)">#post.Title</article>
counter += 1
}
Again, I do not know which language you are writing in so check my syntax carefully.

Related

Creating a rating system for displaying rating stars in asp.net

I've a values something like this 1.25, 2.50, 3.75 or 4.00:
I can loop on the integers like 1, 2, 3 or 4.
But how I can loop on 3.75?
for (int i = 0; i < 3.75; i++)
{
// my logic
}
Updated:
The loop I needed as I'm creating a rating system and displaying the rating stars in loop. For example:
If 1.25 then star 1 and quarter (0.25) of star 2. Or if 4.75 then star 4 and last quarter (0.75) of star.
3.75/5
How I can display rating in stars?
Prepare 2 image files, one has 5 empty-stars and the other has 5 filled-stars, just like:
the 2 images must have same width and height, e.g. 400X70
place the filled-stars overlap on the empty-stars, then crop the filled-stars to a portion of the origin witdh the same as the Rating,
i.e. the crop div width = image_width / 5 * rating
e.g. With 3.5 Rating, width = 400 / 5 * 3.5 = 280
<html>
<head><title>test</title>
<style type="text/css">
.container > * {
position: absolute;
}
.container, .crop {
height: 70px;
}
.crop {
overflow: hidden;
}
</style>
</head>
<body>
<div class="container">
<img src="https://i.stack.imgur.com/yiT2y.png" />
<!-- the width could be calculated either at server or client side, or define in css -->
<div class="crop" style="width:280px">
<img src="https://i.stack.imgur.com/oTi9e.png" />
</div>
</div>
</body>
</html>
Although generally it's not a good idea to loop on double, especially when you check for equality in the loop, in your case it's OK because your loop increment is can be represented precisely as a combination of powers of 2. Specifically, 1.25 is 20+2-2.
for (double i = 0 ; i < 6 ; i+=1.25) {
// my logic
}
Alternatively, you could loop on int, and multiply loop counter by 1.25:
for (int i = 1 ; i <= 4 ; i++) {
double val = 1.25 * i;
//
}
I'm creating a rating system and displaying the rating stars in loop.
You don't need a loop for this. If you have a number between 0 and 5, inclusive, representing the average, you need to know three things:
How many "filled" stars to display,
How big is the filled portion of of the partially-filled star, and
How many "blank" stars to display.
You can find out the answers to these three questions using math:
The number of "filled" stars is the integer portion of the number after truncation
The fraction of the partially filled star is the decimal part of the number
The number of "blank" stars is 5-ceil(n), where ceil(n) represents the "ceiling" of the number (i.e. the smallest int equal or higher than n).
Just use loop variable of type double:
for (double x = 1.25; x <= 4; x += 1.25)
{
// Your logic
}
You can iterate over a list of accepted values instead of iterating on float. If you don't want to manually edit known values, one way to generate them would be:
IEnumerable<float> CalculateBreakpoints(int min, int max, short unitPartitions)
{
var fraction = 1f / unitPartitions;
for (float i = min; i <= max; i += fraction)
{
yield return i;
}
}
It's unlikely that in the wild you'll have ratings that exactly match your known values. You could try choosing known value closest to rating at hand or approach it some other way. Amazon for example shows closest value above actual rating. That could be done like this:
float MapRatingToBreakpoint(float rating, IEnumerable<float> breakpoints)
{
var min = breakpoints.Min();
var max = breakpoints.Max();
if (rating < min || rating > max)
{
throw new ArgumentOutOfRangeException(nameof(rating));
}
foreach (var point in breakpoints)
{
if (rating <= point)
{
rating = point;
break;
}
}
return rating;
}
Once you have a processed rating, to display stars on the front end this code would be able to choose what type of star to use:
for (let i = 1; i <= 5; ++i) {
if (i <= Math.floor(rating)) {
console.log("addFullStar()");
}
else if (i > Math.ceil(rating)) {
console.log("addEmptyStar()");
}
else {
fraction = rating - i + 1;
console.log(`addPartialStar(fraction: ${fraction}`);
}
}
At this point it's up to you to choose how you want to display each type of star. You could use a sprite with all the different stars and play with CSS classes like <span class="star-0-25" /> to attach correct images. Another option for displaying a partial star could be to add full and empty star on top of each other, have empty star with hidden overflow, full star with visible overflow and adjust width of a parent tag.

Add classes to adjacent elements dynamically on mouseenter

I'm creating a grid of elements and have a hover effect in place, using CSS transitions, for each element. I'd like to add secondary effects on adjacent x- and y-axis elements as well, creating a cloud effect. I imagine I'll be referencing those elements using jQuery's next() and prev() methods, or by $index and $parent.$index.
The grid area will be large enough to prevent row-wrapping (using negative margins and hidden overflow).
Here's a simplified example of my repeat:
<div class="activity-thumb-row" ng-repeat="i in getNumArray(20) track by $index">
<div class="activity-thumb"
ng-class="{'adjacent': adjacent}"
ng-repeat="j in getNumArray(30) track by $index"
ng-mouseenter="highlightActivities()">
</div>
</div>
And a function in the controller (which I realize may not be the best approach):
$scope.highlightActivities = function() {
$(this).next().adjacent = true;
$(this).prev().adjacent = true;
}
How can I target elements adjacent to the hovered element using ng-class (or something else) inside ng-repeat?
Here's a fiddle for fiddling.
For reference, here are some related discussions:
Change class on mouseover in directive
Angular js ng repeat with conditional ng class not applying css class
ng-mouseover and leave to toggle item using mouse in angularjs
Here's a directive that calculates all of the indices of adjacent cells and adds the adjacent class using jQuery only ... not ng-class.
Assumes that rows will wrap , would need adjusting for individual row elements
.directive('activityThumb', function() {
return {
restrict: 'C',
link: function(scope, elem) {
elem.bind('mouseenter', function(e) {
var elW = elem.width(),
$parent =elem.parent(),
parentW = $parent.width(),
$items = $parent.children(),
numItems =$items.length
itemsPerRow = Math.floor(parentW / elW),
idx = elem.index(),
rowIndex = idx % itemsPerRow;
/* object of various indices , easy to inspect*/
var adjacentIdx = {
top: idx > itemsPerRow ? idx - itemsPerRow : false,
right: rowIndex != itemsPerRow ? idx + 1 : false,
left: rowIndex > 0 ? idx - 1 : false,
bottom: (numItems - idx) > itemsPerRow ? idx + itemsPerRow : false
}
console.dir(adjacentIdx);
$items.removeClass('adjacent')
$.each(adjacentIdx, function(position, index){
if(index !== false){
$items.eq(index).addClass('adjacent');
}
});
});
}
}
});
It wouldn't take much tweaking to remove jQuery dependency either.
Also would need additional directive on parent to remove extra classes when mouse leaves the main parent from one of the edges
DEMO
First, it's not a good idea to deal with DOM elements in the controller.
Also, this problem seems to be mostly styling related, and not functionality related. I would thus try to keep the logic in the View and not in the controller.
There are 2 ways to deal with View-specific logic: 1) using custom directives or 2) View-defined scope variables
The second approach can work here and seems like the cheapest approach, but also a bit ugly. It ng-inits the rowHighlight array in the scope and sets which element is highlighted:
<div ng-repeat="i in getNumArray(20) track by $index" ng-init="rowHighlight = []">
<div class="activity-thumb"
ng-repeat="j in getNumArray(30) track by $index"
ng-class="{'adjacent': rowHighlight[$index-1] || rowHighlight[$index+1]}"
ng-mouseenter="rowHighlight[$index] = true"
ng-mouseleave="rowHighlight[$index] = false">
</div>
</div>
updated fiddle

css inline-block div positioning

I'm trying to fix a positing issue in a responsive design.
I have a container div, containing 4 (but it could be more or less) divs that are displayed as inline-block. I would like to know how to control the number of divs per line when the page is resized (with CSS, if it's possible). For example, when 4 containees no longer fits in the container, the last one is moved to second line. I would like in that case to have 2 containees in the first line and 2 containees in the second line. I dont know how to do that. Your help would be welcomed!
EDIT:
it could also be 6 containees, in the case the layout would be:
- 1 line of 6 blocks if it fits
- 2 lines of 3 blocks
- 3 lines of 2 blocks
- 6 lines of one
the number of containees is variable. I just want to have the same number of containees per line
the html:
<div class="container">
<div class="containee"></div>
<div class="containee"></div>
<div class="containee"></div>
<div class="containee"></div>
</div>
the css:
.containee {
width:200px;
height:200px;
display:inline-block;
background-color:tomato
}
the example can be seen here : http://cssdesk.com/uGLbq
(PS : I tried to find the solution searching the web but I dont really know the good keywords related with this topic)
You can't with CSS (AFAIK).
You can do "the math" dynamically with Javascript in real time.
In your case,
you known the width of one block (in that moment),
you can easily get the window width (in that moment),
you know the number of your block (in that moment);
Simply apply ( (1) the first time you open the page, and (2) every time the number of blocks changes, or (3) the resolution changes) the algorithm in the following code:
// EXAMPLE OF INPUT
var windowWidth = 1400; // read it...
var blockWidth = 200; // read it or use const...
var numberOfBlocks = 10; // read it...
// Calculate the maximum number of blocks per row
var maxBlocksPerRow;
for (var i=0; i < numberOfBlocks; i++) {
if ( (blockWidth * (i + 1)) > windowWidth){
maxBlocksPerRow = i;
break;
}
}
// Check the highest 0 module combination while iterating backwards
var magicNumberForMatchingBlocks = 1; // if not found, it will be 1.
for (var i = maxBlocksPerRow; i > 0 ; i--) {
if ( (numberOfBlocks % i) == 0){
magicNumberForMatchingBlocks = i;
break;
}
}
alert("With " + numberOfBlocks + " blocks, each one wide " +
blockWidth + " pixels, and a window wide " + windowWidth + " pixels,
the number of blocks per row for having always
the same number of block in any row is: " + magicNumberForMatchingBlocks);
Then use that number to populate or re-arrange the elements with Javascript or better with some Javascript library like jQuery.
html:
<div class="container">
<div class="grouped">
<div class="containee"></div>
<div class="containee"></div>
</div>
<div class="grouped">
<div class="containee"></div>
<div class="containee"></div>
</div>
</div>
css:
.containee {
width:200px;
height:200px;
display:inline-block;
background-color:tomato
}
.grouped {
float:left;
}
Try this:
.container
{
min-width: 410px;
}
Give the .containee a float:left; if the page fits for 4, they will be positioned right beside each other, else, you'll have another line of divs. You can give it as well a margin-top:5px; in case you got another line, the divs of the second line won't be glued to the divs of the first line. Note that with this approach, its not obliged to have equal number of .containee in each line, if you have 4, then you re-size, you'll have 3 - 1, then 2 - 2...etc..

Is there a web control to dynamically generate a table of contents?

Say I have a basic page like so:
<custom:TableOfContents />
<h1>Some Heading</h1>
<h2>Foo</h2>
<p>Lorem ipsum</p>
<h2>Bar</h2>
<p>Lorem ipsum</p>
<h2>Baz</h2>
<p>Lorem ipsum</p>
<h1>Another Heading</h2>
<h2>Qux</h2>
<p>Lorem ipsum</p>
<h2>Quux</h2>
<p>Lorem ipsum</p>
Assume all the header tags exist as server side controls. Is there some web control <custom:TableOfContents /> for ASP.NET webforms that will dynamically generate a table of contents that looks something like the following (when rendered to the screen):
1. Some Heading
1.1. Foo
1.2. Bar
1.3. Baz
2. Another Heading
2.1. Qux
2.2. Quux
Ideally, each entry in the table of contents would be a hyperlink to a dynamically generated anchor at the appropriate place on the page. Also, it would be nice if the text of each header tag could be prefixed with its section number.
If not a web control, is there some easier way of doing this? Keep in mind that many of the header tags are going to be created by data bound controls, so manually maintaining the table of contents is not an option. It seems like the webforms model is ideally suited to creating such a control, which is why I'm surprised I haven't yet found one.
I needed to do a similar thing a few days ago and, though not a webcontrol, used jQuery.
$(document).ready(buildTableOfContents);
function buildTableOfContents() {
var headers = $('#content').find('h1,h2,h3,h4,h5,h6');
var root, list;
var previousLevel = 1;
var depths = [0, 0, 0, 0, 0, 0];
root = list = $('<ol />');
for (var i = 0; i < headers.length; i++) {
var header = headers.eq(i);
var level = parseInt(header.get(0).nodeName.substring(1));
if (previousLevel > level) {
// Move up the tree
for (var L = level; L < previousLevel; L++) {
list = list.parent().parent();
depths[L] = 0;
}
} else if (previousLevel < level) {
// A sub-item
for (var L = previousLevel; L < level; L++) {
var lastItem = list.children().last();
// Create an empty list item if we're skipping a level (e.g., h1 -> h3)
if (lastItem.length == 0)
lastItem = $('<li />').appendTo(list);
list = $('<ol />').appendTo(lastItem);
}
}
depths[level - 1]++;
// Grab the ID for the anchor
var id = header.attr('id');
if (id == '') {
// If there is no ID, make a random one
id = header.get(0).nodeName + '-' + Math.round(Math.random() * 1e10);
header.attr('id', id);
}
var sectionNumber = depths.slice(0, level).join('.');
list.append(
$('<li />').append(
$('<a />')
.text(sectionNumber + ' '+ header.text())
.attr('href', '#' + id)));
previousLevel = level;
}
$('#table-of-contents').append(root);
}
This will make an ordered list and append it to #table-of-contents with appropriate numbering (e.g., 1.1). Just a little bit of CSS is needed to hide the lists' built in numbering: #table-of-contents ol { list-style:none; }.

ASP.net repeater, scroll 3 at a time

I have a list of data that I need to display in a web page 3 at a time
The first needs to be displayed in a div called "left" , the second in a div called "centre" and the third in a div called "right".
And I need to be able to scroll through the data with a pager. And so the next 3 results will be displayed in a similar way, and so on till the end of the data set
Obviously the alternating templates in the repeater are not suitable for this.
Is there a smarter way to achieve this?
Try a loop like this
for (int i = 3; i < enumerable.length + 3; i++)
{
if (i % 3 == 0)
{
// Put it in div 1
{
else if (i % 3 == 1)
{
// put it in div 2
{
else if (i % 3 == 2)
{
// put it in div 3
{
}
The first time through, it will use div1, the second time div2, and the third time div3, and then the fourth time div1, and so on...

Resources