I have a bootstrap modal whose size is set by:
<div class="modal-dialog modal-lg">
I want to be able to determine the modal's size (width actually) before I make a post request to a PHP program to display some dynamic content before displaying the modal. Does anyone know how to get this information?
I have also been trying to find either the width or height of the entire modal as well as the modal classes and found this solution. Though I must add that with this approach the width and height of the modal are only found after it has loaded.
I think that it is not possible to get the correct width and height of the modal before it is being displayed since it is hidden by default before the user clicks to open it. style="display: none; as inline style under the modal class in Bootstrap 3.3.2.
However if you like to get the correct width and height of modal once it is displayed you can use this approach.
// once the modal has loaded all calculations can start
// since the modal is hidden before it is loaded there are
// no dimesions that can be calculated unfortunately
$('#myModal').on('shown.bs.modal', function () {
// get the viewport height
var viewportHeight = $(window).height();
console.log ('viewportHeight = ' + viewportHeight);
// get the viewport width
var viewportWidth = $(window).width();
console.log ('viewportWidth = ' + viewportWidth);
// get the .modal-dialog height and width
// here the .outerHeight() method has to be used instead of the .height() method
// see https://api.jquery.com/outerwidth/ and
// https://api.jquery.com/outerheight/ for reference
// also the .find() method HAS to be used, otherwise jQuery won't find
// the correct element, this is why you got strange values beforehand
var modalDialogHeight = $(this).find('.modal-dialog').outerHeight(true);
console.log ('modalDialogHeight = ' + modalDialogHeight);
var modalDialogWidth = $(this).find('.modal-dialog').outerWidth(true);
console.log ('modalDialogWidth = ' + modalDialogWidth);
// I have included a simple function to log the width and height
// of the modal when the browser window is being resized
var modalContentWidthHeight = function () {
var modalContentWidth = $('#myModal').find('.modal-content').outerWidth(true);
console.log ('modalContentWidth = ' + modalContentWidth);
var modalContentHeight = $('#myModal').find('.modal-content').outerHeight(true);
console.log ('modalContentHeight = ' + modalContentHeight);
};
$(window).resize(modalContentWidthHeight);
});
I hope the above code somehow helps you figure out the modal dimensions and that you can take it from there..
Another thing that was really bugging me that you might encounter when using the Bootstrap 3.3.2 modal. If you like to get rid of this bug Open modal is shifting body content to the left #9855 concerning the modal position and given this bug it still not fixed Modify scrollbar check, stop static nav shift #13103 you can use this approach that works regardless of if you have a vertical scrollbar shown or not.
Reference: Bootstrap 3.3.2 Center modal on all viewport sizes with or without vertical scrollbar
$('#myModal').on('shown.bs.modal', function () {
// meassure the padding-right given by BS and apply it as padding-left to the modal
// like this equal padding on either side of the modal is given regardless of media query
var modalPaddingRight = $('#myModal').css('padding-right');
console.log ('modalPaddingRight = ' + modalPaddingRight);
// apply the padding value from the right to the left
$('#myModal').css('padding-left', modalPaddingRight);
console.log (
'modalPaddingLeft = ' + $('#myModal').css('padding-left') +
' modalPaddingRight = ' + $('#myModal').css('padding-right')
);
// apply equal padding on window resize
var modalPaddingLeft = function () {
var modalPaddingRight = $('#myModal').css('padding-right');
console.log ('modalPaddingRight = ' + modalPaddingRight);
$('#myModal').css('padding-left', modalPaddingRight);
console.log (
'modalPaddingLeft = ' + $('#myModal').css('padding-left') +
'modalPaddingRight = ' + $('#myModal').css('padding-right')
);
};
$(window).resize(modalPaddingLeft);
});
I hope some of this answer can help you. Since I am new to jQuery there might be better or more elegant ways to actually code this, though I would not know how at this stage. Nevertheless I think the information given here might be of help to you.
If you want the actual dimensions of an element using Javascript, JQuery has the built in .width() and .height() functions. I modified your <div> to add a data- attribute that has the bootstrap class incase you want to access that and an ID for easier access:
<div id="my_modal" class="modal-dialog modal-lg" data-size="modal-lg">
Then access it via Javascript:
var width = $("#my_modal").width();
var height = $("#my_modal").height();
var size = $("#my_modal").attr("data-size");
console.log("Width Is: " + width + " and Height Is:" + height + "and Size Is:" + size);
Hope that helps!
Related
I have a js code that adds margin-top to a row with a specific class name (page with id=3) . I would like this code runs before page load because now it instantly displays the row without margin-top and then add it. The row should be displayed with the margin-top already be added.
My site is on wordpress and i added the js script on head.
I have tried
window.onpaint = checkMargin();
but it did not work. Any idea?
This is my js code
<script type="text/javascript">
//sets margin-top in serv-col --- IF not mobile version
function addServMargin() {
containers = document.getElementsByClassName('serv-cont');
titles = document.getElementsByClassName('serv-col-title');
texts = document.getElementsByClassName('serv-col-text');
links = document.getElementsByClassName('serv-col-link');
col_pad = '0px';
if ( window.innerHeight > 800) { col_pad = '8.3vh'; }
for (var i = 0; i < titles.length; i++) {
title_height = titles[i].offsetHeight;
text_height = texts[i].offsetHeight;
style = window.getComputedStyle(containers[i], '');
cont_height = style.getPropertyValue('height');
cont_padd = style.getPropertyValue('padding-top');
links[i].style.marginTop = 'calc(' + cont_height + ' - ' +
cont_padd + ' - ' + col_pad + ' - ' + title_height + 'px - 1.48vh - ' +
text_height + 'px - 127px - 5vh)';
}
}
function checkMargin() {
if (document.getElementsByClassName('page-id-13')[0] && window.innerWidth > 900) { addServMargin(); }
}
window.onresize = checkMargin;
</script>
I don't think making it run first will solve anything. The first thing the code does is get the containers, titles, texts, and links... which it does by searching the DOM. It then loops through the titles array and does the adjusting as needed. If the script runs before any rendering is done, the DOM elements won't exist. It 1) won't be able to find them, and 2) can't loop through them because the array will be empty.
Actually even before that, it checks for the existence of the elements it's looking for, and the screen size. I think the only way to get it to work w/o making it look like an after thought adjustment, would be to use CSS and media sizing to set the styles in the first place.
As I know JS is executed as the script tag is reached by Browser html interpreter. So putting it in the head tag on the first position may guarantee that it strats first, but can't guarantee that it ends execution before page loads, because the page loads asynchroniously.
I'm working on a project over at github pages, which I replace a bootstrap .dropdown with .dropup if the div's overflow-y: scroll will cause the dropdown menu to be cutoff / overflow. You can see the function working properly at this jsfiddle. Notice if you click on the ellipsis icon to the right on the top rows, it will drop down, if you click on the icon on the bottom rows, it will drop up.
Now, my actual implementation (github page), the code is exactly the same (below), but it wants to replace all .dropdown classes with .dropup when opened, including the top-most row which gets cut off, seen in the photo below.
I've been struggling with this for a week and can't quite figure it out. I've tried a few different things that I thought fixed it but ended up just being a hack and didn't work on mobile, or replaced some but not all etc.
Here is the Javascript / jQuery I'm using, which can be seen in the jsfiddle and my github source here.
$(document).on("shown.bs.dropdown", ".dropdown", function () {
// calculate the required sizes, spaces
var $ul = $(this).children(".dropdown-menu");
var $button = $(this).children(".song-menu");
var ulOffset = $ul.offset();
// how much space would be left on the top if the dropdown opened that direction
var spaceUp = (ulOffset.top - $button.height() - $ul.height()) - $('#playlist').scrollTop();
// how much space is left at the bottom
var spaceDown = $('#playlist').scrollTop() + $('#playlist').height() - ((ulOffset.top + 10) + $ul.height());
// switch to dropup only if there is no space at the bottom AND there is space at the top, or there isn't either but it would be still better fit
if (spaceDown < 0 && (spaceUp >= 0 || spaceUp > spaceDown))
$(this).addClass("dropup");
}).on("hidden.bs.dropdown", ".dropdown", function() {
// always reset after close
$(this).removeClass("dropup");
});
Edit:
To clear up any confusion, here's an example of the behavior without my added .dropup function. jsfiddle Notice when you click the last menu item, it opens the menu but requires scrolling. I specifically want to remove the .dropdown class and add .dropup in this case, so no scrolling is required.
It took some basic math, but I managed to figure out what you desired to do. This code changes the bootstrap classes between dropup and dropdown depending on the room available for a normal dropdown.
I calculated this by detracting the height of the button, dropdownmenu and how far the button was scrolled down in the scrollContainer from the height of the scrollContainer. I got the value how much the div was scrolled down by using the buttons offset and detracting the offset from the scrollContainer.
Here is my jQuery (I selected the .playlist class because this was attached to your scrollContainer, but you should replace it by an id or select it by other means):
$(".dropdown, .dropup").click(function(){
var dropdownClassCheck = $(this).hasClass('dropdown');
var buttonOffset = $(this).offset().top;
var scrollboxOffset = $('.playlist').offset().top;
var buttonHeight = $(this).height();
var scrollBoxHeight = $('.playlist').height();
var dropDownButtonHeight = $(this).children('ul').height();
dropdownSpaceCheck = scrollBoxHeight>buttonOffset-scrollboxOffset+buttonHeight+dropDownButtonHeight;
if(dropdownClassCheck && !dropdownSpaceCheck){
$(this).removeClass('dropdown').addClass('dropup');
}
else if(!dropdownClassCheck && dropdownSpaceCheck){
$(this).removeClass('dropup').addClass('dropdown');
}
});
A working JSFiddle
Let me know if there are parts of the code that could be improved/done easier or if there are any problems with my solution.
I have not thoroughly checked, but .scrollTop() is probably why the code fails when combined with other elements in the DOM, so here is a solution without it:
function checkHeights(){
// LOOP through each dropdown
$('.dropdown,.dropup').each(function(index,element){
var $dropDown = $(element),
$dropDownMenu = $dropDown.find('.dropdown-menu'),
dropDownTop = $dropDown.offset().top,
visibleHeight = $dropDown.height(),
hiddenHeight = $dropDownMenu.height(),
ddTop = dropDownTop - hiddenHeight,
ddBottom = dropDownTop + visibleHeight + hiddenHeight;
// LOOP through all parents
$dropDown.parents().each(function(ix,el){
var $el = $(el);
// CHECK if any of them have overflow property set
if( $el.css('overflow') !== 'visible' ){
var limitTop = $el.offset().top,
limitBottom = limitTop + $el.height();
// CHECK if parent is better fit when dropped upside
if( limitBottom < ddBottom && ( ddTop - limitTop ) > ( limitBottom - ddBottom ) )
$dropDown.removeClass('dropdown').addClass('dropup');
else
$dropDown.removeClass('dropup').addClass('dropdown');
// BREAK LOOP
return false;
}
});
});
}
$(document).ready(function() {
checkHeights();
$('.playlist').scroll(checkHeights);
});
JS Fiddle here.
This one does not require any class or id given to it except for dropdown,dropdown-menu, and dropup (all of which are Bootstrap defaults) and would work fine even if there are multiple playlists on page.
UPDATE
The code is modified and wrapped in a function in order to allow being called when scroll event fires.
I think that the problem it's that you have a big header, and the jsFiddle don't. So ulOffset.top it's always big, and spaceDown is always negative
Replace parent div.dropdown with div.dropup.
I have jquery script where you can click a left and right button and it will scroll horizontally to show more content.
The content that needs to be scrolled are in a div with a width of 1296px, but i want to set my jquery code to automatically get the width of the div and when you press on one of the left or right scroll button it will scroll exactly 1296px.
I want to do it this way because I need to later on optimize the design for all screen size and this would be the easier way.
My code:
var $item2 = $('div.group'), //Cache your DOM selector
visible2 = 1, //Set the number of items that will be visible
index2 = 0, //Starting index
endIndex2 = ( $item.length ); //End index
$('#arrowR').click(function(){
index2++;
$item2.animate({'left':'-=1296px'});
});
$('#arrowL').click(function(){
if(index2 > 0){
index2--;
$item2.animate({'left':'+=18.5%'});
}
});
This Javascript should work:
var $item2 = $('div.group'), //Cache your DOM selector
visible2 = 1, //Set the number of items that will be visible
index2 = 0, //Starting index
endIndex2 = ( $item2.length ); //End index
var w = $("#group").width();
$('#arrowR').click(function(){
index2++;
$item2.animate({'left':'-=' + w + 'px'});
});
$('#arrowL').click(function(){
if(index2 > 0){
index2--;
$item2.animate({'left':'+=' + w + 'px'});
}
});
Check this fiddle. Basically we calculate the width initially to not do the same thing repeatedly and the reuse it whenever we need it.
Why not get the width of the visible container first, and then use that value later? Quick example:
var width = $('container').width();
And then during animations:
var left = $item2.css('left') + width;
$item.animate({'left',left});
As a note, innerWidth and outerWidth may be more beneficial than just width depending on how you've set everything up, so if values aren't quite right take a look at those documents.
I've created a fiddle that I think solves your problem:
http://jsfiddle.net/77bvnw3n/
What I did was to create another variable (called width) which on page load, dynamically gets the width of the container.
var width = $('.group-container').width(); //Container Width
This variable is also reset whenever the Next or Previous buttons are pressed (in case the window has been resized since the page loaded).
$('#arrowR').click(function(){
index2++;
//recheck container width
width = $('.group-container').width();
$item2.animate({'left':'-=' + width + 'px'});
});
Take a look and let me know if it helps.
Note: I replaced the 'Next' and 'Previous' images with coloured boxes in my Fiddle and I think you also had a typo in your code, should
endIndex2 = ( $item.length )
be changed to:
endIndex2 = ( $item2.length )
Been trying to get the top and left coordinates colorbox loaded content, but I keep getting either 0 or auto.
I'm executing the following in onComplete callback:
var cboxLeft = $('#cboxContent').css('left');//.position().left;
var cboxTop = $('#cboxContent').css('top');//.position().top;
console.log( 'cboxLeft: ' + cboxLeft + ' cboxTop: ' + cboxTop );
Right now console gives me: cboxLeft: 0px cboxTop: 0px
What I'm really after is appending custom close button to BODY. I need it accessible outside the cboxLoaded* area and visible. Hence trying to get position of content once colorbox is done with it.
.css() will not return these properties. You'll have to use .offset() instead.
So the code should look like:
var cboxLeft = $('#cboxContent').offset().left;
var cboxTop = $('#cboxContent').offset().top;
console.log( 'cboxLeft: ' + cboxLeft + ' cboxTop: ' + cboxTop );
Note: This gives the position relative to the document. If you want where it is on the current viewport (current view of the browser window), you might want to subtract window.scrollX and window.scrollY respectively.
I have 2 divs, one positioned absolutely right: 0 and the other relatively positioned center screen. When the window's width is too small, they overlap. How can I invoke a javascript function when this happens?
Thanks.
Mike
Edited to make clearer.
To check for overlapping div's you might wanna do a check once the page is loaded, and whenever the window is resized:
window.onload = checkOverlap;
window.onresize = checkOverlap;
And then use some offset-checking:
function checkOverlap() {
var centerBox = document.getElementById('centerDiv');
var rightBox = document.getElementById('rightDiv');
console.log("centerbox offset left: " + centerBox.offsetLeft);
console.log("centerbox width: " + centerBox.offsetWidth);
console.log("rightbox offset left: " + rightBox.offsetLeft);
if ((centerBox.offsetLeft + centerBox.offsetWidth) >= rightBox.offsetLeft) {
centerBox.style.display = "inline-block";
} else {
centerBox.style.display = "block";
}
}
You might wanna do some more checks in the function, e.g. to see if the box is already displayed inline, and such. But that should give you a good place to start.
edit: added some diagnostics and fixed error
Part 1:
Do it like this:
<script type="text/javascript">
document.getElementById('example').style.display = "inline";
</script>
...
<div id="example"> ... </div>
document.getElementById('div_id').style.display = 'inline-block'
document.getElementById('div_id').offsetWidth gives us width of div
offsetHeight, offsetLeft, offsetTop are useful also.