height not matching in Chrome - javascript

I'm working through the Single Page Web Applications book and the first example in it isn't working properly in Chrome, but does work in Firefox. The essential code is the following:
.spa-slider {
position: absolute;
bottom: 0;
right: 2px;
width: 300px;
height: 16px;
cursor: pointer;
border-radius: 8px 0 0 0;
background-color: #f00;
}
The JavaScript code is the following:
var spa = (function($) {
var configMap = {
extended_height: 434,
extended_title: 'Click to retract',
retracted_height: 16,
retracted_title: 'Click to extend',
template_html: '<div class="spa-slider"></div>'
},
$chatSlider, toggleSlider, onClickSlider, initModule;
toggleSlider = function() {
var slider_height = $chatSlider.height();
console.log("slide_height: " + slider_height);
if (slider_height == configMap.retracted_height) {
$chatSlider.animate({height: configMap.extended_height})
.attr('title', configMap.extended_title);
return true;
}
if (slider_height == configMap.extended_height) {
$chatSlider.animate({height: configMap.retracted_height})
.attr('title', configMap.retracted_title);
return true;
}
return false;
};
onClickSlider = function(event) {
toggleSlider();
return false;
};
initModule = function($container) {
$container.html(configMap.template_html);
$chatSlider = $container.find('.spa-slider');
$chatSlider.attr('title', configMap.retracted_title)
.click(onClickSlider);
return true;
};
return {initModule: initModule};
}(jQuery));
jQuery(document).ready(function() {
spa.initModule(jQuery('#spa'));
});
My question is essentially the following. The slider doesn't seem to work on Chrome, because console.log("slide_height: " + slider_height); prints 17, so it matches neither of the if guards. On Firefox it prints 16, so the height() property gets the correct value. Can anyone explain why this happens and what is a portable way to write the code?
UPDATE: I use 90% zoom on Chrome and changing it to 100% seems to make the code work correctly. However, the code should clearly work on all zoom levels, so how can this be accomplished? I'm surprised that the book uses code that is so brittle.

Related

A compatible way to show users a browser warning

