Limit number of rows in CSS grid - javascript

Good morning,
I'm currently trying to implement an image gallery based upon the new CSS grid. In detail, I only want to display one row initially and let the user then expand more and more images by clicking a Show more button.
This is how it looks so far: https://stackblitz.com/edit/angular-96bdii?file=src%2Fapp%2Fgallery.component.ts
Now, my problem is that real-world images (instead of colored divs) need more time to be loaded completely. Therefore, the ngViewAfterInit hack doesn't work as the total width is not correct at the time ngViewAfterInit is called. Also, the total width is automatically calculated by a flexbox layout so I essentially don't know it (early).
Could you imagine a better (working) solution that perhaps uses CSS grid techniques I'm not aware of to limit the number of rows to one?
Kind regards

You could retrieve your images programmatically like this:
var img = new Image();
img.onload = function() {
//retrieve this.width
}
img.src = 'http://www.example.com/image.gif';
Then use it to compute the right width and photosPerRow

Related

I'd like to make code that dynamically creates overlayed images in a dynamically created container

can you tell me how to have the following code make multiple images that are layered over one another? Like if I wanted to sometimes have this code post an image1.png with image2.png overlayed over it, but with other if statements true it would post image1.png with image3.png overlayed over it?
// create the images:
var container = document.getElementById("container");
for (var i=0;i<3;i++) {
var img = document.createElement("img");
img.src="https://via.placeholder.com/350x150";
img.classList.add("img");
container.appendChild(img);
}
document.querySelectorAll(".img").forEach(function(img,i) {
img.id="image--"+i; // makes more sense to do that in the creation part too
})
document.getElementById('image--1').src = "https://via.placeholder.com/350x150?text=Image1";
<div id="container"></div>
I tried this code but I couldn't figure out a way to make images that overlay one another, it just posts them one after another.
I want to keep using this code because it always posts directly under the most recently created image, making a column of images on your webpage which is exactly the aesthetic I'm looking for.
you'll just have to target the image with onclick or onmouseover and set the zindex accordingly.
for example:
image1.addEventListner('click', ()=>{image1.style.zIndex = '5' image2.style.zIndex = '3' image3.style.zIndex = '1'}
So I fiddled with it a whole lot and found out that I had to give image0 absolute positioning first and then everything would be hunky-dory with changing the styles of the subsequent images so they lay ontop of image0.
I tested it and it worked great. Batfreakseyes goes right ontop of batfreak.

outerHight doesn't take table hight

I use var targetHeight = jQuery('.acc-content-inner').eq(currIndex).outerHeight(); to take hight of an element. But if the div.acc-content-inner has a table in it, it doesn't add the height from the tabele to the targetHeight
The height may not be calculated right not because of the table, but because of the images. If you run your code on document.ready. My guess is that jQuery calculates it before the images get downloaded. A similar effect can be seen here: http://jsfiddle.net/z2eounmt/1/ (notice it disappears on page refreshing if cache is not cleared). The first time the output is 40, so the height of the image is not included.
To solve this issue, either use imagesLoaded, or change your function to be run on window.load. or change the way your accordion works.

Responsive "masonry-like" columns without using masonry (trying to avoid position:absolute;)

I have a layout of boxes that are all floated left and when you click on their headings, they slide open revealing content. The issue is that the way floats work, when you click to expand one of them, it messes with the row underneath.
http://jsfiddle.net/FCCye/ <-- click on one of the headings to see the issue.
I've solved this by separating them into columns like so:
http://jsfiddle.net/caW4M/
That works fine, however, the layout needs to be responsive, so when the window is 480 or lower, it needs to be 1 column. Between 480 and 768 it needs to be 2 columns. Anything above 768, 3 columns. (obviously, the jsfiddles don't show the breakpoints I have set up.)
This is the code I've come up with to solve this, however it is not working at all. I was wondering if someone could tell me what I'm doing wrong.
// Create all three portfolio columns
var one = $('<div/>').addClass('column').addClass('one');
var two = $('<div/>').addClass('column').addClass('two');
var three = $('<div/>').addClass('column').addClass('three');
// Store all portfolio elements into variables once they're in columns
var colElems = $('.column .project');
// Now append the columns
var winWidth = $(window).width();
if ( winWidth > 480 && winWidth <= 768 ) {
// Remove everything from columns and delete existing columns
$(colElems).appendTo('#portfolio .content');
$('#portfolio .content').remove(one,two,three);
// Store portfolio elements into variables for safe-keeping
var c1Elems = $('.project:nth-child(2n+1)');
var c2Elems = $('.project:nth-child(2n+2)');
// Perform appends into portfolio columns
c1Elems.appendTo(one);
c2Elems.appendTo(two);
// Append portfolio elements to columns
$('#portfolio .content').append(one,two);
}else{
// Remove everything from columns and delete existing columns
$(colElems).appendTo('#portfolio .content');
$('#portfolio .content').remove(one,two,three);
// Store portfolio elements into variables for safe-keeping
var c1Elems = $('.project:nth-child(3n+1)');
var c2Elems = $('.project:nth-child(3n+2)');
var c3Elems = $('.project:nth-child(3n+3)');
// Perform appends into portfolio columns
c1Elems.appendTo(one);
c2Elems.appendTo(two);
c3Elems.appendTo(three);
$('#portfolio .content').append(one,two,three);
}
So, what I'm trying to do is append the normal 3 columns when it's not between 480 and 768 (because on mobile size, the columns would stack on top of each other anyway) and when between 480 and 768, only append two columns. So my thought is that at the different sizes, I would have to pull all of the boxes out of the columns, delete the columns, and reappend the columns in different numbers based on the window width. This has proved to be a failed attempt, so if anyone can explain to me what I'm doing wrong I would be very appreciative!
Thanks!
Not an answer to your question, but if you will follow the advice then your question will no longer be of interest. ;-)
First of all why don't you use CSS3 Media Queries for your different layouts? That is what they are for.
Secondly it is "bad practice" to use pixel values (or any other kind of absolute units) for defining breakpoints, even if a lot of authors actually do! It is best to only use relative units like 'em'.
The new Flexbox module could also be an option for you, depending on the supported Browser versions (especially IE 8).
And why don't you let the expanded box not simply overlap the other content by using 'position: absolute'?
Well, doing things with Javascript which should be done with pure CSS isn't a good idea. What happens, when JS is deactivated? And also from a performance point of view, on resizing the viewport ... - all bad.
So my advice would be to completely rethink your approach.

Changing Button Attributes to Match Slider Window

Greets,
First - this site is incredible. I've learned a ton of great things here!
I'm using a jquery based slider program to display a sequence of pictures (a series of books). Beneath the slider window I've positioned a "PDF" buttons. I'm trying to sort how to have the button download the file associated with whatever image is currently displayed in the slider box. So if "Picture #3" is showing in the slider window I need the PDF button to be associated with the respective #3 file. I believe I need to change each button's attributes dynamically to match what's showing in the slider window.
You can view the beta site at beta
I suspect I'll need some sort of javascript to snag the click event and feed it to the button's attributes. That's as far as my shaky legs can carry me with this one. Can anyone point me in the right direction? I'm a real noob at this and learning slowly so use small words!
Cheers,
TY
You're on the right track. I think this would probably work, but I'm not used to culling from arrays of jQ elements.
Put the filename into an alt tag in your list items, then use this script:
$('#download-button').click( function() {
var left_pos = $('ul').css('left');
var win_width = $('ul').innerWidth();
left_pos = left_pos * (-1) /* Will convert from negative to positive */
var slide_num = left_pos/win_width;
var slides = $('ul').find('li');
$(this).attr('src', 'path/to' + slides[slide_num].attr('alt'));
});
Also, upon checking the living DOM while playing around with the slider, I noticed that it seemed to jump a bit if you changed directions toward the end of/beginning of the slides. You may want to investigate that

Table Row SHOW / HIDE *Without* Column Width Resizing, w/ TableLayout: auto

I have table with multiple rows, showing items for sale. When the user clicks on a row, a Javascript inserts / shows a new row right beneath it with details about the item. The issue is when the description is long, it forces the column widths to readjust / resize. This shifts the columns positions and is really annoying, especially for the user. Right now, I have my table.style.tableLayout: auto. I actually prefer it this way, because the columns are adjusted to the content.
My question is: how do I dynamically "lock" the widths of the columns in my table so that when I insert / show the new row, the columns do not readjust / resize?
I've tried:
dynamically setting the table to temporarily "tableLayout: fixed"
inserting / showing my new row
changing the table back to "tableLayout: auto"
Actions 1 & 2 works in in FireFox, but not in Safari and IE (6 & 7). However, doing all three seems to prevent the columns from shifting too much.
The frustration is unbearable ... loosing lots of sleep ... please help!
Thanks.
For those looking for the code (this is done in jQuery). This also assumes the first row has the proper widths for each cell. Pretty easy changes if needed.
$('table.class_of_table_to_fix tr:first td').each(function() {
$(this).css({'width': $(this).width()+"px"});
});
I would set a percent width on each column simply as a guide. Set it just once on the TH of each column. The browser will still adjust the columns to content if necessary, but the columns will stay in place more consistently.
Next, I would never put css "white-space:nowrap" anywhere on that table. A long description should not break the table layout, it should wrap around properly on multiple lines, and be readable if you set the widths on each column to suit the type of data. Similarly I would keep the use of (non breakable spaces) to dates, times and numbers and allow the text to wrap.
Other than that, I do this at my job on a dialy basis, and there's a time when you need to stop ulling hairs asking the browser to do something it's not designed to do. Content should flow and adapt. Locking column widths to pixels is 99.99999% of the time a bad idea.
PS: If you really, reeally, REALLY need to lock columns, the only solution I'm aware of that works with CSS2 and accross all browsers is to use images. You could insert a 1px high transparent gif image in each column, and counting in the padding of the cells (TD), set a pixel width on each image (IMG), instead of on the columns (TH/TD). You could hide those in the TH for example. You can leave the images at 1 pixel wide and set percent widths on TDs, and when you open a new row, you would get each column width minus TD Padding, and set that to the corresponding IMG. I haven't tried! I just know that in many projects I've worked on, I've used small gif images to lock a minimum vertical spacing between columns, for example.
I had a similar problem when I was implementing a table with groups that could be toggled. I wanted the initial ratio between the columns to stay the same without fixing the widths of the columns. By default the browser would change the widths depending on the visibility of the table's rows, which was undesirable.
I went ahead and followed #faB's suggestion of applying percentages, but doing so using a small script that would calculate the percentages of the th elements and apply them after the initial render. This made my columns stay the same width, even with all rows hidden.
Here's the script, which uses jQuery:
(function($){
var lock_widths = function() {
var total_width = $('table').innerWidth();
var headers = $('table th');
var leftover = 100;
$.each(headers, function(ix, el) {
var header = $(el), width;
// on the last call use the leftover percentage
if (ix == headers.length - 1) {
width = leftover;
} else {
leftover -= width = header.outerWidth() / total_width * 100;
}
header.css({'width': width + '%'});
});
};
$(document).ready(lock_widths);
})(jQuery);
Tested in IE7+, Firefox and Chrome. This works for my special case because I have header columns as a reference, but it could be rewritten to measure some other columns.
You can display the details of the row beneath the clicked one in DIV and set its
style="overflow:auto";
so that details will wrap and scrollbar will be available to display entire text.
I don´t know if you´re familiar with jquery, but that´s what I would use - in combination with a separate class for the column that´s causing resizing in the new row - to:
Calculate / get the with of the column
Set the with of the afore mentioned class
Add the row
I haven´t tried it, but that should do it.
By the way, there are probably other ways to do it, I´m just more familiar with jquery (for point 1. and 2.).

Categories