document.height not affected by jquery calls. - javascript

I have already followed instructions on how to make a specific div height take up the entire document. I created the following function, which works perfectly when the page is first loaded.
function resizeBody() {
$(document).ready(function () {
$(window).resize(function() {
$('.body').height((document).height - $(".topbar").height() - 30);
});
$(window).resize();
console.log(document.height);
});
};
In another section of my code, I am hiding and showing divs using jquery to create tabs. These tabs are all of different heights. The code is as follows:
$(document).ready(function() {
$(".tab").click(function () {
$(".tab_content").hide();
$(".tab").css("font-weight","normal");
resizeBody();
});
$("#infoButton").click(function() {
$("#info").show();
$("#infoButton").css("font-weight", "bold");
});
$("#toolsButton").click(function () {
$("#tools").show();
$("#toolsButton").css("font-weight", "bold");
});
$("#dataButton").click(function () {
$("#data").show();
$("#dataButton").css("font-weight", "bold");
});
$("#visButton").click(function () {
$("#vis").css('display','inline-block');
$("#visButton").css("font-weight", "bold");
});
resizeBody();
});
My problem is that when I hide or show a div, the properties of the document aren't updated. Calling console.log(document.height) in the resizeBody() function still prints the original height of the document. Oddly, when I type "document.height" directly into the developer console, the correct (resized) value is printed.
Additionally, after opening the developer console, the page seems to update (without any kind of refresh) and the body div is correctly resized.
What am I missing here? Is this a problem specific to Chrome or am I misunderstanding something fundamental about the way javascript deals with the document object.
It may be important to note that all of my divs use inline-block as their display style. Each div gives a specific value for it's height in the web inspector.

Related

Bootstrap tooltip gets stuck if element changes when visible

