Liquid Layout IE Problems, of course (Newbie) - javascript

I'm new to CSS, never created a layout before and I'm having some issues with my first one in Internet Explorer. I think it looks good in Firefox though.
I have done a lot of reading about HTML and CSS before starting the layout so I knew IE had some bugs but even after making the layout and researching the issues none of the resolutions seem to be working. Im hoping someone here can help.
TL;DR: New layout not working in IE, need help(did research)
Problem 1: In IE the 2 right sidebars are too wide compared to Firefox. Everything else appears normal, just those 2 are too wide which is affecting the layout
Problem 2: When the window width is below 1024 it is supposed to switch from container1.css to container2.css effectively changing the container properties to better display in smaller resolutions. Works great in Firefox, but in IE it seems to remove the container period leaving the contents to flow throughout the entire window.
<HTML>
<HEAD>
<TITLE>My Liquid Layout</TITLE>
<link rel="stylesheet" type="text/css" href="LiquidLayout.css" />
<link id="container1" rel="stylesheet" type="text/css" href="container1.css" />
<link id="container2" rel="alternate" type="text/css" href="container2.css" />
<script type="text/javascript">
<!--
var css = "container1";
function changeStyle(styleSheet)
{
if(styleSheet == css)
return;
var selected = document.getElementById(styleSheet);
var current = document.getElementById(css);
if(!selected)
{
selected = current.cloneNode(true);
selected.id=styleSheet;
selected.setAttribute("href",current.getAttribute("href").replace(new
RegExp(css),styleSheet));
}
current.setAttribute("rel","stylesheet1");
selected.setAttribute("rel","stylesheet");
document.getElementsByTagName('head')[0].appendChild(selected);
css = styleSheet;
}
function windowSize()
{
var windowWidth;
var windowHeight;
windowWidth = window.innerWidth;
windowHeight = window.innerHeight;
if (document.body && document.body.offsetWidth)
{
windowWidth = document.body.offsetWidth;
windowHeight = document.body.offsetHeight;
}
if (document.compatMode=='CSS1Compat' &&
document.documentElement &&
document.documentElement.offsetWidth )
{
windowWidth = document.documentElement.offsetWidth;
windowHeight = document.documentElement.offsetHeight;
}
if (window.innerWidth && window.innerHeight)
{
windowWidth = window.innerWidth;
windowHeight= window.innerHeight;
}
if(windowWidth < 1024)
changeStyle('container2');
else if(windowWidth >= 1024)
changeStyle('container1');
}
window.onresize = new Function("windowSize()");
//-->
</script>
</HEAD>
<BODY>
<div id = "container">
<div id = "header"><p id = "size"></p></div>
<div id = "content">
<div id = "menu">
<ul>
<li>About</li>
<li>Contact</li>
<li>Home</li>
<li>Video</li>
<li>Gallery</li>
<li>IGN</li>
</ul>
</div>
<div id = "sidebox"></div>
<div class = "column" id = "sidebar"></div>
<div class = "column" id = "main"></div>
</div>
<div id = "footer"></div>
</div>
</BODY>
</HTML>
The main CSS is:
body
{
background-color:gray;
margin: 0px;
text-align: center;
}
#header
{
width: 100%;
height: 200px;
background-color: yellow;
}
#content
{
padding-top:5px;
padding-bottom:0px;
padding-right:5px;
padding-left:5px;
min-height: 768px;
}
#menu
{
width: 66%;
height: 250px;
background-color: blue;
float: left;
}
#sidebox
{
width: 34%;
height: 250px;
background-color: red;
float: right;
display: inline;
}
#sidebar
{
width: 34%;
background-color: red;
height: 100%;
float: right;
}
#main
{
width: 65%;
height: 100%;
background-color: green;
float: left;
}
If anyone can please offer some advice on fixing these issues in IE I would appreciate it!
Any suggestions for improvement are welcome as well