There are countless questions about this but the answers to all of them are out of date with IE no longer supporting conditional statements, jQuery no longer supporting detection without a migrate plugin etc. This question has been asked before but there are no answers that remain supported in 2020.
The tag is a perfect example of how simple this should be. Surely there must be a way to detect the browser (IE) and then set a DIV with a warning message to visible.
There have been answers in the past but even they aren't supported now. Of course any JS used to detect the browser would need to be compatible with IE.
My first thought was to do something that would detect MSIE and then display a DIV. It seems up for debate as to if you should use feature or browser detection based on everything I've looked through for the last few hours.
The reason I need this message in IE is because the site isn't compatible due to new JS and CSS features. I wouldn't know where to start with this so apologies for not posting any code. All it needs is something like this.
// Detect if Internet Explorer
// If no do nothing
// If Internet Explorer
// Set iewarning to visible
.iewarning {
display: none;
}
<div class="iewarning">Update your browser</div>
I don't know how to go about detecting features, the browser or user agent but this question has to be asked again now that there's no conditional statements or jQuery support. Pure JS is the most ideal solution. Any approaches using that would be appreciated. Thanks in advance.
EDIT
If feature detection could be used to make a DIV visible.
if (typeof Promise == "undefined") {
document.getElementByClass("iewarning").style.display = "block";
}
.iewarning {
display: none;
}
<div class="iewarning">Please upgrade your browser</div>
That doesn't work though but seems like it could be a more minimal solution.
EDIT
Using a query selector instead should work? I'm entirely lost but willing to use feature detection if someone can help me get it working.
if (typeof Promise == "undefined") {
document.querySelector("div.iewarning").style.display = "block";
}
.iewarning {
display: none;
}
<div class="iewarning">Please upgrade your browser</div>
OK based on your comments so far here is the most simplfied browser detection approach I could devise using a div in the HTML as you requested.
function isUnsupported (browser) {
return (browser.name === "MSIE" || browser.name === "IE")
}
var isUnsupported = this.isUnsupported(this.get_browser());
// Uncomment to simulate being in an IE browser.
//var isUnsupported = true;
this.listen("load", window, function() {
if (isUnsupported) {
var warning = document.querySelector(".iewarning");
warning.style.display = 'block';
}
});
function listen(evnt, elem, func) {
if (elem.addEventListener) // W3C DOM
elem.addEventListener(evnt,func,false);
else if (elem.attachEvent) { // IE DOM
var r = elem.attachEvent("on"+evnt, func);
return r;
}
else window.alert('Error: unsupported browser!');
}
function get_browser() {
var ua = navigator.userAgent, tem, M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
if (/trident/i.test(M[1])) {
tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
return { name: 'IE', version: (tem[1] || '') };
}
if (M[1] === 'Chrome') {
tem = ua.match(/\bOPR\/(\d+)/)
if (tem != null) { return { name: 'Opera', version: tem[1] }; }
}
if (window.navigator.userAgent.indexOf("Edge") > -1) {
tem = ua.match(/\Edge\/(\d+)/)
if (tem != null) { return { name: 'Edge', version: tem[1] }; }
}
M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
if ((tem = ua.match(/version\/(\d+)/i)) != null) { M.splice(1, 1, tem[1]); }
return {
name: M[0],
version: +M[1]
};
}
.iewarning {
display: none;
}
<div>Welcome to the Website👋</div>
<div class="iewarning">IE not supported. Please upgrade your browser.</div>
There are countless questions about this but the answers to all of them are out of date with IE no longer supporting conditional statements, jQuery no longer supporting detection without a migrate plugin etc.
They're not out of date, since those features are still no longer supported, and nothing new has arrived to replace them.
This question has been asked before but there are no answers that remain supported in 2020.
There's a reason for that.
The tag is a perfect example of how simple this should be. Surely there must be a way to detect the browser (IE) and then set a DIV with a warning message to visible.
There are ways, but they have varying degree of reliability, and none match what conditional comments provided.
There have been answers in the past but even they aren't supported now.
That's basically your answer right there.
Of course any JS used to detect the browser would need to be compatible with IE.
Would it? If it's not compatible, wouldn't that give you an indicator that the browser doesn't support the features you want to provide?
My first thought was to do something that would detect MSIE and then display a DIV. It seems up for debate as to if you should use feature or browser detection based on everything I've looked through for the last few hours.
Yes, read those debates. If you want to detect features, then detect features. If you actually want to detect browsers, then do so with the user agent.
The reason I need this message in IE is because the site isn't compatible due to new JS and CSS features.
What about other legacy browsers that don't support the features you want? Why do you only want to deal with one specific browser in this situation.
I wouldn't know where to start with this so apologies for not posting any code.
You already had a good start when you read the myriad of other discussions on this topic.
You seem unwilling to listen to any previous discussion and are hoping there's some magic that hasn't yet found its way to the internet.
There isn't.
Here's a summary of some options.
IE's legacy features - If the specific versions of IE that you want to detect have conditional comments enabled, then use that feature.
User agent sniffing - gives detailed information about the user agent. It can technically be spoofed by the user, but that's very rare, and who cares. If the user wants you to believe they're using a different browser, then let them.
Feature detection - If missing features are your concern, then this would seem to be the obvious choice. However, if you load libraries that provide compatibility for some of the missing features, it could get a little complicated. As long as you're aware of the 3rd party code you load, it shouldn't be an issue.
Let it break - Why not? Do you think your site is the only one they'll encounter that uses modern features? Most sites take this approach, and it works incredibly well.
Ask the user - Kindly request upon entry that the user tell you their browser and version. Say things like "pretty please" and convince them that it's of the utmost importance (lie to them), and you may have some success.
Write a virtual psychic library - This would harness the unseen powers of the universe to detect the exact browser and version of the visitor to your site. Seems like a winning solution to me.
You're not the first to want this, but you're sort of acting like this topic hasn't really been explored in full until today. It has. There's nothing new at the moment. When there is, it will be big news, and you'll see it discussed in those old posts.
I just wrote a codepen a couple of days ago that uses the approach codepen.io utilizes in production to notify a user when they come to their site with an IE browser. The notification is modal. It's pretty solid.
CSS:
* {
margin: 0;
padding: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
#unsupported-message :last-child {
margin-bottom: 0px;
}
html, body {
height: 100%;
-webkit-overflow-scrolling: touch;
}
body {
background: #131417;
}
/* #media all and (min-width:831px) */
body {
position: relative;
height: auto;
min-height: 100vh;
}
body {
color: white;
}
body {
position: relative;
overflow-x: hidden;
overflow-y: auto;
height: 100vh;
background: #131417;
}
/* #media all and (min-width:831px) */
body:not(.sidebar-false) {
padding-left: 188px;
}
html {
font-family: "Lato", "Lucida Grande", "Lucida Sans Unicode", Tahoma, Sans-Serif;
line-height: 1.5;
font-size: 15px;
font-weight: 400;
}
html {
overflow-x: hidden;
}
#unsupported-overlay,
#unsupported-modal {
display: block;
position: absolute;
position: fixed;
left: 0;
right: 0;
z-index: 9999;
background: #000;
color: #D5D7DE;
}
#unsupported-overlay {
top: 0;
bottom: 0;
opacity: 0.7;
}
#unsupported-modal {
top: 80px;
margin: auto;
width: 90%;
max-width: 520px;
max-height: 90%;
padding: 40px 20px;
box-shadow: 0 10px 30px #000;
text-align: center;
overflow: hidden;
overflow-y: auto;
border: solid 7px #ffdd40;
}
#unsupported-message :last-child { margin-bottom: 0; }
#unsupported-message h2 {
font-family: 'Telefon', Sans-Serif;
font-size: 34px;
color: #FFF;
}
#unsupported-message h3 {
font-size: 20px;
color: #FFF;
}
body.hide-unsupport { padding-top: 24px; }
body.hide-unsupport #unsupported-message { visibility: hidden; }
#unsupported-banner {
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
background: #ffdd40;
color: #000;
font-size: 14px;
padding: 2px 5px;
line-height: 1.5;
text-align: center;
visibility: visible;
z-index: 199;
}
#unsupported-banner a {
color: #000;
text-decoration: underline;
}
#media (max-width: 800px), (max-height: 500px) {
#unsupported-message .modal p {
/* font-size: 12px; */
line-height: 1.2;
margin-bottom: 1em;
}
#unsupported-modal {
position: absolute;
top: 20px;
}
#unsupported-message h1 { font-size: 22px; }
body.hide-unsupport { padding-top: 0px; }
#unsupported-banner { position: static; }
#unsupported-banner strong,
#unsupported-banner u { display: block; }
}
JS:
// dirty vanilla listen method
function listen(evnt, elem, func) {
if (elem.addEventListener) // W3C DOM
elem.addEventListener(evnt,func,false);
else if (elem.attachEvent) { // IE DOM
var r = elem.attachEvent("on"+evnt, func);
return r;
}
else window.alert('Error: unsupported browser!');
}
// dirty browser detection but production worthy
function get_browser() {
var ua = navigator.userAgent, tem, M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
if (/trident/i.test(M[1])) {
tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
return { name: 'IE', version: (tem[1] || '') };
}
if (M[1] === 'Chrome') {
tem = ua.match(/\bOPR\/(\d+)/)
if (tem != null) { return { name: 'Opera', version: tem[1] }; }
}
if (window.navigator.userAgent.indexOf("Edge") > -1) {
tem = ua.match(/\Edge\/(\d+)/)
if (tem != null) { return { name: 'Edge', version: tem[1] }; }
}
M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
if ((tem = ua.match(/version\/(\d+)/i)) != null) { M.splice(1, 1, tem[1]); }
return {
name: M[0],
version: +M[1]
};
}
function isUnsupported (browser) {
return (browser.name === "MSIE" || browser.name === "IE")
}
var isUnsupported = this.isUnsupported(this.get_browser());
/*
Uncomment the below line of code to simulate
being in an IE browser.
*/
//var isUnsupported = true;
if (isUnsupported) {
this.listen("load", window, function() {
var d1 = document.createElement('div');
var a1 = document.createElement('a');
var d2 = document.createElement('div');
var title = document.createElement('h2');
var p1 = document.createElement('p');
d1.id = 'unsupported-message';
a1.id = 'unsupported-overlay';
a1.href = '#unsupported-modal';
d2.id = 'unsupported-modal';
d2.role = 'alertdialog';
d2['aria-labelledby'] = 'unsupported-title';
title.id = 'unsupported-title';
title.innerHTML = 'âš  Unsupported Browser âš ';
d2.appendChild(title);
d2.innerHTML += "This site does not support Internet Explorer. We generally only support the recent versions of major browsers like Chrome, Firefox, Safari, and Edge."
d2.appendChild(p1)
d1.appendChild(a1);
d1.appendChild(d2)
document.body.appendChild(d1);
});
} else {
var instructions = document.createElement('div')
instructions.innerHTML = "Uncomment line 45 (//var isUnsupported = true;) in the javascript to simulate being in an unsupported browser."
document.body.append(instructions)
}

