It's not the first time I'm bumping into this problem and never have the opportunity to figure out something right.
So here's the problem:
I have 2 divs. Each of them have a title in them. Depending on the length of the title, the title may have to fit on 2 lines or not. All of this is generated from a CMS, so no way of telling if one of them will have 2 lines or one at a given time (so I can't just separate them with a class if they have 1 line or 2)
Here's the juicy part: I want the title in those two divs centered vertically. Line height won't do it because theres always the possibility of it being on 1 or 2 lines, and display:table-cell + vertical-align:middle is not compatible with IE7.
So is there a way to vertically center those titles and that will work in every browser?
Edit: Heres a photo of the situation I try to explain:
Edit #2: Here's a code sample recreating my example. We want to get them both centered. http://jsfiddle.net/m7bLj/
Edit #3:
After the answer of #mikhailvs, I came up with this code, that worked.
$(document).ready(function(){
$(".container-div").each(function(){
$(this).children('div').css('top', String($(this).height() / 2 - $(this).children('div').height() / 2) + 'px');
})
})
If you are willing to use jQuery, you can do something like this:
var div1onLoadCallback = function () {
var w = $(window);
var div1 = $('#div1');
div1.css('top', String(w.height() / 2 - div1.height() / 2) + 'px');
}
Then declare your div like <div id="div1" onload="div1onLoadCallback()"></div>
and similarly for the second div. Of coarse, you would need to modify the css position attribute for the titles for it to work (such as position: absolute).
Related
I'm trying to render a pdf from dynamic content with puppeteer and react. The layouting is done in material ui for react, so page-break-before:always is not an option because i need the grid layout which is flex and wont work with page-break-before. I need to get the height of one page, so the header of the next page doesn't overflow. If i calculate where the header should be with pagewidth * Math.sqrt(2), it gives me the position value of where it actually is. But unfortunally when i go to print it it's overflowing by a few pixels and the error is getting bigger with each page. I have wondered how to fix this problem for the last 2 days. I've even tried resetting the position with a margin.
Here are some code snippets from my program which might maybe help.
let width = 800//document.documentElement.getBoundingClientRect().width
for (let pagewidth = width; pagewidth * Math.sqrt(2) < document.documentElement.getBoundingClientRect().height; pagewidth += width) {
let pageBreakXPosition = Math.ceil(Math.sqrt(2) * pagewidth)
header.style.marginTop = pageBreakXPosition - header.getBoundingClientRect().top + "px"
}
this is just the "important" part of the code because all of the other code targets the elements' width or some other styles. My problem would really be fixed if i just knew the exact point where the page would break, but appareantly my calculation for pageBreakXPosition is wrong in some way.
attached is a picture of the overflow(if you look carefully you can see that the error is getting bigger):
Page 2
Page 4
I think you can set the height as per your requirement and that should work
Use these:
`- document.height()
document.body.scrollheight
screen.height
$(document).height()`
I am in a scenario like this:
We have two similar popup windows, and such popup windows are generated by a factory (in Javascript) so that they share same common events & functions. One of them is our custom resize function named resizeFormRowService. It will get called when the browser window fires the resize event.
As the popup window is in a structure like repeating
<div class="row">
<div> //label </div>
<div> //data </div>
</div>
The resizeFormRowService first get the width of the parent div with class row, then set it's first div child (which is label) to a fixed width like 140px, and set second div's width to "parent - first child". All are done by JQuery (as shown below)
I found that there is a strange behavior on one of the popup in Chrome (I am comparing two similar popup windows as stated).
The calculated width of the second child div (which is data) is 5px more than the other popup's corresponding field. So I log something in resizeFormRowService to trace what's going on.
StandardTemplatePopup.prototype.resizeFormRowService = function () {
var self = this;
var $popUp = self.getPopup();
...
var $rows = $popUp.find('.row');
$rows.each(function () {
var $this = $(this);
var $firstDiv = $this.find('div:first');
var $secondDiv = $this.find('div:eq(1)');
var labelColWidth = self.options('labelColWidth');
// labelColWidth is something we can config, so both popup firstDiv's width is the same
// so I think the problem must be in $this.width()
$firstDiv.width(labelColWidth);
//Add by me, want to see which row is this
console.log($this);
//Add by me, see this row's width
console.log($this.width());
var width = $this.width() - $firstDiv.outerWidth() - 0.5;
$secondDiv.width(width);
});
...
};
Running this on both popup windows, one log 270px while the other one log 265px! So I try to see which rows are they, at this point I think maybe there is some scripts within the first popup window changing the row's margin / padding and thus changing its width, but surprisingly it's not the case
Here is first popup
Here is the second popup
As shown, the second child div's calculated width differ by 5px, but the parent's row width is exactly the same, which is contradicting what I logged in the resizeFormRowService!
So my question is: are there any known issues of JQuery width() which lead to my problem? If no, then any advice pointing to potential cause is appreciated.
EDITED:
I hope this may hint someone, one of my teammates, by trial & error, adding an empty div at the end of the first popup window
<div class="col-xs-12"> </div>
Then everything goes fine...both popup windows will resize correctly.
PS1: The smaller result: 265px is the correct and expected result
PS2: The height difference in the images is due to the wrongly calculated width of the second child div which makes content too wide to show in one line, so the height is auto-increased
I'm just going to put this in an answer because comments aren't very insightful.
To me, it would seem that your calculations are too fast and don't keep to any pre-set values. Something like say, a CSS transition would 100% surely mess it up for you. I personally would code it more like this (being a front-ender myself)
$rows.each(function () {
var $this= $(this);
var $firstDiv = $('div:first', $this);
var $secondDiv = $('div:eq(1)', $this);
var labelColWidth = self.options('labelColWidth');
// labelColWidth is something we can config, so both popup firstDiv's width is the same
// so I think the problem must be in $this.width()
$firstDiv.width(labelColWidth);
//Add by me, want to see which row is this
console.log($this);
//Add by me, see this row's width
console.log($this.width());
//why recalculate the $firstDiv.width when you have labelColWidth?
//try to avoid simple names like "width" for prevention of double naming
var newWidth = $this.width() - labelColWidth - 0.5;
$secondDiv.width(newWidth);
});
-- I should mention, Selectors like div:first and div:eq(1) tend to break when you insert things like : after or : before. I would recommend you use classes instead.
I have seen this done a few times before. I can't remember the other sites, but if you know of others I'd like to see. (https://gumroad.com/)
Basically, when they do something like:
Share your 'songs' directly to your 'fans'. And the words in the quotes keep getting replaced.
I was wondering if there is a JS/Jquery library to help with that. Or otherwise I'd like some other websites that do it so I can get ideas!
Thanks.
I implemented something similar (without animations) using jQuery.
The code basically cycles data from an array every 2000ms, and adds it to a span.
Live Demo - http://jsfiddle.net/Dogbert/vF4rj/3/
JS:
var options = [
["music", "listeners"],
["software", "users"],
["films", "viewers"],
["comics", "readers"]
];
var interval = 2000;
var holder1 = $(".holder-1"), holder2 = $(".holder-2");
var currentIndex = 0;
function doIt() {
holder1.html(options[currentIndex][0]);
holder2.html(options[currentIndex][1]);
currentIndex = (currentIndex + 1) % options.length;
setTimeout(doIt, interval);
}
doIt();
HTML:
<h2>
Sell
<span class="holder-1"></span>
directly to your
<span class="holder-2"></span>
</h2>
If you are interested in their approach, it seems like this is what they are doing:
They have the header text in their code twice. One is what you see being animated. The other is hidden by setting its opacity to 0. This hidden version is what will be used to do any calculations on the displayed one.
The hidden version has its text updated by inserting new text into placeholder span tags. The displayed version has placeholders in that spot that are empty spaces, and their width is animated by using the new width from the hidden version.
The hidden version is also used to determine the positioning of the new text relative to the rest of the sentence, and based on that information, an HTML element containing that text is animated to fall in perfectly where it should.
A pretty clever approach.
What makes this work for Gumroad is the slick animation so I feel answers are incomplete without this essential element.
That being said, the d3 javascript library (d3js.org) has a very good implementation of the base functionality plus support for transitions. The key code is the following which allows you to easily specify the type of css transform you want to be applied (see the last line):
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(32," + (height / 2) + ")");
A full example can be viewed here: http://bl.ocks.org/mbostock/3808234
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!
This is a followup question for this:
Scrollpane on the bottom, css is hacky, javascript is hard
I ended up doing the scrolling in the same way explained in the accepted answer.
Now there is a request that one item is selected somehow (eg. as an url parameter or by some javascript calls) I should scroll the pane to the item with the corresponding ID in the scrollpane. Like a link to an anchor () would work!
I want to make a javascript call like this
function scrollTo(id) {
$('#middle').magicallyScrollThatItemWouldBeVisible(itemid);
}
But this is not in jQuery (or at least I don't know of it). So is there a way to make it?
I'll post a simple jsFiddle here:
http://jsfiddle.net/ruisoftware/U6QdQ/4/
Help me write that scrollTo function!
A .animate would be fine too.
UPDATE: If it was not clear I would like it to only align to the left or right side of the panel, it it was overflowed on that side (so the minimum possible amount of scrolling happens)
It's not jQuery, just JavaScript, and I've actually never used it all, so I'm not sure how you would have to mess with it to get it to work in this situation, but there is a scrollIntoView function:
yourElement.scrollIntoView();
Since the elements have a fixed width, you can count the number of elements by using .index() + 1, and animate to this value (after subtracting the container's width).
If you want the element to be centered, use - Math.round(middle.width()/100)*50.
Fiddle: http://jsfiddle.net/U6QdQ/17/
//This code should be run on load / DOMReady
(function($){ //Run on load / DOMReady
$.fn.magicScrollTo = function(){
var middle = $("#middle");
var currentScrollLeft = middle.scrollLeft();
var width = middle.width();
var newScrollLeft = this.offset().left + currentScrollLeft - middle.offset().left;
if(newScrollLeft >= currentScrollLeft && newScrollLeft <= currentScrollLeft + width - this.outerWidth()) return;
if(newScrollLeft > currentScrollLeft){ //If the element is at the right side
newScrollLeft = newScrollLeft - width + this.outerWidth();
}
middle.animate({
scrollLeft: newScrollLeft,
}, 'fast')
}
})(jQuery);
Usage:
//Select the 4rd element, and scroll to it (eq is zero-based):
$('.item').eq(3).magicScrollTo();
Something along these lines would be a good start:
http://jsfiddle.net/vHjJ4/
This will bring the target into the centre of the carousel. I think you will have to add in some extra checks to make sure that it didn't scroll to far, for example if you targeted the first or last element...unless this is built into the scroll function (it might be).
I'm not sure I understand your question exactly, but it sounds like you're asking how to scroll horizontally to the selected item in the bottom pane. If so, try something like this:
//get the position of the element relative to the parent ("middle")
var pos = $("#itemid").position();
if (pos){
$("#middle").scrollLeft(pos.left);
}
From here, you can use the width of middle to center the item if needed.