Off target absolutely positioned elements in IE - javascript

I have a bunch of absolutely positioned elements being generated into a div through javascript.
The positioning of each element differs 2px vertically. IE however adds an extra vertical pixel every 3 elements, then one every 2 elements and then back every 3 elements.
Wait, A pic explains it:
I have coloured the back behaving blocks in red, the correct ones in green.
Chrome renders it correctly (and so does Firefox):
When I use the IE developer tools, I can see that the CSS is set correctly:
I've tried adding zoom:1 to the elements, but that doesn't seem to make a difference.
The code to add the elements is this:
var element = document.createElement("a");
element.style.fontSize = "6pt";
element.style.width = "20px";
element.style.height = "20px";
element.style.position = "absolute";
element.style.backgroundColor = "red";
element.style.zoom = "1";
element.style.display = "block";
var tofs = (columns * 2 + r * 20 - (c * 2));
var lofs = (c * 14 + (r + offset) * 9);
trace(c + "," + r + ": " + lofs + "," + tofs);
element.style.top = tofs + "px";
element.style.left = lofs + "px";
element.style.textIndent = "-10000px";
element.style.overflow = "hidden";
element.innerText = t;
element.selectable = "no";
setBackgroundForSeat(t, element);
target.append(element);
I have tried adjusting the offset every 3 then 2 elements when IE is detected, but that doesn't work: the actual visual difference to the next element becomes 1px instead of the desired 2px (where without the hack it's 3px).
I have run out of ideas. Anybody?
Update: Here's a JS fiddle with the behaviour described. http://jsfiddle.net/uGHDh/5/

I know the IE toolbar is telling you it's setting the CSS correctly, but it might be lying about the actual values. From your code it looks like you will be getting floating point values, and it seems like IE is producing rounding errors when it draws out the objects.
You could try casting the pixel values to an integar before using them, but that might product unwanted results in all the browsers.

Related

Problem with the '.style.transform=' in JS

