Display: Block/None html elements with css..not releasing from memory - javascript

I can't wrap my head around this. I have several Divs within a HTML page. Each Div represents a different section and thus contains different images for that section. All the images are referenced from css and displayed/removed using javascript (document.getElementById('DIV').style.display='none/block';).
For the purpose of this example lets say I have 2 divs. Each section Div(Div1 & Div2) would be the parent divs and any Div within those parents will be its child. (DIV1a, DIV2a)
I have found that if Div1 is set using display: block and uses the css Background-image:.... and Div2 is display='none' when I hide Div1 using style.display = 'none'; that it does remove it from the screen and allows me to show Div2..however the background-image is still present in the browser memory.
The interesting thing and which I can't wrap my head around is if I place the background-img into a child div(div1a) within DIV1 when I use style.display = 'none' for the the Parent DIV1 the child div1a image does get removed from the browser memory when I use style.display = 'none' on the parent DIV1. However I have found this also to be inconsistent....it seems to work on some parent divs and not on others.
As you can probably tell by this point I am heavily confused and really don't know how to approach this.
Thank you all for your time and thoughts.
Code Example:
When using this method
<div id="Div1">
content....
</div>
<div id="Div2" style="display: none">
...content
</div>
div#Div1{
background-image: url(images/mybg.png);
background-repeat: no-repeat;
width: 480px;
height: 360px;
}
document.getElementById("Div1").style.display='none';
document.getElementById("Div2").style.display='block';
The image is still present in the resources tab when I execute the above javascript
When using this method:
<div id="Div1">
<div id="Div1a">
content....
</div>
</div>
<div id="Div2" style="display: none">
content....
</div>
div#Div1a{
background-image: url(images/mybg.png);
background-repeat: no-repeat;
width: 480px;
height: 360px;
}
document.getElementById("Div1").style.display='none';
document.getElementById("Div2").style.display='block';
The image gets removed from the resources tab when I execute the above javascript...but this effect is inconsistent and doesn't always work :s

Setting something to display: none does not remove anything from memory in any browser. The entire DOM element is still in the DOM occupying the same amount of memory, it is just marked hidden from view and layout.
If you want to actually remove an element from memory, then you need to physically remove it from the DOM, usually using parent.removeChild(child) AND make sure that there are no references to the DOM element anywhere in your javascript which would keep it from getting garbage collected.
Also, I don't know how you are assessing memory usage in your browser, but most methods will not accurately detect whether a browser has freed a given image or not because the memory may have been freed from an internal pool of memory (available for reuse), but not returned to the OS. Just releasing an image will not necessarily show a reduction in memory usage by the browser. What does show would be highly browser specific and even OS specific and would certainly depend upon exactly what tools you were using to examine memory usage.

Related

Can I detect the width of a dynamicaly filled div box without rendering it on the web page?