You didn't specify which version of IE, so I'm guessing you've only checked the most recent version?
Add a doctype as suggested, and you should be ok in IE9, but if you're supporting other versions of IE as well you are going to want some way of targeting each version independently as they all have different and progressively worse bugs. Occasionally, something will work in IE7 but not IE8, but generally as you head towards IE6 your problems will multiply exponentially, especially with a liquid layout.
I'd recommend using Modernizr, which will add different class names to the HTML element depending on the version of IE in use. It also does a bunch of other stuff like making HTML5 elements styleable in older IE as well, so it is worth using, even without any of the other feature tests it offers. I can see you aren't using any HTML5 elements, but I don't know if that's your whole layout, or just the beginnings of it...
You'll probably also want to use Selectivizr so that most useful CSS3 features can be used in IE8 and below as well, although you need to use a JS library, such as jQuery for this, so it may or may not be useful. There isn't any CSS3 in your CSS, but again, your example could be much simplified
In terms of improvements to your code, you don't need to include HTML comments in your script tags <!-- and haven't since the days of like IE4 or something. Additionally, your should go at the bottom of the <body> (just before the closing </body>) for performance reasons, rather than in the <head>, and if you use the HTML5 doctype (which you can still use even if you aren't planning on using any HTML5 elements) you don't need to specify a type attribute on the <script> element. In JavaScript, the opening curly brackets should go on the same line as the function definition or conditional, so do:
if (condition) {
or:
function something() {
and not:
if (condition)
{
or:
function something()
{
This is usually ok most of the time, but it can produce bugs that are very hard to spot, so it is worth getting into the habit of doing it all the time. And when attaching an event listener, you don't need to specify new Function("function_name"), you can just attach the function directly:
window.onresize = windowSize();
Also, in CSS, zero values do not need to specify measurement units, so you can just have 0 instead of 0px...

If you have copy and pasted the entirity then your missing a doctype making IE render in quirksmode.
I would suggest adding the HTML5 doctype to the top of your document <!DOCTYPE html>
More information on quirks mode can be found here

Related

How can I figure out what size an HTML Element will be? (tween size as element added)

I'm pretty sure this is currently infeasable.
I have an animation that involves an element moving from an absolute position to an inline one. For reasons, I can not know how the container is sized, nor how the element I'm animating is sized.
What I need to know is what the size of the HTML Element will be after the transformation, without any jittery drawing.
This makes the problem very difficult (likely undoable) because I have no way to know if adding the element will resize the parent, or resize the element itself.
What I need is a means of looking into the future.
const byId = (id) => document.getElementById(id);
#container {
height: 3em;
min-width: 50%;
background: teal;
}
#mystery {
background: purple;
}
<div id="container">
<div id="mystery">Some Text</div>
</div>
<button onClick='byId("mystery").style.position = "relative"'>Position Relative</button>
<button onClick='byId("mystery").style.position = "absolute"'>Position Absolute</button>
Currently, these are the only solutions I can imagine (they're all absurd):
Clone the entire webpage HTML, make the clone have opacity: 0; pointer-events: none and render what the future will be secretly.
Capture the paint data of the current page (basically screenshot), overlay that while secretly modifying the page, get my future, revert, and remove the screenshot overlay.
Similar to number 2, is there a way to ❄️freeze❄️ rendering of a page for 3-4 frames?
I remember seeing a "sizing worker" something-or-rather a long time ago. Couldn't find any information on it now, but it seems like it might be useful?
You can simply change the property, measure the sizes you want and then change the property back. JS is fast enough to do it all between renderings, as long as you keep it all in the same thread. Have you tried that at all?
Asker Edit:
Here's the code to prove it works.
function byId(id){ return document.getElementById(id); }
const tweenyEl = byId("tweeny");
function appendTweeny() {
tweenyEl.style.opacity = "1";
const startingWidth = tweenyEl.clientWidth + "px"
tweenyEl.style.position = "relative";
const targetWidth = tweenyEl.clientWidth + "px";
console.log(startingWidth, targetWidth);
tweenyEl.style.width = startingWidth;
requestAnimationFrame(() =>
requestAnimationFrame(() =>
tweenyEl.style.width = targetWidth
)
);
}
function resetTweeny() {
tweenyEl.style.position = "";
tweenyEl.style.width = "";
tweenyEl.style.opacity = "0.1";
}
#container {
display: inline-block;
height: 3em;
min-width: 150px;
background: teal;
}
#tweeny {
font-family: arial;
color: white;
position: absolute;
background: purple;
transition: all 0.5s ease;
opacity: 0.1;
}
<div id="container">
<div id="tweeny">I'm Tweeny</div>
</div>
<br>
<button onClick='appendTweeny()'>Append Tweeny</button>
<button onClick='resetTweeny()'>Reset Tweeny</button>
I would suggest cloning the page into an iframe and then positioning the iframe off the screen.
<iframe style="width:100vw;height:100vh;left:-101vw;positionabsolute"><iframe>
Also bear in mind that the user can zoom in-and-out at will! Different browsers might render the same thing in different ways. You really don't know how big an element will be until it does so.
I don't know if you can get anywhere by specifying display: none; ... whether or not the browser would bother to make these calculations for an object that isn't visible.
You can clone on the fly an element with same transformation with delay 0 and then calculate it's width and height, then do what you want with your actual element it's still animating

Tag object being changed dynamically by displaying html from a code editor

Hello stackoverflow community, I have a question regarding the use of the <object> html tag. Below is a description of what I want to do:
I am using the summernote editor, however I would like every change within the editor to be presented to the user as the html page will be. I am currently using the following code:
$('#summernote').summernote({
placeholder: 'Hello bootstrap 4',
tabsize: 2,
height: 300,
lang: 'pt-BR'
});
$("#summernote").on("summernote.change", function(e) { // callback as jquery custom event
console.log('it is changed');
myFunction();
});
var i = 0;
var dragging = false;
$('#dragbar').mousedown(function(e) {
e.preventDefault();
dragging = true;
var main = $('#main');
var ghostbar = $('<div>', {
id: 'ghostbar',
css: {
height: main.outerHeight(),
top: main.offset().top,
left: main.offset().left
}
}).appendTo('body');
$(document).mousemove(function(e) {
ghostbar.css("left", e.pageX + 2);
});
});
$(document).mouseup(function(e) {
if (dragging) {
var percentage = (e.pageX / window.innerWidth) * 100;
var mainPercentage = 100 - percentage;
$('#console').text("side:" + percentage + " main:" + mainPercentage);
$('#sidebar').css("width", percentage + "%");
$('#main').css("width", mainPercentage + "%");
$('#ghostbar').remove();
$(document).unbind('mousemove');
dragging = false;
}
});
function myFunction(data) {
var text = $('#summernote').summernote('code');
document.getElementById("demo").innerHTML = "<!DOCTYPE html><html><meta charset='UTF-8'>" + text + "</html>";
console.log(document.getElementById("demo"));
console.log(text);
}
.clearfix:after {
content: '';
display: table;
clear: both;
}
#main {
float: right;
width: 50%;
}
#sidebar {
width: 50%;
float: left;
overflow-y: hidden;
}
#dragbar {
/*background-color: #a9a9a9;*/
background: transparent;
height: 100%;
float: right;
width: 3px;
cursor: col-resize;
}
#ghostbar {
width: 3px;
background-color: #a9a9a9;
opacity: 0.5;
position: absolute;
cursor: col-resize;
z-index: 999
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Summernote Editor</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.9/summernote-bs4.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.9/summernote-bs4.js"></script>
<script src="summernote-pt-BR.js"></script>
</head>
<body>
<div class="container">
<div class="row">
<!--<div id="summernote"></div>-->
<div id="sidebar" class="col">
<span id="position"></span>
<div id="dragbar">
</div>
sidebar
<form method="post">
<textarea id="summernote" name="editordata"></textarea>
<button type="submit" class="btn btn-primary">Salvar</button>
</form>
</div>
<div id="main">main
<p id="demo"></p>
</div>
</div>
</div>
</body>
</html>
But instead of using the <p> tag along with innerHtml, I'd like to use the <object> tag, and its contents being changed daily.
If you have other better solutions, feel free to make suggestions.
Note: I have already tried using the tag but somehow using this tag hinders the resize that I need to perform between the editor and html viewer.
Note 2: I'm a beginner, and my English is not good. So sorry if something went wrong without making sense. I used Google translate to explain the issue.
Hi Rafael — thanks for clarifying.
The reason your code looks different in the iframe or object tags is due to the differing CSS. When you use an iframe and set the source dynamically, the CSS comes from the User Agent Stylesheet. The tag does not inherit the parent's styles. Currently, your CSS in the p tag is from Bootstrap 4.
Option 1: You could customize the CSS on this element to make it appear consistent in a non-Bootstrap context.
Option 2: If you still want to change tags, I think you are better off using an iframe instead of an object tag, per the MDN docs and the discussion on this SO thread.
Change <p id="demo"></p> to <iframe id="demo"></iframe>, and your myFunction to:
function myFunction(data) {
var text = $('#summernote').summernote('code');
var frame=document.getElementById("demo");
frame.srcdoc="<!DOCTYPE html><html><meta charset='UTF-8'>" + text + "</html>";
}
If you support IE11, Edge, and Opera Mini (srcdoc is not supported there) you can use a polyfill.
One final consideration with this route is performance — I couldn't find much on this, but I suspect that setting the innerHTML of your p tag is far less expensive than re-rendering an iframe. You might want to investigate and consider reducing the update interval if this becomes a problem.

