I'm looking for a solution to only display a div if there is space to do so.
On my blog's post pages I display latest posts in the left sidebar, like so...
No Nay Never post page
I want to show a different number of sidebar items dependent on how long the post is. Currently I have three divs displaying different numbers of items and run this script.
if ($("#contentheight").height()>960 && $("#contentheight").height()<1200) {
document.getElementById("threeposts").className += "hide";
}
else if ($("#contentheight").height()>1200 && $("#contentheight").height()<1880) {
document.getElementById("fiveposts").className += "hide";
}
else if ($("#contentheight").height()>1880) {
document.getElementById("sevenposts").className += "hide";
}
However, this is hardly convenient and for very short posts it shows no items at all.
Is there a workaround whereby I can, for example, code for 7 items, but only show as many as the parent div can take? I tried using overflow:hidden but then you end up with the end item chopped in half.
For example, if there is enough room for three full items, they would be shown but any after that would not.
You can create a hidden div or a div which is not inserted into the DOM with the desired width.
Then insert item by item until the height of this div exceeds the length of your post.
Now you know how many items will fit into the div.
try something like this:
$('#container').children().each( function() {
var top = $(this).top;
var height = $(this).height;
if (top + height > $(this).parent().height()) {
$(this).className += "hide";
}
});
Related
I'm trying to implement an HTML infinite scroller in which at any given time there are only a handful of div elements on list (to keep the memory footprint small).
I append a new div element to the list and at the same time I'm removing the first one, so the total count of divs remains the same.
Unfortunately the viewport doesn't stay still but instead it jumps backwards a little bit (the height of the removed div actually).
Is there a way to keep the viewport still while removing divs from the list?
I made a small self contained HTML page (well, it still needs JQuery 3.4.1) which exposes the problem: it starts by adding 5 divs and then it keeps adding a new one and removing the first one every 1 second
function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
function removeit() {
// remove first one
var tiles = $(".tile");
$(tiles[0]).remove();
}
function addit() {
// append new one
var jqueryTextElem = $('<div class="tile" style="height:100px;background-color:' + getRandomColor() + '"></div>');
$("#inner-wrap").append(jqueryTextElem);
}
function loop() {
removeit();
addit();
window.setTimeout(loop, 1000);
}
addit();
addit();
addit();
addit();
addit();
loop();
<div id="inner-wrap"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
You can temporarily add position: fixed to the parent element:
first add position: fixed to the parent;
then remove the item;
then remove position: fixed from the parent
I have a feeling you're trying to have your cake and eat it, in that if you get the viewport to be "still", I think you're meaning you don't want a user to see the scrollbar move and then also not have any new affordance to scroll further down the page, because you would want the scrollbar thumb/grabber to still sit at the bottom of the scrollbar track?
I mean, you could just use $(window).scrollTop($(window).scrollTop() + 100); in your example to make it so the scroll position of the viewport won't visually move when removing elements, but at that point, you wouldn't be keeping the users view of the current elements the same or even allowing a user to have new content further down the page to scroll towards. You'd just be "pushing up" content through the view of the user?
If you are trying to lighten the load of what is currently parsed into document because you are doing some heavy lifting on the document object at runtime, maybe you still want to remove earlier elements, but retain their geometry with some empty sentinel element that always has the height of all previously removed elements added to it? This would allow you to both have a somewhat smaller footprint (though not layout-wise), while still having a usable scrollbar that can communicate to a user and both allow a user to scroll down, towards the content that has been added in.
All in all, I think what you currently have is how most infinite scrollers do and should work, meaning the scroll position and scrollbar should change when content is added in the direction the user is scrolling towards, this communicates to them that they can in fact keep scrolling that way. You really shouldn't want the viewports scroll position to be "still".
To see more clearly why I don't think you have an actual issue, replace your loop() definition with something like this...
function loop() {
$(window).scroll(function() {
// check for reaching bottom of scroller
if ($(window).scrollTop() == ($(document).height() - $(window).height())) {
addit();
removeit();
}
})
}
Okay now.. I really didn't know how to give this one a title. Here is my problem. I am trying to make a page where the body has a class defining the width of another div a.k.a baser.
I have a jQuery script that detects the width of the window and gives body a class hereafter. for example when the width of the window is about 900px - body will be given a class .col_6.
Each card is 150px in width, but when they have the additional class large they will be 300px in width. The problem now is that depending on the order of the cards in HTML, there will be some empty spaces if a card.large should be placed in a space only 150px wide. Then the card will automatically jump to next row and leave an open space of 150px in the previous row.
What I would like to know is - what can I add to my script to perhaps selecting a 150px wide card placed later in the order and move it in the empty spot or filling out the empty spot with a javascript made div ( for other purposes )..
I hope you are able to figure out my problem by reading this.. I have made a jsfiddle that shows my code and the problem. You can try resizing the window when reading the fiddle. It will show you how an empty space will be seen sometimes.
http://jsfiddle.net/EK8q2/4/
here is my javascript/jQuery if it can help you any way..
$(document).ready(function() {
winResize(window.innerWidth);
});
$(window).resize(function() {
winResize(window.innerWidth);
// Room for more functions
});
function winResize(w) {
resizeBaser(w);
// Room for more functions
}
function resizeBaser(w) {
var index = Math.min(10, Math.floor(w / 150));
if (index > 0) {
$('body').alterClass('col_*', 'col_' + index);
}
}
The algorithm as I see it is this:
Attach to load/scroll/resize events:
$(window).on('load scroll resize', function () {
});
There, group the $('.card') elements into an array of rows.
Something like:
var rowsObj = {}, rows = [];
$('.card').each(function(){
var el = $(this),
pos = el.position(),
currentRow = rowsObj[pos.top] || (rowsObj[pos.top] = []);
currentRow.push(el);
});
$.each(rowsObj, function(k, v) {
if (/^\d+(\.\d+)?$/.test(k)) {
rows.push(v);
}
});
// rows now contains array of arrays of $-ed elements
3. Then I'd enumerate the rows from end to start and tried to id all orphan cards (condition: single most narrow card) - having these, I'd search from top to bottom and tried to locate the possible new row (i.e. the last element of that potential row) and orphan.insertAfter(thatElement). Upon insertion, I'd exclude both rows (one containing the orphan, the other - incomplete row) from the array. Do until no pairs (orphan-incomplete) can be formed.
4.Then I'd think on how to extend this logic to widths larger than single card.
I would like to scroll horizontally the given element. The only way I find is using ScrollIntoView DOM method, which allows either align the element's bottom with the view bottom or the top - with the view top.
But what if the element is OK with respect to the Y axis, and I only want to scroll it horizontally? How can I align its left with the view left or its right with the view right?
EDIT
Here is more context. I have a YUI table with a horizontal scrollbar. I wish to scroll it programmatically to a certain TD node. I do not think window.scrollTo is of any help to me, since the scrollbar is on a div element, not on the whole page.
EDIT2
Turns out there is a duplicate SO question with the right answer - How can I scroll programmatically a div with its own scrollbars?
Voting to close mine.
I've recently had a problem with a table header that had inputs as filters for each column. Tabbing through the filters would move the focus, but if one of the inputs wasn't visible or if it was partly visible, it would only JUST bring the input into view, and I was asked to bring the full input and column into view. And then I was asked to do the same if tabbing backwards to the left.
This link helped to get me started: http://www.webdeveloper.com/forum/showthread.php?197612-scrollIntoView-horizontal
The short answer is that you want to use:
document.getElementById('myElement').scrollLeft = 50;
or:
$('#myElement')[0].scrollLeft = 50;
Here's my solution (which may be overkill for this question, but maybe it'll help someone):
// I used $.on() because the table was re-created every time the data was refreshed
// #tableWrapper is the div that limits the size of the viewable table
// don't ask me why I had to move the head head AND the body, they were in 2 different tables & divs, I didn't make the page
$('#someParentDiv').on('focus', '#tableWrapper input', function () {
var tableWidth = $('#tableWrapper')[0].offsetWidth;
var cellOffset = $(this).parent()[0].offsetLeft;
var cellWidth = $(this).parent()[0].offsetWidth;
var cellTotalOffset = cellOffset + cellWidth;
// if cell is cut off on the right
if (cellTotalOffset > tableWidth) {
var difference = cellTotalOffset - tableWidth;
$('#tableWrapper').find('.dataTables_scrollHead')[0].scrollLeft = difference;
$('#tableWrapper').find('.dataTables_scrollBody')[0].scrollLeft = difference;
}
// if cell is cut off on the left
else if ($('#tableWrapper').find('.dataTables_scrollHead')[0].scrollLeft > cellOffset) {
$('#tableWrapper').find('.dataTables_scrollHead')[0].scrollLeft = cellOffset;
$('#tableWrapper').find('.dataTables_scrollBody')[0].scrollLeft = cellOffset;
}
});
This is something I used a while back. There might be better and more efficient way of doing it but this gets the work done:
$(".item").click(function(event){
event.preventDefault();
// I broke it down into variable to make it easier to read
var tgt_full = this.href,
parts = tgt_full.split("#"),
tgt_clean = parts[1],
tgt_offset = $("#"+tgt_clean).offset(),
tgt_left = tgt_offset.left;
$('html, body').animate({scrollLeft:tgt_left}, 1000, "easeInOutExpo");
})
You just need to make sure that the item is an a tag with an href that corresponds to the target id element:
HTML:
go to section 1
...
<section id="one"> Section 1</section>
Hope this helps!
I have to display a table with many columns on a web page. The columns are basically days of the week therefore only 7 columns need to be displayed at once (out of four weeks in total).
I have set up a window with the overflow set to hidden which displays the first seven days and managed to get the table to scroll left seven days however the table won't scroll further that this. If I scroll back then the table scrolls back too far and the table totally disappears to the right.
I am quite new to jQuery and realise that I should be using possibly the position() or offset() functions. I am sure this is a simple piece of code although my hours of googling have turned up nothing that covers this problem.
Does anyone know any decent tutorials out there to get me started ? Thanks
It is simply having a container div of 500px with overflow set to hidden continaing a seperare div of 2000px. When the user clicks on the previous or next buttons the inner div will scroll plus or minus 500px dependent on the position.
try this:
$('.next').click(function(event){
if($('.table').css('left') != '-1500px') {
$(this).prop('disabled', true)
$('.table').animate({left:'-=500px'}, 500, function() {
$('.next').prop('disabled', false)
});
}
});
$('.prev').click(function(event){
if($('.table').css('left') != '0px') {
$(this).prop('disabled', true)
$('.table').animate({left:'+=500px'}, 500, function() {
$('.prev').prop('disabled', false)
});
}
});
http://jsfiddle.net/ZSFFS/27/
I am trying to create css to solve a problem with displaying a like button next to a page title. I have 3 cases.
The title fits to the left of the like button
The title is long and flows to multiple lines to the left of the button
The title has long words that overflow the div and cover the like button
My question: Is there a way to set up the div so when case 3 happens, the div grows and pushes the like button below the title but keeps the same functionality for cases 1 and 2?
Dynamically remove the width when the word causes overflow. By removing width, you cause the button to move down and thus behave like options 1&2.
Check these divs dynamically with some jQuery/JavaScript to see if a word causes an overflow.
//Javascript function to remove width class when overflow occurs.
//40em is an arbitrary width
$.each($('.ConstrainedDiv'),function() {
var wordregex = /\w+/g;
var content = $(this).html();
var wordArray = content.match(wordregex );
for(var i = 0; i < wordArray.length; i++) {
if(wordArray[i].length > 40) {
$(this).removeClass('someWidth');//behavior changes if you remove this
break;
}
}
});
Fiddle. Note the difference in behavior by commenting out the marked line. Note2 resolution and fiddle box width matter.[Demo tested in FF7]