I have this SVG header that, on screen scroll, its parts move differently. For this, I am using a script like the following:
let menu = document.getElementById('main-menu');
let lua = document.getElementById('lua');
window.addEventListener('scroll', function(){
let value = window.scrollY;
menu.style.marginTop = value * 0.45 + 'px'; // working just fine
lua.style.transform = "translateY(" + value * 0.25 + ")"; // don't know how to make this work
OBS: I need to use the transform: translate because this SVG element, for some reason, can't be moved with margin or top/left, only translate.
The menu.style work just fine, but on the lua.style case I'm struggling cause I don't know how to write on the JS a CSS such as transform: translateY that merges a child property (translate) inside another property (transform).
I've tried to write the lua.style.transform = "translateY(" + value * 0.25 + ")"; in many different ways, like:
lua.style.transform = value + "translateY(" * 0.25 + ")";
// or
lua.style.translate = value * 0.45 + 'px';
// or
lua.style.translate = value * 0.45;
// or
lua.style.translate = (0,value * 0.45);
but still can't make it work. How can I write it correctly?
DONE! I used the template literal that Dane Landry explained in the comments. Thanks man.
The code:
lua.style.transform = ` translateY(${value * 0.25}px ) `;
And also thanks kmoser for reminding me translate demans a unit of measurement. It does.

Using OpenLayers ZoomBox in JavaFX WebView

I am using JavaFX WebView included in jdk-8u45 to open a web page which shows a map using OpenLayers 2.13.1. I'm trying to zoom in on the map using a ZoomBox with a BoxHandler. The zooming works like it should, but the problem is how the the rectangle is drawn.
The wanted result is that once I click on the map and start dragging, the rectangle should start drawing as I move the mouse. This works fine in all browsers, except inside my WebView. What happens is that only after I have moved my mouse a few cm in both x- and y-direction (e.g. diagonally), the rectangle starts drawing from this position (not the one where I started dragging). I have looked at the coordinates from the different mouse events, and they all seem to be correct, which is confirmed by the fact that it zooms in on the area I actually dragged over (e.g. not the area that is drawn).
JavaScript console.log stmts output coordinates from the moment I click on the map, but nothing is drawn in the beginning of the drag.
Has anyone had similar problems with WebView? As I said, the code works like a charm in all other browsers I have tried (Safari, Firefox, Chrome, IE). I have looked around on the internet, but I haven't been able to find an answer to my problem.
Code taken from BoxHandler.js:
startBox: function (xy) {
;;;console.log(xy);
;;;console.log("startbox xy=" + xy.x + "," + xy.y);
if(this.zoomBox){
this.removeBox();
}
this.zoomBox = OpenLayers.Util.createDiv('zoomBox',
this.dragHandler.start);
this.zoomBox.className = this.boxDivClassName;
this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1;
this.map.viewPortDiv.appendChild(this.zoomBox);
OpenLayers.Element.addClass(
this.map.viewPortDiv, "olDrawBox"
);
},
/**
* Method: moveBox
*/
moveBox: function (xy) {
var startX = this.dragHandler.start.x;
var startY = this.dragHandler.start.y;
;;;console.log("dragHandler.start.x=" + this.dragHandler.start.x);
;;;console.log("dragHandler.start.y=" + this.dragHandler.start.y);
var deltaX = Math.abs(startX - xy.x);
var deltaY = Math.abs(startY - xy.y);
this.zoomBox.style.width = Math.max(1, deltaX) + "px";
this.zoomBox.style.height = Math.max(1, deltaY) + "px";
this.zoomBox.style.left = xy.x < startX ? xy.x+"px" : startX+"px";
this.zoomBox.style.top = xy.y < startY ? xy.y+"px" : startY+"px";
console.log("zoombox width=" + this.zoomBox.style.width);
console.log("zoombox height=" + this.zoomBox.style.height);
console.log("zoombox left=" + this.zoomBox.style.left);
console.log("zoombox top=" + this.zoomBox.style.top);
// depending on the box model, modify width and height to take borders
// of the box into account
var box = this.getBoxCharacteristics();
;;;console.log("movebox xOffset=" + box.xOffset);
;;;console.log("movebox yOffset=" + box.yOffset);
if (box.newBoxModel) {
if (xy.x > startX) {
this.zoomBox.style.width =
Math.max(1, deltaX - box.xOffset) + "px";
}
if (xy.y > startY) {
this.zoomBox.style.height =
Math.max(1, deltaY - box.yOffset) + "px";
}
}
},
/**
* Method: endBox
*/
endBox: function(end) {
var result;
console.log(this.map.viewPortDiv.lastElementChild.style);
if (Math.abs(this.dragHandler.start.x - end.x) > 5 ||
Math.abs(this.dragHandler.start.y - end.y) > 5) {
var start = this.dragHandler.start;
var top = Math.min(start.y, end.y);
var bottom = Math.max(start.y, end.y);
var left = Math.min(start.x, end.x);
var right = Math.max(start.x, end.x);
result = new OpenLayers.Bounds(left, bottom, right, top);
} else {
result = this.dragHandler.start.clone(); // i.e. OL.Pixel
}
this.removeBox();
this.callback("done", [result]);
}
Also, I don't know if this is relevant, but when I inspect the HTML div element that holds the map (using Firebug Lite) it looks like the top border of the div is further down than it should be. The map (in correct position on the webpage) is extending beyond the top border. This is different behavior than in the other browsers I mentioned.
Any help would be appreciated.

Image slider is choppy

I have put together a plain javascript/css image slider, started out as just a learning exercise but am now looking to apply it in the real world. The problem is that the animation is choppy on my desktop (which is a v. high spec gaming rig) - and even worse on a mobile (to the degree it's not really an animation anymore)
You can see it in action here:
www.chrishowie.co.uk/sands/
jsfiddle isolates much of the pertinent code - it's not a "this doesn't work" issue, so hopefully the fiddle gives enough to help optimize it.
http://jsfiddle.net/9aozrxy8/5/
In summary: I have a DIV with 4 images in a row, each image is 100% the width of the page. I use javascript to translateX (I have tried translate3d as heard this uses GPU, but didnt make much diff) and I set CSS transitions to ease-in the transform.
I also thought that potentially I am just trying to do too much on this site - but then I look at some other sites doing a heck of a lot more and it's smooth as silk. So I guess I'm missing something.
function slideRight() {
if (sliding) {
return false
};
window.sliding = true;
el = document.getElementById("slider");
cst = getComputedStyle(el);
transformst = cst.transform || cst.webkitTransform || cst.mozTransform;
widthst = cst.width;
widthst = widthst.replace("px", ""); // computed width of slider (7680px)
slidewidth = widthst / 4;
transformst = transformst.replace("matrix(", "");
transformst = transformst.replace(")", "");
transformst = transformst.split(",");
transformst = transformst[4]; // returns current transform in px without unit (px)
if (!transformst) {
transformst = 0;
}
var activebtn = "sldr" + Math.round((Number(transformst) / (-1 * slidewidth)));
document.getElementById(activebtn).classList.remove("sliderbuttonactive");
if (activebtn != "sldr3") {
document.getElementById("slider" + Math.round((2 + Number(transformst) / (-1 * slidewidth)))).style.visibility = "visible";
document.getElementById("slider" + Math.round((2 + Number(transformst) / (-1 * slidewidth)))).style.display = "initial";
document.getElementById("slider").style.transform = "translate3d(" + 25 * ((Number(transformst) / (slidewidth)) - 1) + "%, 0, 0)";
document.getElementById("slider").style.transform = "-webkit-translate3d(" + 25 * ((Number(transformst) / (slidewidth)) - 1) + "%, 0, 0)";
document.getElementById("slider").style.transform = "-moz-translate3d(" + 25 * ((Number(transformst) / (slidewidth)) - 1) + "%, 0, 0)";
document.getElementById("slider").style.transform = "-ms-translate3d(" + 25 * ((Number(transformst) / (slidewidth)) - 1) + "%, 0, 0)";
document.getElementById("leftslidebtn").style.visibility = "visible";
document.getElementById("leftslidebtn").style.display = "block";
}
activebtn = activebtn.replace("sldr", "");
activebtn = "sldr" + (1 + Number(activebtn));
document.getElementById(activebtn).classList.add("sliderbuttonactive");
if (Number(activebtn.replace("sldr", "")) == 3) {
document.getElementById("rightslidebtn").style.visibility = "hidden";
document.getElementById("rightslidebtn").style.display = "none";
}
setTimeout(function () {
window.sliding = false
}, 2000);
}
update: still not resolved but on mobile I have made it usable by reducing the image size for small screens and also not displaying images that are off-screen. Not perfectly smooth but getting there.
Thanks a lot,
C
Like Jeremy mentioned, that the "transition" in your JSFiddle caused the problem, it's also causing it on your website.
In your "Main.css" in line 221. Remove the "transition: top ease 2s;" from class .slide
Everything works fine then on Win8.1/Google Chrome/i7

Centering via offset math doesn't work in non-webkit browsers

The code: http://jsfiddle.net/LPF85/6/
In FF, IE7, and IE9 (the only browsers I've tested that don't run WebKit), it seems that the left attribute is either always set to 0, or, in IE's case, negative.
My positioning code is all based off the dimensions of the document.
function open_img_in_face_box(id, width){
max_width = $j(document).width();
max_height = $j(document).height();
padding = 150;
passed_width = width || (max_width - (2 * padding));
var img = $j('#' + id);
dom_img = document.getElementById(id);
$j(document).bind('reveal.facebox', function() {
$j("#facebox .image img").width(passed_width);
})
// display
jQuery.facebox({
image: img.attr('src')
});
// center and adjust size
var aspect_ratio = img.width() / img.height();
var img_width = passed_width;
var img_height = passed_width / aspect_ratio;
window_center_y = max_height / 2;
window_center_x = max_width / 2;
offset_y = window_center_y - (img_height / 2);
offset_x = window_center_x - (img_width / 2);
var fbx = $j('#facebox');
fbx.css('position', 'absolute');
fbx.css('left', offset_x + 'px !important');
fbx.css('top', offset_y + 'px !important');
fbx.css('margin-left', 'auto');
fbx.css('margin-right', 'auto');
}
margin-left and margin-right don't appear to do anything here, which I'm fine with, because the left math should work across all browsers, right? (It is just math)
The goal of the facebox / lightbox, is to be centered both horizontally and vertically.
Why would you even programatically calculate the position in the first place? What if the user resizes the page? This can easily be done in pure CSS.
I don't really understand your jsFiddle (or am I not seeing the same thing?) so I'll just give you this script: http://jsfiddle.net/minitech/8U4Ke/ that can be modified however you like. It's commented. ;)
Now it's easy to hide and show - to hide, fade out .overlay. To show, fade it in. To change the contents, replace the HTML in .popup. Add close boxes and whatnot liberally.

Multiple translateX in Javascript (Webkit)

If I apply a .style.webkitTransform = 'translateX(10px)'; on an element and then I would like to add another .style.webkitTransform = 'translateX(10px)'; to reach a total of 20px is impossible.
The element will again be 10px.
How can I go around this?
(Except keeping the previous values and adding it to translateX like = preValue+current+'px';)
You've already figured out out the answer.
var pixels = parseFloat(element.style.webkitTransform.split(/[()]/)[1]);
pixels += 10;
element.style.webkitTransform = 'translateX(' + pixels + 'px)';

Categories

Resources