Scroll then fix to top header in html

So, i'd like to have an header working similarly to the one here http://www.blackmesasource.com/ , the only problem being I know nothing about javascript and jquery, can anyone help me?
Nice - I just knocked this up for you - it's rough and has had no cross-browser testing:
<style type="text/css">
body {
padding:0;
margin:0;
}
#hero {
background-color:#eee;
}
nav {
position:absolute;
bottom:0;
left:0;
background-color:#ccc;
box-sizing:border-box;
width:100%;
padding:20px;
}
nav.fixed-position {
position:fixed;
top:0;
bottom:initial;
}
</style>
<body>
<div>
<div id="hero">
<nav id="nav-menu">
Your nav here
</nav>
</div>
<section style="height:2000px;">
content
</section>
</div>
<script type="text/javascript">
var hero = document.getElementById('hero'),
nav = document.getElementById("nav-menu"),
viewportHeight = Math.max(window.innerHeight || 0),
navOffsetTop = nav.offsetTop;
hero.style.height = viewportHeight + 'px';
var hasScrolled = function() {
var fromTop = document.body.scrollTop || document.documentElement.scrollTop || 0;
if (navOffsetTop < fromTop) {
nav.classList.add('fixed-position');
} else {
nav.classList.remove('fixed-position');
}
}
window.addEventListener('scroll', hasScrolled);
</script>
</body>
You can drop this into an empty file and run it in your browser to see the result - I tested it in Firefox with no problems but as I say, it will need additional work; such as:
Crossbrowser - depending on what level of IE support you plan to have, classList might not work.
Optimisation - currently the hasScrolled function fires every time the user scrolls, you might want to find a way to limit that.
Global vars - I've made no attempt to use a nice clean namespace for the JS, something else you might like to look into.
Additionally, this doesn't require jQuery, but given what I've just suggested you need to do you might want to look into using it - it's mainly crossbrowser which will help you out alot if you don't really know JS.
You can see best resources here. Just follow same structure https://css-tricks.com/scroll-fix-content/