Can I detect the width of a dynamicaly filled div box without rendering it on the web page?
<div>{{some.data.from.some.model}}</div>
If I render it, I know it's width is 260px (in every modern browser).
Can I detect it, before it is rendered on the web page? Are there tools, mechanisms, libraries to do that?
My Imagination is:
That is the div box width this class (margin, padding, whatever)
This is the content (text, font, fontsize, whatever..)
Tell me it's width
Don't show it on the homepage yet, I'll decide afterwards
You can't get the size of an element that doesn't exist (hasn't been rendered). Any solution you find to calculating an element's size without it being rendered is probably not going to be cross-browser.
So, the best you can do is render said element out of view, be it via "visibility: hidden", or pushing it out of view with "display: fixed". Once you have an actual element, you can check it's size for the current browser via JS and proceed accordingly.
I have created a simple fiddle here: http://jsfiddle.net/5wq8o02q/.
HTML
<div id="playground" class="block">
some content
</div>
<span id="width"> </span>
CSS
.block {
/* width: 100px; */
height: 100px;
}
JQUERY:
$(function(){
//$('#playground').css('visibility','hidden');
$('#playground').css('display','none');
$('#width').html($('#playground').css('width'));
});
It helps to use display: none and it won't use screen real estate as visibility: hidden. It still gives the width you are looking for (I think). Let me know me it helps ...

Why does my element move around when the page loads and when javascript executes?

Consider this page: http://www.collegeanswerz.com/adelphi-university/academics/professors/do-professors-explain-things-clearly-are-professors-interesting.
The element in question is "Do they make things easy to understand? Are they interesting?" in the light gray box on the top right. When the page loads, it starts off high up, and then it moves 30px down. The same thing happens when you click "Information" in the navbar.
This is the element: <div id="question_sub" class="well"></div>.
Why does this happen, and how can I fix it?
Answer to Why does it Happen
If you try loading your page without javascript the page looks like
Problem
Your page is very heavily dependent on js for dom elements modification and for styling also.
Solution To avoid this style your page in css as maximum as possible, JS should be used for interaction or making web page attractive.
Probable Problem
If you are loading lots of external script which are not related to page content like discus inside head element
Solution
Move all the external js from head to end of body if you are not doing it, or you can load them asynchronously. Refer Mozilla Synch and Async
Another Way
If you want content to be loaded from server only when some portion of it has changed then use application cache technique with this the pages will be loaded from client machine so only initial page load will take time for the first load and then it will be quite fast
Check Using Application Cache
Other Ways
Compress Javascript and CSS
Use gzip compression
there are lot of more stuff, search it you will find ocean of knowledge, reference
If you want to keep the 50px margin between the elements then change the navbar class to also be 50px
.navbar {
margin-bottom: 50px;
}
Currently it is set at 20px;
Remove this code :-
comments powered by <span class="logo-disqus">Disqus</span>
This is a problem about fusion-margin
Remove this:
#college_pages_css .questions {
margin-top: 30px;
And try this, it will work fine:
#college_pages_css .questions {
margin-top: 0;
If you want a margin, put the margin on div#normal ;)
It looks like you're having a CSS issue due to the floating elements.
try floating the nav on the left:
#normal > nav {
float: left;
}
.disqus { float: right }
and wrap the following elements in a div that is floated to the right, for exemple:
<div class="disqus">
<div id="question_sub" class="well">Do they make things easy to understand? Are they interesting?</div>
<p class="stratify" style="display: block;">tip: talk about the best/worst/average cases</p>
<div id="disqus_thread">
</div>

Scrollbars on overflow div do not appear when content is added to div using Javascript

I have an HTML Document that looks a bit like this, only is far more complex and harder to control:
<body>
<div id="title">This div does not do anything, just stays at the top.</div>
<div id="container">
<div id="navigation">Some navigation</div>
<div id="content">Most of the content</div>
</div>
</body>
Then I have a stylesheet that includes the following:
#container
{
height: auto !important;
overflow: visible !important;
overflow-x: auto;
overflow-y: scroll;
position: relative;
width: auto !important;
}
This all works absolutely perfectly. The title section stays at the top of the page, the container div becomes scrollable if the content is long enough to need to scroll, otherwise it doesn't.
The problem is, that I am then using Javascript to add a whole lot more stuff to the content div. This means that the content div is getting longer than the page after it has loaded and this seems to mean, in IE8 at least, that the scrollbars on the container never get activated, so once the Javascript added content falls off the bottom of the page it becomes inaccessible.
It doesn't help that the minute I start tinkering with the IE developer tools, the scrollbars vanish altogether and I can't make them reappear, so it becomes somewhat hard to test.
I know IE8 has some issues with overflow-y.
You should try with this maybe.
-ms-overflow-y: scroll;
Hope that helps.
Hard to say if this will work without seeing more code, but why not remove the styles from your css and add them with javascript, once the content has loaded.
The solution that has worked was a simple hackaround of resizing the element with JavaScript to match the size it actually is once I have added the extra data to it, like this:
document.all['container'].style.height = document.documentElement.clientHeight+"px";
Of course, this doesn't entirely circumvent the problem- for that we need a new function:
function resizeResults()
{
var resultPanel=document.all["container"];
var topPanel=document.all["title"];
var newHeight= document.documentElement.clientHeight;
newHeight -= topPanel.clientHeight;
resultPanel.style.height=newHeight;
}
Then we can use window.attachEvent("onresize", resizeResults); to ensure that we don't lose the scrollbar or have it otherwise messed around when the user changes the window size.
Just remove the styles you have given for the element to make it scroll before loading ajax content to it.After loading ajax content then add those attributes again.