I am using Bootstrap 5.1.3 (in Rails). Our application consists of dynamically loaded data, that is not always the fastest to load (some complicated SQL queries / huge amounts of data to make calculations with).
We use tooltips on different elements to show extra information / indicate (click)actions. Tooltips are added like this.
On the element that should get the tooltip:
data-bs-toggle="tooltip" data-bs-placement="top" title={question.questionDescription}
In that Bootstrap file:
componentDidUpdate(previousProps, previousState)
{
// Enable all tooltips.
TooltipHelper.enableTooltips([].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')));
}
And then TooltipHelper:
static enableTooltips(targets)
{
var enabledTooltips = targets.map(function (target) {
return new bootstrap.Tooltip(target, { trigger: 'hover' });
});
}
The tooltips work, but don't always go away. My guess is that when a tooltip is shown (because hovering over something) and then that element (or a parent of that element) gets changed, for example the content of it, the tooltip stays there. No matter if I click somewhere of hover over other elements.
I've tried adding a delay within the enableTooltips()-function. This seems to work, but the needed delay is too big. Also, it still breaks when elements are dynamically added and content is loaded, when the page isn't reloaded.
My hacky solution:
static enableTooltips(targets)
{
setTimeout(function() {
var enabledTooltips = targets.map(function (target) {
return new bootstrap.Tooltip(target, { trigger: 'hover' });
});
}, 5000);
}
Anyone know of a solution? Thanks

jquery offset top wrong value, but gets right on page resize

I want to achieve a sticky menu like the left navigation on this page: http://getbootstrap.com/2.3.2/scaffolding.html.
My menu is a nav element with position:relative (I tried static as well) that goes fixed when it reaches the top of the viewport.
here's my function:
$(document).ready(function() {
function stickyNav() {
var elementPosition = $('nav').offset();
console.log(elementPosition);
$(window).scroll(function(){
if($(window).scrollTop() > elementPosition.top){
$('nav').addClass("sticky");
} else {
$('nav').removeClass("sticky");
}
});
}
stickyNav();
}); //document ready
the console.log(elementPosition); returns an offset top of around 1200px on page load, which is wrong. But if i resize the page, the value changes to around 650px which is the correct offset top and the function does what it is supposed to be doing.
I've looked around and found out that offsetp top maybe wrong when it's on hidden elements, or it has issues with margins but I actually don't have any complex structure here, just a single visible nav element .
any help on figuring this out would be much appreciated! thanks!!
jQuery(document).ready handler occurs when the DOM is ready. Not when the page is fully rendered.
https://api.jquery.com/ready/
When using scripts that rely on the value of CSS style properties,
it's important to reference external stylesheets or embed style
elements before referencing the scripts.
In cases where code relies on loaded assets (for example, if the
dimensions of an image are required), the code should be placed in a
handler for the load event instead.
So if you're using stylesheets that are loaded AFTER the script in question, or the layout of the page depends on image sizes, or other content, the ready event will be hit when the page is not in its final rendering state.
You can fix that by:
Making sure you include all stylesheets before the script
Making sure the CSS is more robust, and doesn't depend that much on content size (such as images)
Or, you can do this on window load event.
Edit:
If you want to make your script dependent on more than one async event (like the loadCSS library), use this:
var docReady = jQuery.Deferred();
var stylesheet = loadCSS( "path/to/mystylesheet.css" );
var cssReady = jQuery.Deferred();
onloadCSS( stylesheet, function() {
cssReady.resolve();
});
jQuery(document).ready(function($) {
docReady.resolve($);
});
jQuery.when(docReady, cssReady).then(function($) {
//define stickyNav
stickyNav();
});
You can add a check to see if your CSS has loaded by setting a style tag in your document which shows a test element, and then overwrite this in your CSS file to hide it. Then you can check the status of your page by checking this element. For example...
In your HTML:
<div id="loaded-check" style="display:block; height:10px; width:10px; position:fixed;"></div>
In your CSS:
#loaded-check { display:none; }
In your jQuery script:
var startUp = function() {
var cssLoaded = $('#loaded-check').is(':visible');
if (cssLoaded) {
$('#loaded-check').remove();
doOtherStuff()
}
else {
setTimeout(function() {
startUp();
}, 10);
}
}
var doOtherStuff = function () {
//bind your sticky menu and any other functions reliant on DOM load here
}

Hide link when table is visible

I have a horizontal website that keeps displaying my tables/images (my images are in tables) when you click the 'more' link at the bottom. I am trying to make it so that when my last image/table is visible, the 'more' link disappears. I am very new at coding but I managed to compile this but it's not working.
I read that CSS always recognizes an element as visible as long as it fits within the page, and that Javascript must be used to check if it is actually visible on a page. Any solution is appreciated, thanks.
<script src="./lib/jquery.js" type="text/javascript">
function() {
if($('#finaltable').is(':visible')){
$('#morelink').remove(this);
}
}
</script>
<html>
//There are about 20 tables but the last one is ID'd as 'final table'
<table id="finaltable">
<tr><td>Final Table</td></tr>
</table>
You cannot use jquery :visible, because it's based only on the fact that your element has CSS display different that none (its parents as well) and its width and height greater than 0. references
In your case, I would use the offset property. On the click event on the "More" button to check where is the final table.
<a id="more" href="#">More></a>
<script>
jQuery(document).ready(function () {
$("#more").on("click",function(e)
{
//finaltable display on screen
if($("#finaltable").offset().left<=0)
{
$("#more").hide();
}
});
});
</script>
Refer to window.scrollY in a setTimeout to determine if your are nearing the bottom of the page: https://developer.mozilla.org/en-US/docs/Web/API/Window.scrollY
You are declaring a function in JavaScript but not calling it. You could write the following code.
/* Declare the function */
var f = function() {
if($('#finaltable').is(':visible')){
$('#morelink').remove();
}
}
/* Call the function */
jQuery(document).ready(function () {
f();
});
Here is a demo of the code.

mCustomScrollbar scrollbar display on hidden div

I've seen answers on here on how to do this, but I just can't get it to work. Maybe another set of eyes will help. I'm trying to get the scrollbar to appear in a div that popups when an image is clicked. Here's the code for that:
('modalcs' is the name of the div that pops up)
And the function:
function update_scroll(theID)
{
document.getElementById(theID).style.display = 'block';
$(".scrollable").mCustomScrollbar("update");
}
In my $(document).ready(function() I have:
$(".scrollable").mCustomScrollbar({
theme:"dark-thick",
scrollButtons:{
enable:true,
advanced:{
updateOnBrowserResize:true,
updateOnContentResize:true
}
}
});
and I understand that on page load since the hidden div isn't seen, the scrollbar is unable to see its content.
TIA for any help!
The problem is that the "update" command does not operate on a collection, so if $(".scrollable") returns more than one element, it will update only the first one. Use $.each
$(".scrollable").each(function(){
$(this).mCustomScrollbar("update");
});
On the other hand, since you are operating on 1 element, you can just change your function:
function update_scroll(theID)
{
$('#' + theID).show().mCustomScrollbar("update");
}

Javascript display html if div exists

I am trying to display a table (or ul) that will contain a navigation bar on my page, but only displays the tabs that will contain jquery called divs present on the html.
Essentially, it's a single html document that contains all divs, jquery hides all divs but the first, and the nav bar will allow to navigate through each.
Now I am trying to make it easy to use for my client, so that the menu items will only exist if the div for it also exists. I've got most of it done, the only thing is actually knowing if a div exists.
I tried using this:
if(document.getElementById("page1")) {
document.write("<b>Good morning</b>");}
else
{
document.write("<b>Bad morning </b>");
}
When I place the above code within the div page1, it returns true. Is there no way to do it from the top of the page and not within the div?
Thanks!
Update:
As suggested by many, I have used the following:
$j(document).ready(function(){
//Hide the sections we don't need right away
$j("#page2").hide();
$j("#page3").hide();
$j("#page4").hide();
if ($j('#page1').length > 0) {
var page = 'Excellent Morning' ;
}
});
Then when I try to use:
document.write(page);
It displays the following instead:
[object HTMLBodyElement]
Why not use jQuery since you are already?
if ($('#page1').length > 0) {
// do stuff...
}
EDIT: As davin pointed out, your code should be evaluated after the DOM has been rendered. You can do this by placing it in a $(document).ready call:
$(document.ready(function() {
if ($('#page1').length > 0) {
// do stuff...
}
});
EDIT 2: Based on the OP's edits, a better solution would be to add a placeholder element and to set its content (like FishBasketGordo suggested). An example of this:
$(document.ready(function() {
//Hide the sections we don't need right away
$("#page2, #page3, #page4").hide();
if ($('#page1').length) {
$('#myPlaceHolder').html('<b>Good Morning</b>');
}
else
{
$('#myPlaceHolder').html('<b>Bad Morning</b>');
}
});
Somewhere else in the document...
<span id="myPlaceHolder"></span>
If you place it at the top of the page, the page1 div doesn't exist when the code runs. If you are using jQuery, place the code in a $(document).ready event. Then, you can put it where you want it within the markup. Here's an example:
$(document).ready(function() {
if (document.getElementById("page1")) {
document.write("<b>Good morning</b>");
} else {
document.write("<b>Bad morning </b>");
}
});
Although, rather than doing a document.write, I would consider having a placeholder span or div, and setting it's innerHTML property (or use jQuery's html method). I would also use CSS for my style instead of <b> tags, but that's another matter entirely.
You can use
if ($(selector).length > 0) {
// element exists
}
or you can check out this post for a more elegant solution
Is there an "exists" function for jQuery?

Categories