Javascript swap divs not working in IE 9 or less

I am trying to swap divs in IE 9 and less. But my javascript is not working. Can anybody help me out?
You can see my script here: http://jsfiddle.net/pny71Lqd/
Not sure why the JS is also not working on jsfiddle. It is working in my browsers (also IE), but when i try IE 9 or smaller it brakes down.
Find the code below:
<style>
body{ background:#f6f6f6;}
#container2 {
width: 926px;
}
#leftCol2{ float: left;
width: 300px;
background:#FFFFFF;
}
#rightCol2{float:left;
width:300px;
background: #FF9;
}
</style>
<script type='text/javascript' src='//code.jquery.com/jquery-1.9.1.js'></script>
<script type='text/javascript'>//<![CDATA[
$(function(){
$(window).resize(function() { //Fires when window is resized
var width = (window.innerWidth > 0) ? window.innerWidth : screen.width;
if(width < 1024) {
$("#container2").each(function() {
var detach = $(this).find("#leftCol2").detach();
$(detach).insertAfter($(this).find("#rightCol2"));
})
}
else {
$("#container2").each(function() {
var detach = $(this).find("#rightCol2").detach();
$(detach).insertAfter($(this).find("#leftCol2"));
})
}
});
});//]]>
</script>
</head>
<body>
<div id="container2">
<div id="leftCol2">
<p>Div 1.</p>
</div>
<div id="rightCol2">
<p>Div 2.</p>
</div>
</div>
As you can see I try to swap around leftCol2 with rightCol2 when the screen is resized smaller than 1024. Actually I'd like also the divs to be swapped around when the page is just loaded (and not necessarily resized). Who can help? Thank you very much!
Seemed to be a problem with my emulator. Got a different one and it worked for IE9 and less!