Is linking a <div> using javascript acceptable?

I want to link an entire <div>, but CSS2 does not support adding an href to a div (or span for that matter). My solution is to use the onClick property to add a link. Is this acceptable for modern browsers?
Example code:
<div class="frommage_box" id="about_frommage" onclick="location.href='#';">
<div class="frommage_textbox" id="ft_1"><p>who is Hawk Design?</p></div>
My test page is at http://www.designbyhawk.com/pixel. Updated daily.
Thanks for the help.
You don't need to do that. There's a perfectly simple and standards-compliant way to do this.
Block-level elements will by default take up the entire available width. a elements are not by default block-level, but you can make them so with display: block in CSS.
See this example (no Javascript!). You can click anywhere in the div to access the link, even though the link text doesn't take up the whole width. You just need to remove that p element and make it an a.
Attaching a click event handler to a <div> element will work for your users with JavaScript enabled.
If you're looking for a progressive enhancement solution, however, you'll want to stick with a <a> element.
It is acceptable, only it's not good for SEO.
Maybe you can make a <a> element act like a div? (settings it's style to display:block etc.)
It will work in every browser(even IE6). The only problem with this is that search engines probably won't fetch it since it's javascript. I see no other way to be able to make an entire div click-able though. Putting an "a" tag around it won't work in all browsers.
If all you're trying to achieve is a large clickable box, try setting the following CSS on an anchor:
a {
display: block;
padding: 10px;
width: 200px;
height: 50px;
}
HTML:
<div class='frommage_box'>
<a href='location.html'>CONTENT GOES HERE</a>
</div>
CSS:
.frommage_box a{
display:block;
height:100%;
}
By default block elements take up 100% width. We adjust the height to 100%. And this will allow spiders to crawl yoru page.

Don't load hidden images

I have a bunch of hidden images on my website. Their container DIVs have style="display: none". Depending on the user's actions, some images may be revealed via javascript. The problem is that all my images are loaded upon opening the page. I would like to put less strain on the server by only loading images that eventually become visible. I was wondering if there was a pure CSS way to do this. Here are two hacky/complicated ways I am currently doing it. As you can see, it's not clean code.
<div id="hiddenDiv">
<img src="spacer.gif" />
</div>
.reveal .img {
background-image: url(flower.png);
}
$('hiddenDiv').addClassName('reveal');
Here is method 2:
<img id="flower" fakeSrc="flower.png" />
function revealImage(id) {
$('id').writeAttribute(
'src',
$('id').readAttribute('fakeSrc')
);
}
revealImage('flower');
The browser will load any images that has a src attribute set, so what you want to do is to use data-src in the markup and use JavaScript to set the src attribute when you want it to load.
<img class="hidden" data-src="url/to/image.jpg" />
I created this tiny plugin that will take care of the problem:
(function($){
// Bind the function to global jQuery object.
$.fn.reveal = function(){
// Arguments is a variable which is available within all functions
// and returns an object which holds the arguments passed.
// It is not really an array, so by calling Array.prototype
// he is actually casting it into an array.
var args = Array.prototype.slice.call(arguments);
// For each elements that matches the selector:
return this.each(function(){
// this is the dom element, so encapsulate the element with jQuery.
var img = $(this),
src = img.data("src");
// If there is a data-src attribute, set the attribute
// src to make load the image and bind an onload event.
src && img.attr("src", src).load(function(){
// Call the first argument passed (like fadeIn, slideIn, default is 'show').
// This piece is like doing img.fadeIn(1000) but in a more dynamic way.
img[args[0]||"show"].apply(img, args.splice(1));
});
});
}
}(jQuery));
Execute .reveal on the image(s) you want to load/show:
$("img.hidden").reveal("fadeIn", 1000);
See test case on jsFiddle.
Here's a jQuery solution:
$(function () {
$("img").not(":visible").each(function () {
$(this).data("src", this.src);
this.src = "";
});
var reveal = function (selector) {
var img = $(selector);
img[0].src = img.data("src");
}
});
It's similar to your solution, except it doesn't use the fakeSrc attribute in the markup. It clears the src attribute to stop it from loading and stores it elsewhere. Once you are ready to show the image, you use the reveal function much like you do in your solution. I apologize if you do not use jQuery, but the process should be transferable to whichever framework (if any) that you use.
Note: This code specifically must be ran before the window has fired the load event but after the DOM has been loaded.
Weirdly, there's no answer about native lazy loading which is implemented in the majority of the browsers already.
you can do it by adding loading="lazy" attribute to your image.
Addy Osmani wrote a great article about it. You can read more about lazy loading here: https://addyosmani.com/blog/lazy-loading/
It partially depends on how your images must be placed in your code. Are you able to display the images as the background of a <div>, or are you required to use the <img> tag? If you need the <img> tag, you may be screwed depending on the browser being used. Some browsers are smart enough to recognize when an image is inside of a hidden object or in an object of 0 width/height and not load it since it's essentially invisible, anyway. For this reason many people will suggest putting an image in a 1x1 pixel <span> if you want the image to be pre-loaded but not visible.
If you don't require the <img> tag, most browsers won't load images referenced by CSS until the element in question becomes visible.
Mind you that short of using AJAX to download the image there's no way to be 100% sure the browser won't pre-load the image anyway. It's not unbelievable that a browser would want to pre-load anything it assumes may be used later in order to "speed up" the average load times.
Using CSS to put the image an unused class, then adding that class to an element with javascript is going to be your best bet. If you don't use image tags at all, this solution becomes a bit more obvious.
Though, for perspective, most people have the opposite problem where they want to preload an image so it shows up instantly when it's told to be shown.
If you are okay relying on scripting, there is the background image method and the image src method. Put simply, set all your hidden images to some very small image (reduce strain on server) or one that does not exist at all (who cares? The visitor cannot see the image-missing [X] anyway, the div is hidden) then change it with script...
<img src="I_do_not_exist.jpg" id="my_image" />
<input type="button" onclick="document.getElementById('my_image').src='I_exist.jpg';" Value="change image" />
<br /><br /><br />
<div id="mydiv" style="width:40px; height:40px; border:2px solid blue"></div>
<input type="button" onclick="document.getElementById('my_div').style.width='455px';document.getElementById('my_div').style.height='75px';document.getElementById('my_div').style.backgroundImage='url(I_exist.jpg)';" Value="change background image" />
I left a width on the above example to show that nothing is in the div image wise until you ask it to load.
If you make the image a background-image of a div in CSS, when that div is set to 'display: none', the image will not load.
You can do the following for a pure CSS solution, it also makes the img box actually behave like an img box in a responsive design setting (that's what the transparent png is for), which is especially useful if your design uses responsive-dynamically-resizing images.
<img style="display: none; height: auto; width:100%; background-image:
url('img/1078x501_1.jpg'); background-size: cover;" class="center-block
visible-lg-block" src="img/400x186_trans.png" alt="pic 1">
The image will only be loaded when the media query tied to visible-lg-block is triggered and display:none is changed to display:block. The transparent png is used to allow the browser to set appropriate height:width ratios for your <img> block (and thus the background-image) in a fluid design (height: auto; width: 100%).
1078/501 = ~2.15 (large screen)
400/186 = ~2.15 (small screen)
So you end up with something like the following, for 3 different viewports:
<img style="display: none; height: auto; width:100%; background-image: url('img/1078x501_1.jpg'); background-size: cover;" class="center-block visible-lg-block" src="img/400x186_trans.png" alt="pic 1">
<img style="display: none; height: auto; width:100%; background-image: url('img/517x240_1.jpg'); background-size: cover;" class="center-block visible-md-block" src="img/400x186_trans.png" alt="pic 1">
<img style="display: none; height: auto; width:100%; background-image: url('img/400x186_1.jpg'); background-size: cover;" class="center-block visible-sm-block" src="img/400x186_trans.png" alt="pic 1">
And only your default media viewport size images load during the initial load, then afterwards, depending on your viewport, images will dynamically load.
And no javascript!

Categories