How do I direct JavaScript to a function on a satisfied IF statement? Trying to fix an Alert loop after progress bar completion

This is a very basic question, and for some reason I am having a hard time wrapping my brain around it. I am new and learning so bear with me please.
Here is a progress bar: https://codepen.io/cmpackagingllc/pen/ZNExoa
When the bar has loaded completely it adds the class completed as seen on js line 41.
progress.bar.classList.add('completed');
So say once completed I want to add an Alert that say's "completed". I assume this would be an easy task but because of the way the code is written with the loop seen on line 46/47
loop();
}, randomInterval);
I am unable to incorporate the Alert properly without an alert loop even when I used return false to stop the loop afterwards.
So the route I am trying to take now is to add the alert prompt to the success function found on line 21-25
function success() {
progress.width = progress.bar.offsetWidth;
progress.bar.classList.add('completed');
clearInterval(setInt);
alert("Completed!");
}
But now I am stuck trying to format it correctly so when the if is called on line 36
if (progress.width >= progress.bar.offsetWidth) {
When the if is called on line 36 I want to to jump to the success function instead. No matter how I try it the code fails to execute. How would I format this correctly so it jumps to my function instead of looping after completed?
I would greatly appreciate some assistance with this. I am trying to understand if there is a better way to add the alert. Thank you much.
I read your code with special attention because recently I have been working with some loading bars (but not animated ones).
The problem is that you are using setTimeout() and not setInterval(), so calling clearInterval() has no effect at all. And you really don't need setInterval() because you're already making recursive calls (looping by calling the same function from its body).
I've took the liberty of rewriting your code for you to analyse it. Please let me know if you have any doubts.
NOTE: It's easier in this case to use relative units for the width! So you don't have to calculate "allowance".
let progress = {
fill: document.querySelector(".progress-bar .filler"),
bar: document.querySelector(".progress-bar"),
width: 0
};
(function loop() {
setTimeout(function () {
progress.width += Math.floor(Math.random() * 50);
if (progress.width >= 100) {
progress.fill.style.width = '100%';
progress.bar.classList.add('completed');
setTimeout(function () {
alert('COMPLETED!');
}, 500);
} else {
progress.fill.style.width = `${progress.width}%`;
loop();
}
}, Math.round(Math.random() * (1400 - 500)) + 500);
})();
Like a comment said, there are several timers in your code. Also, success was never executed. Here you have a version that works.
If you are learning, try to make your code as simple as possible, use pseudocode to see in wich step there is an error and try debugging from there.
var progress = {
fill: document.querySelector(".progress-bar .filler"),
bar: document.querySelector(".progress-bar"),
width: 0 };
function setSize() {
var allowance = progress.bar.offsetWidth - progress.width;
var increment = Math.floor(Math.random() * 50 + 1);
progress.width += increment > allowance ? allowance : increment;
progress.fill.style.width = String(progress.width + "px");
}
function success() {
progress.width = progress.bar.offsetWidth;
progress.bar.classList.add('completed');
alert("Completed!");
}
(function loop() {
var randomInterval = Math.round(Math.random() * (1400 - 500)) + 500;
var setInt = setTimeout(function () {
setSize();
if (progress.width >= progress.bar.offsetWidth) {
success();
} else {
loop();
}
}, randomInterval);
})();
.progress-bar {
height: 10px;
width: 350px;
border-radius: 5px;
overflow: hidden;
background-color: #D2DCE5;
}
.progress-bar.completed .filler {
background: #0BD175;
}
.progress-bar.completed .filler:before {
opacity: 0;
}
.progress-bar .filler {
display: block;
height: 10px;
width: 0;
background: #00AEEF;
overflow: hidden;
transition: all 0.5s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.progress-bar .filler:before {
content: '';
display: block;
background: repeating-linear-gradient(-45deg, #00AEEF, #00AEEF 10px, #23c3ff 10px, #23c3ff 20px);
height: 10px;
width: 700px;
border-radius: 5px;
animation: fill 10s linear infinite;
}
#keyframes fill {
from {
transform: translatex(-350px);
}
to {
transform: translatex(20px);
}
}
<div class="progress-bar">
<span class="filler"></span>
</div>

How can I dynamically add a pattern image to a svg?

I'm new working with SVG images. I'm using them to paint a jacket several times of different colors without needing to have an image for each colour. This is being done with jQuery.
That was the 'easy' part. I solved it by applying fill: #color; CSS rule to <path> inside <svg>.
The hard part is when trying to fill the svg path with an image. It's really weird. My code is printed just fine in the html inside the <svg>, but not working at all. And when, in chrome's dev tools, I cut the <defs> element, and paste it again exactly where it was, it suddenly works! It's driving me crazy :(.
My code:
var items = [
{
title: 'Africa',
// color: '#776254'
},
{
title: 'Aguamarina',
// color: '#9cd3be'
},
{
title: 'Aluminio',
// color: '#9b9b9b'
},
{
title: 'Amarillo Jamaica',
// color: '#ffcd01'
},
{
title: 'Amatista',
// color: '#4d4169'
},
{
title: 'Ambar Brillante',
// color: '#eb6608'
},
{
title: 'Arándano',
// color: '#604483'
}
];
$(function () {
var PrendaShow = {
$mac_wrapper: $('#prendas-mac-slider-wrapper .mac-slider'),
$fullprints_wrapper: $('#fullprints-gallery'),
img: {
src: 'image.svg',
width: 350,
height: 188
},
init: function () {
this.makeItems();
this.bindEvents();
},
bindEvents: function () {
// events
},
makeItems: function() {
var self = this,
$model = $('<div/>', { class: 'mac-item' });
$model.append($('<div/>', { class: 'item-img' }));
$.each(items, function() {
var $item = $model.clone();
self.$mac_wrapper.append($item);
});
this.svgDraw();
},
svgDraw: function () {
var self = this;
$.get(this.img.src, function(data) {
var $svg = self.normalizeSvg(data);
self.appendImgs($svg);
});
},
normalizeSvg: function (data) {
var $svg = $(data).find('svg');
$svg = $svg.removeAttr('xmlns:a');
$svg.width(this.img.width).height(this.img.height);
return $svg;
},
appendImgs: function ($svg) {
var items = this.$mac_wrapper.find('.mac-item');
$.each(items, function() {
var $clone = $svg.clone(),
color = $(this).data('color');
$clone.find('path').css('fill', 'url(#img1)');
var img = document.createElementNS('http://www.w3.org/2000/svg', 'image');
img.setAttributeNS(null,'height','536');
img.setAttributeNS(null,'width','536');
img.setAttributeNS('http://www.w3.org/1999/xlink','href','http://www.boogdesign.com/examples/svg/daisy-grass-repeating-background.jpg');
img.setAttributeNS(null,'x','10');
img.setAttributeNS(null,'y','10');
img.setAttributeNS(null, 'visibility', 'visible')
$clone.prepend($('<defs/>').html('<pattern id="img1" patternUnits="userSpaceOnUse" width="100" height="100"></pattern>'));
$clone.find('pattern').append(img)
$(this).find('.item-img').append($clone);
});
}
};
PrendaShow.init();
});
#prendas-mac-slider-wrapper {
margin-top: 80px;
}
.mac-slider {
display: flex;
font-size: 0;
padding: 0 100px;
}
.mac-item {
width: 100%;
height: 160px;
min-width: 0;
position: relative;
display: inline-block;
text-align: center;
cursor: pointer;
}
.item-img {
background: url('https://ae01.alicdn.com/kf/HTB1Cqi6KXXXXXbpXVXXq6xXFXXXy/Classic-font-b-White-b-font-font-b-Jacket-b-font-font-b-Men-b-font.jpg') center center no-repeat;
background-size: contain;
pointer-events: none;
position: absolute;
top: 0;
left: -9999px;
right: -9999px;
margin: auto;
}
svg {
mix-blend-mode: multiply;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hero">
<div class="container-fluid">
<div id="prendas-mac-slider-wrapper" class="row">
<div class="mac-slider">
</div>
</div>
</div>
</div>
I'm not being able to give my exact example because of images upload. I really hope you understand what I'm trying to do here, and what's going wrong.
EDIT: Not sure if this deserves to be in an answer, but I preferred to write it here since I don't think its the right way to do this.
As I knew that, from chrome dev tools, if I deleted the <defs> element and pasted it again, it worked, I tried this and worked:
var svg_html = $svg.html();
$svg.html('');
$svg.html(svg_html);
Your problem is here:
$clone.prepend($('<defs/>').html('<pattern ...
You cannot use jQuery to create SVG elements like this. You are doing it the correct way (with createElementNS()) when you create the <image> element. But you also need to use the same method when creating the <defs> and <pattern> elements.

Event 'transitionend' is called too early, it delays rendering

What I'm doing and what's wrong
When I click on a button, a slider shows up. (here is an example of what it looks like, do not pay attention to this code)
The slider shows via an animation. When the animation is finished I should include an HTML page I've loaded from the server. I need to apply the HTML in the slider after the animation otherwise the animation stops (the DOM is recalculated).
My algorithm
Start the request to get the HTML to display inside the slider
Start the animation
Wait the data to be ready and the transition to be finished
Why? If I apply the HTML during the animation, it stops the animation while the new HTML is added to the DOM. So I wait for both to end before step 4.
Apply the HTML inside the slider
Here is the shortened code:
// Start loading data & animate transition
var count = 0;
var data = null;
++count;
$.get(url, function (res) {
data = res;
cbSlider();
});
// Animation starts here
++count;
$(document).on('transitionend', '#' + sliderId, function () {
$(document).off('transitionend', '#' + sliderId);
cbSlider()
});
function cbSlider() {
--count;
// This condition is only correct when both GET request and animation are finished
if (count == 0) {
// Attempt to enforce the frame to finish (doesn't work)
window.requestAnimationFrame(() => { return });
$('#' + sliderId + ' .slider-content').html(data);
}
}
The detailed issue
transitionend is called too early. It makes the last animated frame a lot too long (477.2ms) and the last frame is not rendered at transitionend event.
From the Google documentation, I can tell you that the Paint and Composite step of the Pixel Pipeline is called after the Event(transitionend):
Maybe I'm overthinking this.
How should I handle this kind of animations?
How can I wait the animation to be fully finished and rendered?
I'm not sure why transitionend is fired before the last frame has rendered, but in this (very crude) test it seems that a setTimeout does help...
The first example shows how the html calculation and injection happens too early. The second example wraps the long running method in a setTimeout and doesn't seem to trigger any interuption in the animation.
Example 1: reproduction of your problem
var ended = 0;
var cb = function() {
ended += 1;
if (ended == 2) {
$(".animated").html(createLongHTMLString());
}
}
$(".load").click(function() {
$(".animated").addClass("loading");
$(".animated").on("transitionend", cb);
setTimeout(cb, 100);
});
function createLongHTMLString() {
var str = "";
for (var i = 0; i < 100000; i += 1) {
str += "<em>Test </em>";
}
return str;
};
.animated,
.target {
width: 100px;
height: 100px;
position: absolute;
text-align: center;
line-height: 100px;
overflow: hidden;
}
.target,
.animated.loading {
transform: translateX(300%);
}
.animated {
background: green;
z-index: 1;
transition: transform .2s linear;
}
.target {
background: red;
z-index: 0;
}
.wrapper {
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="animated">Loading</div>
<div class="target"></div>
</div>
<button class="load">load</button>
Example 2: in which a setTimeout seems to fix it
With a setTimeout around the html injection code.
var ended = 0;
var cb = function() {
ended += 1;
if (ended == 2) {
setTimeout(function() {
$(".animated").html(createLongHTMLString());
});
}
}
$(".load").click(function() {
$(".animated").addClass("loading");
$(".animated").on("transitionend", cb);
setTimeout(cb, 100);
});
function createLongHTMLString() {
var str = "";
for (var i = 0; i < 100000; i += 1) {
str += "<em>Test </em>";
}
return str;
};
.animated,
.target {
width: 100px;
height: 100px;
position: absolute;
text-align: center;
line-height: 100px;
overflow: hidden;
}
.target,
.animated.loading {
transform: translateX(300%);
}
.animated {
background: green;
z-index: 1;
transition: transform .2s linear;
}
.target {
background: red;
z-index: 0;
}
.wrapper {
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="animated">Loading</div>
<div class="target"></div>
</div>
<button class="load">load</button>
Well, if transitions are not working for you the way you want to, you can go back a few years and use jQuery animations instead?
(function(slider){
$.get(url, function (res) {
slider.animate({
// put whatever animations you need here
left: "5%",
}, 5000, function() {
// Animation complete.
slider.find('.slider-content').html(res);
});
});
}($('#' + sliderId)));
You can also start both actions at the same time, and then add the html to the document only after the animation has finished and the request is complete, but that would require a flag.
(function(slider){
// whether the animation is finished
var finished = false;
// whether the html has been added already
var added = false;
// your html data
var html = null;
function add() {
if (finished && html && !added) {
// make sure function will only add html once
added = true;
slider.find('.slider-content').html(html);
}
}
$.get(url, function (res) {
html = res;
add();
});
slider.animate({
// put whatever animations you need here
left: "5%",
}, 5000, function() {
// Animation complete.
finished = true;
add();
});
}($('#' + sliderId)));

Internet Explorer render issue (simple JS timer - window.setTimeout)

<script language="JavaScript" type="text/javascript">
var theBar = createProgressBar(document.getElementById('progress-bar'));
var value;
function resetValue() {
value = 0;
}
function showProgress() {
value += 1;
theBar.setValue(value);
if (value < 100) {
window.setTimeout(showProgress, 100);
}
}
window.onload=resetValue();showProgress();
</script>
--
<script language="JavaScript" type="text/javascript">
function createProgressBar(elem) {
var div1 = document.createElement('DIV');
div1.className = 'progress-bar-background';
div1.style.height = elem.offsetHeight + 'px';
elem.appendChild(div1);
var div2 = document.createElement('DIV');
div2.className = 'progress-bar-complete';
div2.style.height = elem.offsetHeight + 'px';
div2.style.top = '-' + elem.offsetHeight + 'px';
elem.appendChild(div2);
return {
div1 : div1,
div2 : div2,
setValue : function(v) {
this.div2.style.width = v + '%';
}
}
}
</script>
--
div.field input{
height: 45px;
width: 270px;
font-size: 24px;
}
.progress-bar-background {
background-color: #D0D0D0;
width: 100%;
position: relative;
overflow:hidden;
top: 0;
left: 0;
}
.progress-bar-complete {
background-color: green;
width: 50%;
position: relative;
overflow:hidden;
top: -12px;
left: 0;
}
#progress-bar {
width: auto;
height: 10px;;
overflow:hidden;
border: 0px black solid;
}
--
This snippet works perfectly under Chromer, Safari and FireFox.
The only issue is with Internet Explorer.
It seems to render as "half-full" and doesn`t execute anything.
Since I`m not that familiar with JS I have no clue what to start looking for.
Would appreciate some noob friendly advice.
change this...
window.onload=resetValue();showProgress();
to this...
window.onload = function() {
createProgressBar();
resetValue();
showProgress();
};
and you should be fine.
Remember...
"window.onload" is a property of the Window object ... and the value of this property should be a function that will execute automatically once the browser has loaded the entire DOM AND all the content (images, css, js, etc.)
This a NOT a good place to execute your stuff however -- you should use the event "onContentLoaded" but since it is not uniformly supported across browsers -- you should use a JavaScript library such as jQuery or Prototype or MooTools instead.
BUT -- of course if you're new to JS -- do NOT skim over it in order to get the pleasure of using these libs -- first get the real taste of what JavaScript is and what it is like to juggle with the browser incompatibilities -- only then you'll be able to appreciate the full potential of these libraries.
The first thing I see is that you shouldn't create the progress bar (or reference anything in the DOM) until the page has been loaded. IE is particularly sensitive to this. It looks to me like you're calling createProgressBar right when the javascript is loaded rather than after the page is loaded.
When I put your stuff into a jsFiddle and make sure that the code doesn't run until the page is loaded, it works for me in IE8.
See it here: http://jsfiddle.net/jfriend00/CQqat/

Categories