Controlling image height in Bootstrap-Lightbox gallery

I'm working on a website of an artist, so galleries are really important. I'm using Bootstrap for the website, and Lightbox for Bootstrap plugin for the galleries. It works fine adjusting the width of the image to any resolution (I want to make it as responsive as possible). But, as you can observe if you click on any vertical photo (for example, the one in the second row, second column), when it opens, it's bigger than the screen and it can't be seen without scrolling.
So, I want to get rid of this problem, adjusting the maximum height of the image to the height of the screen. But I can't find the way to do this. Any ideas for doing it in a simple way? I've uploaded the website to a server so you can see the problem: http://mural.uv.es/ivape2/es/galeria.html
Thank you.
I had a similar problem and tinny77's answer was the only thing that approached a solution.
Here is a working snippet of what I ended up with
$().ready(function() {
$('[data-toggle="lightbox"]').click(function(event) {
event.preventDefault();
$(this).ekkoLightbox({
type: 'image',
onContentLoaded: function() {
var container = $('.ekko-lightbox-container');
var image = container.find('img');
var windowHeight = $(window).height();
if(image.height() + 200 > windowHeight) {
image.css('height', windowHeight - 150);
var dialog = container.parents('.modal-dialog');
var padding = parseInt(dialog.find('.modal-body').css('padding'));
dialog.css('max-width', image.width() + padding * 2 + 2);
}
}
});
});
});
<html>
<head>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js" type="text/javascript"></script>
<script class="cssdeck" src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/ekko-lightbox/3.3.0/ekko-lightbox.min.js"></script>
</head>
<body>
<p>Click Image</p>
<a href="http://lorempixel.com/400/1920" data-toggle="lightbox">
<img height="200" src="http://lorempixel.com/400/1920"/>
</a>
</body>
</html>
I solved it this way by editing the Javascript:
onContentLoaded: function() {
var imgh = $(".ekko-lightbox-container").find("img").height();
var winh = $(window).height();
if ((imgh+200)>winh)
{
$(".ekko-lightbox-container").find("img").css("height",winh-150).css("width","auto").css("margin","0 auto");
}
}
See the JSFiddle
.container {
height:100%;
width: 100%;
border: 1px solid #000000;
}
.item {
max-height: 90%;
max-width: 90%;
border: 1px solid #000000;
}
Assuming you have a .container width a given width/height. I've put both width and height at 100% for the .container
Then you just create a class and asign it max-width: 80%; which will output the image to be 80% the width of the .container
Try adding this
.ekko-lightbox.modal.fade.in div.modal-dialog{
max-width:27%;
}
This is just simple solution, best it will be to make media-queries for different resolution
This has been solved (commit on github) by calculating the maximum image height (80% of viewport height) in the preload function but currently it is not part of the base branch.

Categories