Onload JavaScript sometimes doesn't execute - javascript

I have encountered an issue with my JavaScript. Sometimes, the code doesn't execute at all and i can't corelate this to a specific thing, like throwing an error and halting the code or something similar. What i intend to do is to change the picture (a logo) depending of the resolution of the device.
function logo_change() {
if ( document.body.clientWidth < 390 ) {
document.getElementById('logo').style.display = 'none';
document.getElementById('logo-m').style.display = 'block';
}
else {
document.getElementById('logo-m').style.display = 'none';
document.getElementById('logo').style.display = 'block';
}
}
window.onresize = function() {
logo_change();
};
window.onload = function() {
logo_change();
};
#logo {
max-width: 20%;
min-width: 185px;
float: left;
margin-top: 17px;
}
#logo-m {
width: 50px;
float: left;
margin-top: 17px;
display: none;
}
<a id='logo-l' class="logo-l" href="index.php">
<img src="https://d1afx9quaogywf.cloudfront.net/sites/default/files/Logos/facebook-logo_0.png" id='logo' class="logo" name="logo" height="60"></img>
<img src="https://www.ricksdailytips.com/wp-content/uploads/2016/08/f.png" id='logo-m' class="logo-m" height="50"></img>
</a>
I have tried of doing this with media queries doing basically the same thing( with display block and none), but the link would collapse and such.
Also, if i resize the page, the code executes and the logo changes. Thus, i thing is is a window.onload thing.
Thanks for your responses.

To do this with CSS media queries:
#logo, #logo-m {
display: none;
/* other common properties */
}
#media screen and (max-width: 389px) {
#logo-m { display: block; }
}
#media screen and (min-width: 390px) {
#logo { display: block; }
}

Related

Lazy loading of images for website to load faster

i want that before the actual image gets loaded a spinner should be shown so that my website can load faster
window.addEventListener('load', function(){
var allimages= document.getElementsByTagName('img');
for (var i=0; i<allimages.length; i++) {
if (allimages[i].getAttribute('data-src')) {
allimages[i].setAttribute('src', allimages[i].getAttribute('data-src'));
}
}
}, false)
<img src="https://loremflickr.com/400/600" data-src="images/banguet-hall-location-icon.png" class="secEightImg" />
<img src="http://www.jettools.com/images/animated_spinner.gif" data-src="images/banguet-hall-location-icon.png" class="secEightImg" />
<script>
</script>
the problem is the actual image is shown two times and instead of spinner a broken image (which is shown when no image is found) is shown first
please help
If you want a spinner per image, just add the spinner URL as the initial src attribute for all of them:
<img src="spinner.gif" data-src="actual-image.png" />
Then, once the page loads, change all those src for the real URL (data-src) and listen for the load and error events on each image.
For each of them, add a .loaded class or .error class to the images and style them as you want. For example, you could hide the ones that could not be loaded, show a custom "error" image (using background-image) or style them as you wish, like in this example:
function imageLoaded(e) {
updateImage(e.target, 'loaded');
}
function imageError(e) {
updateImage(e.target, 'error');
}
function updateImage(img, classname) {
// Add the right class:
img.classList.add(classname);
// Remove the data-src attribute:
img.removeAttribute('data-src');
// Remove both listeners:
img.removeEventListener('load', imageLoaded);
img.removeEventListener('error', imageError);
}
window.addEventListener('load', () => {
Array.from(document.getElementsByTagName('img')).forEach(img => {
const src = img.getAttribute('data-src');
if (src) {
// Listen for both events:
img.addEventListener('load', imageLoaded);
img.addEventListener('error', imageError);
// Just to simulate a slow network:
setTimeout(() => {
img.setAttribute('src', src);
}, 2000 + Math.random() * 2000);
}
});
})
html,
body {
margin: 0;
height: 100%;
}
.images {
width: 100%;
height: 100%;
background: #000;
display: flex;
align-items: center;
overflow-x: scroll;
}
.margin-fix {
border-right: 1px solid transparent;
height: 16px;
}
img {
width: 16px;
height: 16px;
margin: 0 64px;
}
img.loaded {
width: auto;
height: 100%;
margin: 0;
}
img.error {
background: red;
border-radius: 100%;
/* You could add a custom "error" image here using background-image */
}
<div class="images">
<img
src="https://i.stack.imgur.com/RvfGz.gif"
data-src="https://d39a3h63xew422.cloudfront.net/wp-content/uploads/2014/07/20145029/driven-by-design-the-incomparable-lancia-stratos-1476934711918-1000x573.jpg" />
<img
src="https://i.stack.imgur.com/RvfGz.gif"
data-src="https://car-images.bauersecure.com/pagefiles/76591/1752x1168/ford_racing_puma_01.jpg?mode=max&quality=90&scale=down" />
<img
src="https://i.stack.imgur.com/RvfGz.gif"
data-src="http://doesntexist.com/image.jpg" />
<span class="margin-fix"></span>
</div>
The problem is that the spinner image you use initially might take some time to load.
One solution would be to use a data URI, so instead of:
<img src="https://i.stack.imgur.com/RvfGz.gif" data-src="actual-image.png" />
You would have:
<img src="data:image/gif;base64,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cXVlcnknPmZ1bmN0aW9uLm15c3FsLXF1ZXJ5PC9hPl06IENhbid0IGNvbm5lY3QgdG8gbG9jYWwgTXlTUUwgc2VydmVyIHRocm91Z2ggc29ja2V0ICcvdmFyL3J1bi9teXNxbGQvbXlzcWxkLnNvY2snICgyKSBpbiA8Yj4vaG9tZS9hamF4bG9hZC93d3cvbGlicmFpcmllcy9jbGFzcy5teXNxbC5waHA8L2I+IG9uIGxpbmUgPGI+Njg8L2I+PGJyIC8+CjxiciAvPgo8Yj5XYXJuaW5nPC9iPjogIG15c3FsX3F1ZXJ5KCkgWzxhIGhyZWY9J2Z1bmN0aW9uLm15c3FsLXF1ZXJ5Jz5mdW5jdGlvbi5teXNxbC1xdWVyeTwvYT5dOiBBIGxpbmsgdG8gdGhlIHNlcnZlciBjb3VsZCBub3QgYmUgZXN0YWJsaXNoZWQgaW4gPGI+L2hvbWUvYWpheGxvYWQvd3d3L2xpYnJhaXJpZXMvY2xhc3MubXlzcWwucGhwPC9iPiBvbiBsaW5lIDxiPjY4PC9iPjxiciAvPgo8YnIgLz4KPGI+V2FybmluZzwvYj46ICBteXNxbF9xdWVyeSgpIFs8YSBocmVmPSdmdW5jdGlvbi5teXNxbC1xdWVyeSc+ZnVuY3Rpb24ubXlzcWwtcXVlcnk8L2E+XTogQ2FuJ3QgY29ubmVjdCB0byBsb2NhbCBNeVNRTCBzZXJ2ZXIgdGhyb3VnaCBzb2NrZXQgJy92YXIvcnVuL215c3FsZC9teXNxbGQuc29jaycgKDIpIGluIDxiPi9ob21lL2FqYXhsb2FkL3d3dy9saWJyYWlyaWVzL2NsYXNzLm15c3FsLnBocDwvYj4gb24gbGluZSA8Yj42ODwvYj48YnIgLz4KPGJyIC8+CjxiPldhcm5pbmc8L2I+OiAgbXlzcWxfcXVlcnkoKSBbPGEgaHJlZj0nZnVuY3Rpb24ubXlzcWwtcXVlcnknPmZ1bmN0aW9uLm15c3FsLXF1ZXJ5PC9hPl06IEEgbGluayB0byB0aGUgc2VydmVyIGNvdWxkIG5vdCBiZSBlc3RhYmxpc2hlZCBpbiA8Yj4vaG9tZS9hamF4bG9hZC93d3cvbGlicmFpcmllcy9jbGFzcy5teXNxbC5waHA8L2I+IG9uIGxpbmUgPGI+Njg8L2I+PGJyIC8+CjxiciAvPgo8Yj5XYXJuaW5nPC9iPjogIG15c3FsX3F1ZXJ5KCkgWzxhIGhyZWY9J2Z1bmN0aW9uLm15c3FsLXF1ZXJ5Jz5mdW5jdGlvbi5teXNxbC1xdWVyeTwvYT5dOiBDYW4ndCBjb25uZWN0IHRvIGxvY2FsIE15U1FMIHNlcnZlciB0aHJvdWdoIHNvY2tldCAnL3Zhci9ydW4vbXlzcWxkL215c3FsZC5zb2NrJyAoMikgaW4gPGI+L2hvbWUvYWpheGxvYWQvd3d3L2xpYnJhaXJpZXMvY2xhc3MubXlzcWwucGhwPC9iPiBvbiBsaW5lIDxiPjY4PC9iPjxiciAvPgo8YnIgLz4KPGI+V2FybmluZzwvYj46ICBteXNxbF9xdWVyeSgpIFs8YSBocmVmPSdmdW5jdGlvbi5teXNxbC1xdWVyeSc+ZnVuY3Rpb24ubXlzcWwtcXVlcnk8L2E+XTogQSBsaW5rIHRvIHRoZSBzZXJ2ZXIgY291bGQgbm90IGJlIGVzdGFibGlzaGVkIGluIDxiPi9ob21lL2FqYXhsb2FkL3d3dy9saWJyYWlyaWVzL2NsYXNzLm15c3FsLnBocDwvYj4gb24gbGluZSA8Yj42ODwvYj48YnIgLz4K" data-src="actual-image.png" />
As you can see, your HTML document will grow fast using this approach, which is a problem.
A better approach might be to use CSS to add the spinner so that you only include the data URI once. To do that, you need to add an empty src attribute to your images initially anyway:
<img src data-src="actual-image.png" />
Or:
<img src="" data-src="actual-image.png" />
If you don't put it, the image will have an annoying gray border you can't get rid of until you add a src attribute.
function imageLoaded(e) {
updateImage(e.target, 'loaded');
}
function imageError(e) {
updateImage(e.target, 'error');
}
function updateImage(img, classname) {
// Add the right class:
img.classList.add(classname);
// Remove the data-src attribute:
img.removeAttribute('data-src');
// Remove both listeners:
img.removeEventListener('load', imageLoaded);
img.removeEventListener('error', imageError);
}
window.addEventListener('load', () => {
Array.from(document.getElementsByTagName('img')).forEach(img => {
const src = img.getAttribute('data-src');
if (src) {
// Listen for both events:
img.addEventListener('load', imageLoaded);
img.addEventListener('error', imageError);
// Just to simulate a slow network:
setTimeout(() => {
img.setAttribute('src', src);
}, 2000 + Math.random() * 2000);
}
});
})
html,
body {
margin: 0;
height: 100%;
}
.images {
width: 100%;
height: 100%;
background: #000;
display: flex;
align-items: center;
overflow-x: scroll;
}
.margin-fix {
border-right: 1px solid transparent;
height: 16px;
}
img {
width: 16px;
height: 16px;
margin: 0 64px;
background-image: url("data:image/gif;base64,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cXVlcnknPmZ1bmN0aW9uLm15c3FsLXF1ZXJ5PC9hPl06IENhbid0IGNvbm5lY3QgdG8gbG9jYWwgTXlTUUwgc2VydmVyIHRocm91Z2ggc29ja2V0ICcvdmFyL3J1bi9teXNxbGQvbXlzcWxkLnNvY2snICgyKSBpbiA8Yj4vaG9tZS9hamF4bG9hZC93d3cvbGlicmFpcmllcy9jbGFzcy5teXNxbC5waHA8L2I+IG9uIGxpbmUgPGI+Njg8L2I+PGJyIC8+CjxiciAvPgo8Yj5XYXJuaW5nPC9iPjogIG15c3FsX3F1ZXJ5KCkgWzxhIGhyZWY9J2Z1bmN0aW9uLm15c3FsLXF1ZXJ5Jz5mdW5jdGlvbi5teXNxbC1xdWVyeTwvYT5dOiBBIGxpbmsgdG8gdGhlIHNlcnZlciBjb3VsZCBub3QgYmUgZXN0YWJsaXNoZWQgaW4gPGI+L2hvbWUvYWpheGxvYWQvd3d3L2xpYnJhaXJpZXMvY2xhc3MubXlzcWwucGhwPC9iPiBvbiBsaW5lIDxiPjY4PC9iPjxiciAvPgo8YnIgLz4KPGI+V2FybmluZzwvYj46ICBteXNxbF9xdWVyeSgpIFs8YSBocmVmPSdmdW5jdGlvbi5teXNxbC1xdWVyeSc+ZnVuY3Rpb24ubXlzcWwtcXVlcnk8L2E+XTogQ2FuJ3QgY29ubmVjdCB0byBsb2NhbCBNeVNRTCBzZXJ2ZXIgdGhyb3VnaCBzb2NrZXQgJy92YXIvcnVuL215c3FsZC9teXNxbGQuc29jaycgKDIpIGluIDxiPi9ob21lL2FqYXhsb2FkL3d3dy9saWJyYWlyaWVzL2NsYXNzLm15c3FsLnBocDwvYj4gb24gbGluZSA8Yj42ODwvYj48YnIgLz4KPGJyIC8+CjxiPldhcm5pbmc8L2I+OiAgbXlzcWxfcXVlcnkoKSBbPGEgaHJlZj0nZnVuY3Rpb24ubXlzcWwtcXVlcnknPmZ1bmN0aW9uLm15c3FsLXF1ZXJ5PC9hPl06IEEgbGluayB0byB0aGUgc2VydmVyIGNvdWxkIG5vdCBiZSBlc3RhYmxpc2hlZCBpbiA8Yj4vaG9tZS9hamF4bG9hZC93d3cvbGlicmFpcmllcy9jbGFzcy5teXNxbC5waHA8L2I+IG9uIGxpbmUgPGI+Njg8L2I+PGJyIC8+CjxiciAvPgo8Yj5XYXJuaW5nPC9iPjogIG15c3FsX3F1ZXJ5KCkgWzxhIGhyZWY9J2Z1bmN0aW9uLm15c3FsLXF1ZXJ5Jz5mdW5jdGlvbi5teXNxbC1xdWVyeTwvYT5dOiBDYW4ndCBjb25uZWN0IHRvIGxvY2FsIE15U1FMIHNlcnZlciB0aHJvdWdoIHNvY2tldCAnL3Zhci9ydW4vbXlzcWxkL215c3FsZC5zb2NrJyAoMikgaW4gPGI+L2hvbWUvYWpheGxvYWQvd3d3L2xpYnJhaXJpZXMvY2xhc3MubXlzcWwucGhwPC9iPiBvbiBsaW5lIDxiPjY4PC9iPjxiciAvPgo8YnIgLz4KPGI+V2FybmluZzwvYj46ICBteXNxbF9xdWVyeSgpIFs8YSBocmVmPSdmdW5jdGlvbi5teXNxbC1xdWVyeSc+ZnVuY3Rpb24ubXlzcWwtcXVlcnk8L2E+XTogQSBsaW5rIHRvIHRoZSBzZXJ2ZXIgY291bGQgbm90IGJlIGVzdGFibGlzaGVkIGluIDxiPi9ob21lL2FqYXhsb2FkL3d3dy9saWJyYWlyaWVzL2NsYXNzLm15c3FsLnBocDwvYj4gb24gbGluZSA8Yj42ODwvYj48YnIgLz4K");
}
img.loaded {
width: auto;
height: 100%;
margin: 0;
}
img.error {
background: red;
border-radius: 100%;
/* You could add a custom "error" image here using background-image */
}
<div class="images">
<img
src
data-src="https://d39a3h63xew422.cloudfront.net/wp-content/uploads/2014/07/20145029/driven-by-design-the-incomparable-lancia-stratos-1476934711918-1000x573.jpg" />
<img
src
data-src="https://car-images.bauersecure.com/pagefiles/76591/1752x1168/ford_racing_puma_01.jpg?mode=max&quality=90&scale=down" />
<img
src
data-src="http://doesntexist.com/image.jpg" />
<span class="margin-fix"></span>
</div>
Other approaches might be to just hide the images initially with display: none for example, in which case you might want a wrapper around them to show something like an empty box to indicate the users that something will be shown in there, or even a spinner made with other elements if you want/need to get fancy.
What you can do is something like:
$(".sly-main-slider div img").attr('src', "#");
$(".sly-main-slider").addClass("loading");
$(".sly-main-slider div").hide();
$(".sly-main-slider div img").load(function() {
$(".sly-main-slider div").show();
$(".sly-main-slider").removeClass("loading");
}).attr('src', "https://loremflickr.com/400/600");
.loading {
position: absolute;
top: 10%;
left: 10%;
z-index: 2000;
background: url(http://1.bp.blogspot.com/-nfXo9GWbDtM/VOn0vr4yLMI/AAAAAAAABCA/dDNgd7_QCFo/s1600/block-loader.gif) no-repeat center center;
height: 32px;
width: 32px;
}
.loading:after {
position: absolute;
top: 8px;
left: 40px;
content: 'Loading...';
}
body {
position: relative;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='sly-main-slider'>
<div>
<img src="https://loremflickr.com/400/600" alt="" />
</div>
</div>

New to Javascript - changing style of element

So based on the value of a boolean, I want certain tabs in my sidebar to display/ hide when the page loads.
var someVar = true;
function show_ifTrue() {
if (Boolean(someVar) == true) {
document.getElementById('x').style.display = 'block';
console.log("I CHANGED IT");
}
else {
document.getElementById('x').style.background = 'red';
}
}
.sidebar {
position: fixed;
overflow-y: scroll;
top: 0;
bottom: 0;
float: left;
display: inline-block;
z-index: 50;
}
#tab {
display: block;
}
#x {
display: none;
}
<div class="sidebar">
Cats
Dogs
</div>
I have tried everything from taking out the display from .sidebar a{...} and giving each tab its own display property, using !important, changing in JS using style.cssText or setting attribute, I just can't get it to change the display.
In order to change the color, you have to call the function first, but you are never calling it, since onpageshow could only be added to <body>, so you could move it there - <body onpageshow='...'>. Or, if you still want to deal only with the div itself, do it onload:
window.onload=function(){
show_ifTrue();
}
This way too could also use your pageshow:
window.onpageshow=function(){
show_ifTrue();
}
Also, you don't need Boolean prefix in your function, just someVar == true.
It appears that you are missing the css closing braket for #tab (EDIT: OP edited this, but it could also have been part of the issue). Also, you might want to use window.onload, or onpageshow on the body element — it's the only element that it will work on. With that fixed, here's a working example:
window.onload = function () {
show_ifTrue();
}
var someVar = true;
function show_ifTrue() {
if (someVar === true) {
document.getElementById('x').style.display = 'block';
console.log('I CHANGED IT');
}
else {
document.getElementById('x').style.background = 'red';
}
}
.sidebar {
position: fixed;
overflow-y: scroll;
top: 0;
bottom: 0;
float: left;
display: inline-block;
z-index: 50;
}
#tab {
display: block;
}
#x {
display: none;
}
<div class="sidebar">
Cats
Dogs
</div>
I hope that helps!

Scrollable div to stick to bottom, when outer div changes in size

Here is an example chat app ->
The idea here is to have the .messages-container take up as much of the screen as it can. Within .messages-container, .scroll holds the list of messages, and in case there are more messages then the size of the screen, scrolls.
Now, consider this case:
The user scrolls to the bottom of the conversation
The .text-input, dynamically gets bigger
Now, instead of the user staying scrolled to the bottom of the conversation, the text-input increases, and they no longer see the bottom.
One way to fix it, if we are using react, calculate the height of text-input, and if anything changes, let .messages-container know
componentDidUpdate() {
window.setTimeout(_ => {
const newHeight = this.calcHeight();
if (newHeight !== this._oldHeight) {
this.props.onResize();
}
this._oldHeight = newHeight;
});
}
But, this causes visible performance issues, and it's sad to be passing messages around like this.
Is there a better way? Could I use css in such a way, to express that when .text-input-increases, I want to essentially shift up all of .messages-container
2:nd revision of this answer
Your friend here is flex-direction: column-reverse; which does all you ask while align the messages at the bottom of the message container, just like for example Skype and many other chat apps do.
.chat-window{
display:flex;
flex-direction:column;
height:100%;
}
.chat-messages{
flex: 1;
height:100%;
overflow: auto;
display: flex;
flex-direction: column-reverse;
}
.chat-input { border-top: 1px solid #999; padding: 20px 5px }
.chat-input-text { width: 60%; min-height: 40px; max-width: 60%; }
The downside with flex-direction: column-reverse; is a bug in IE/Edge/Firefox, where the scrollbar doesn't show, which your can read more about here: Flexbox column-reverse and overflow in Firefox/IE
The upside is you have ~ 90% browser support on mobile/tablets and ~ 65% for desktop, and counting as the bug gets fixed, ...and there is a workaround.
// scroll to bottom
function updateScroll(el){
el.scrollTop = el.scrollHeight;
}
// only shift-up if at bottom
function scrollAtBottom(el){
return (el.scrollTop + 5 >= (el.scrollHeight - el.offsetHeight));
}
In the below code snippet I've added the 2 functions from above, to make IE/Edge/Firefox behave in the same way flex-direction: column-reverse; does.
function addContent () {
var msgdiv = document.getElementById('messages');
var msgtxt = document.getElementById('inputs');
var atbottom = scrollAtBottom(msgdiv);
if (msgtxt.value.length > 0) {
msgdiv.innerHTML += msgtxt.value + '<br/>';
msgtxt.value = "";
} else {
msgdiv.innerHTML += 'Long long content ' + (tempCounter++) + '!<br/>';
}
/* if at bottom and is IE/Edge/Firefox */
if (atbottom && (!isWebkit || isEdge)) {
updateScroll(msgdiv);
}
}
function resizeInput () {
var msgdiv = document.getElementById('messages');
var msgtxt = document.getElementById('inputs');
var atbottom = scrollAtBottom(msgdiv);
if (msgtxt.style.height == '120px') {
msgtxt.style.height = 'auto';
} else {
msgtxt.style.height = '120px';
}
/* if at bottom and is IE/Edge/Firefox */
if (atbottom && (!isWebkit || isEdge)) {
updateScroll(msgdiv);
}
}
/* fix for IE/Edge/Firefox */
var isWebkit = ('WebkitAppearance' in document.documentElement.style);
var isEdge = ('-ms-accelerator' in document.documentElement.style);
var tempCounter = 6;
function updateScroll(el){
el.scrollTop = el.scrollHeight;
}
function scrollAtBottom(el){
return (el.scrollTop + 5 >= (el.scrollHeight - el.offsetHeight));
}
html, body { height:100%; margin:0; padding:0; }
.chat-window{
display:flex;
flex-direction:column;
height:100%;
}
.chat-messages{
flex: 1;
height:100%;
overflow: auto;
display: flex;
flex-direction: column-reverse;
}
.chat-input { border-top: 1px solid #999; padding: 20px 5px }
.chat-input-text { width: 60%; min-height: 40px; max-width: 60%; }
/* temp. buttons for demo */
button { width: 12%; height: 44px; margin-left: 5%; vertical-align: top; }
/* begin - fix for hidden scrollbar in IE/Edge/Firefox */
.chat-messages-text{ overflow: auto; }
#media screen and (-webkit-min-device-pixel-ratio:0) {
.chat-messages-text{ overflow: visible; }
/* reset Edge as it identifies itself as webkit */
#supports (-ms-accelerator:true) { .chat-messages-text{ overflow: auto; } }
}
/* hide resize FF */
#-moz-document url-prefix() { .chat-input-text { resize: none } }
/* end - fix for hidden scrollbar in IE/Edge/Firefox */
<div class="chat-window">
<div class="chat-messages">
<div class="chat-messages-text" id="messages">
Long long content 1!<br/>
Long long content 2!<br/>
Long long content 3!<br/>
Long long content 4!<br/>
Long long content 5!<br/>
</div>
</div>
<div class="chat-input">
<textarea class="chat-input-text" placeholder="Type your message here..." id="inputs"></textarea>
<button onclick="addContent();">Add msg</button>
<button onclick="resizeInput();">Resize input</button>
</div>
</div>
Side note 1: The detection method is not fully tested, but it should work on newer browsers.
Side note 2: Attach a resize event handler for the chat-input might be more efficient then calling the updateScroll function.
Note: Credits to HaZardouS for reusing his html structure
You just need one CSS rule set:
.messages-container, .scroll {transform: scale(1,-1);}
That's it, you're done!
How it works: First, it vertically flips the container element so that the top becomes the bottom (giving us the desired scroll orientation), then it flips the content element so that the messages won't be upside down.
This approach works in all modern browsers. It does have a strange side effect, though: when you use a mouse wheel in the message box, the scroll direction is reversed. This can be fixed with a few lines of JavaScript, as shown below.
Here's a demo and a fiddle to play with:
//Reverse wheel direction
document.querySelector('.messages-container').addEventListener('wheel', function(e) {
if(e.deltaY) {
e.preventDefault();
e.currentTarget.scrollTop -= e.deltaY;
}
});
//The rest of the JS just handles the test buttons and is not part of the solution
send = function() {
var inp = document.querySelector('.text-input');
document.querySelector('.scroll').insertAdjacentHTML('beforeend', '<p>' + inp.value);
inp.value = '';
inp.focus();
}
resize = function() {
var inp = document.querySelector('.text-input');
inp.style.height = inp.style.height === '50%' ? null : '50%';
}
html,body {height: 100%;margin: 0;}
.conversation {
display: flex;
flex-direction: column;
height: 100%;
}
.messages-container {
flex-shrink: 10;
height: 100%;
overflow: auto;
}
.messages-container, .scroll {transform: scale(1,-1);}
.text-input {resize: vertical;}
<div class="conversation">
<div class="messages-container">
<div class="scroll">
<p>Message 1<p>Message 2<p>Message 3<p>Message 4<p>Message 5
<p>Message 6<p>Message 7<p>Message 8<p>Message 9<p>Message 10<p>Message 11<p>Message 12<p>Message 13<p>Message 14<p>Message 15<p>Message 16<p>Message 17<p>Message 18<p>Message 19<p>Message 20
</div>
</div>
<textarea class="text-input" autofocus>Your message</textarea>
<div>
<button id="send" onclick="send();">Send input</button>
<button id="resize" onclick="resize();">Resize input box</button>
</div>
</div>
Edit: thanks to #SomeoneSpecial for suggesting a simplification to the scroll code!
Please try the following fiddle - https://jsfiddle.net/Hazardous/bypxg25c/. Although the fiddle is currently using jQuery to grow/resize the text area, the crux is in the flex related styles used for the messages-container and input-container classes -
.messages-container{
order:1;
flex:0.9 1 auto;
overflow-y:auto;
display:flex;
flex-direction:row;
flex-wrap:nowrap;
justify-content:flex-start;
align-items:stretch;
align-content:stretch;
}
.input-container{
order:2;
flex:0.1 0 auto;
}
The flex-shrink value is set to 1 for .messages-container and 0 for .input-container. This ensures that messages-container shrinks when there is a reallocation of size.
I've moved text-input within messages, absolute positioned it to the bottom of the container and given messages enough bottom padding to space accordingly.
Run some code to add a class to conversation, which changes the height of text-input and bottom padding of messages using a nice CSS transition animation.
The JavaScript runs a "scrollTo" function at the same time as the CSS transition is running to keep the scroll at the bottom.
When the scroll comes off the bottom again, we remove the class from conversation
Hope this helps.
https://jsfiddle.net/cnvzLfso/5/
var doScollCheck = true;
var objConv = document.querySelector('.conversation');
var objMessages = document.querySelector('.messages');
var objInput = document.querySelector('.text-input');
function scrollTo(element, to, duration) {
if (duration <= 0) {
doScollCheck = true;
return;
}
var difference = to - element.scrollTop;
var perTick = difference / duration * 10;
setTimeout(function() {
element.scrollTop = element.scrollTop + perTick;
if (element.scrollTop === to) {
doScollCheck = true;
return;
}
scrollTo(element, to, duration - 10);
}, 10);
}
function resizeInput(atBottom) {
var className = 'bigger',
hasClass;
if (objConv.classList) {
hasClass = objConv.classList.contains(className);
} else {
hasClass = new RegExp('(^| )' + className + '( |$)', 'gi').test(objConv.className);
}
if (atBottom) {
if (!hasClass) {
doScollCheck = false;
if (objConv.classList) {
objConv.classList.add(className);
} else {
objConv.className += ' ' + className;
}
scrollTo(objMessages, (objMessages.scrollHeight - objMessages.offsetHeight) + 50, 500);
}
} else {
if (hasClass) {
if (objConv.classList) {
objConv.classList.remove(className);
} else {
objConv.className = objConv.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
}
}
}
}
objMessages.addEventListener('scroll', function() {
if (doScollCheck) {
var isBottom = ((this.scrollHeight - this.offsetHeight) === this.scrollTop);
resizeInput(isBottom);
}
});
html,
body {
height: 100%;
width: 100%;
background: white;
}
body {
margin: 0;
padding: 0;
}
.conversation {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
position: relative;
}
.messages {
overflow-y: scroll;
padding: 10px 10px 60px 10px;
-webkit-transition: padding .5s;
-moz-transition: padding .5s;
transition: padding .5s;
}
.text-input {
padding: 10px;
-webkit-transition: height .5s;
-moz-transition: height .5s;
transition: height .5s;
position: absolute;
bottom: 0;
height: 50px;
background: white;
}
.conversation.bigger .messages {
padding-bottom: 110px;
}
.conversation.bigger .text-input {
height: 100px;
}
.text-input input {
height: 100%;
}
<div class="conversation">
<div class="messages">
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is the last message
</p>
<div class="text-input">
<input type="text" />
</div>
</div>
</div>
You write;
Now, consider this case:
The user scrolls to the bottom of the conversation
The .text-input, dynamically gets bigger
Wouldn't the method that dynamically sets the .text-input be the logical place to fire this.props.onResize().
To whom it may concern,
The answers above did not suffice my question.
The solution I found was to make my innerWidth and innerHeight variable constant - as the innerWidth of the browser changes on scroll to adapt for the scrollbar.
var innerWidth = window.innerWidth
var innerHeight = window.innerHeight
OR FOR REACT
this.setState({width: window.innerWidth, height: window.innerHeight})
In other words, to ignore it, you must make everything constant as if it were never scrolling. Do remember to update these on Resize / Orientation Change !
IMHO current answer is not a correct one:
1/ flex-direction: column-reverse; reverses the order of messages - I didn't want that.
2/ javascript there is also a bit hacky and obsolete
If you want to make it like a PRO use spacer-box which has properties:
flex-grow: 1;
flex-basis: 0;
and is located above messages. It pushes them down to the chat input.
When user is typing new messages and input height is growing the scrollbar moves up, but when the message is sent (input is cleared) scrollbar is back at bottom.
Check my snippet:
body {
background: #ccc;
}
.chat {
display: flex;
flex-direction: column;
width: 300px;
max-height: 300px;
max-width: 90%;
background: #fff;
}
.spacer-box {
flex-basis: 0;
flex-grow: 1;
}
.messages {
display: flex;
flex-direction: column;
overflow-y: auto;
flex-grow: 1;
padding: 24px 24px 4px;
}
.footer {
padding: 4px 24px 24px;
}
#chat-input {
width: 100%;
max-height: 100px;
overflow-y: auto;
border: 1px solid pink;
outline: none;
user-select: text;
white-space: pre-wrap;
overflow-wrap: break-word;
}
<div class="chat">
<div class="messages">
<div class="spacer-box"></div>
<div class="message">1</div>
<div class="message">2</div>
<div class="message">3</div>
<div class="message">4</div>
<div class="message">5</div>
<div class="message">6</div>
<div class="message">7</div>
<div class="message">8</div>
<div class="message">9</div>
<div class="message">10</div>
<div class="message">11</div>
<div class="message">12</div>
<div class="message">13</div>
<div class="message">14</div>
<div class="message">15</div>
<div class="message">16</div>
<div class="message">17</div>
<div class="message">18</div>
</div>
<div class="footer">
<div contenteditable role="textbox" id="chat-input"></div>
</div>
<div>
Hope I could help :)
Cheers

How to have a clickable text box appear over an image on hover

I have an image inside of a DIV. When a user hovers over the image I would like a white box with 65% opacity to come up from the bottom of the image that would only cover a about 30% of the bottom of the image. In that box would be text that say something like "+ Order Sample" and when the user clicks on that box it would be added to the cart.
Easy enough to handle the adding to cart part it's the css and possibly javascript necessary to make this happen that I'm struggling with. Can someone get me started? Here's what I have so far. This includes edits from first answer.
foreach($array as $key => $value) {
$imgsrc = $value['option_value']. ".jpg" ;
$option_name = $value['option_name'] ;
$fullname = $value['quality'] . " " . $value['color'] ;
$cbpg = $value['cbpg'] ;
$space = $value['space'] ;
print "<div class='colorbook-color-guide-div' onmouseover='showOrderSample();'>" ;
print "<img class='colorbook-color-guide-image js-color-option js-tooltip' nopin='nopin' data-tooltip-content='$option_name' src='/images/uploads/colors/$imgsrc' alt='$option_name' >" ;
print "<div id='orderSample' onclick='hideOrderSample();alert(\"order sample\");' ><b>+ Order Sample</b></div>" ;
print "<p class='colorbook-color-subtitle'>$fullname</p>" ;
//print "<p class='colorbook-color-subtitle'>$cbpg $space</p>" ;
print "</div>" ;
}
And here's the CSS I have.
.colorbook-color-guide-div {
width: 176px;
min-height: 107px;
margin-bottom: 2px;
margin-right: 21px;
cursor: pointer;
float:left;
text-align:center;
}
.colorbook-color-guide-image {
width: 176px;
min-height: 86px;
}
.colorbook-color-subtitle {
font-family: HelveticaNeueLT-Light, Museo-500, Helvetica, Arial, sans-serif;
font-style: normal ;
font-weight:600 ;
font-size: 13px ;
font-size: 1.3rem ;
color: #929496 ;
margin-top: -3px;
}
#orderSample {
height:0px;
top:100px;
width:176px;
display:block;
overflow:hidden;
background:white;
opacity:.65;
}
And the JavaScript
function showOrderSample() {
var element = document.getElementById("orderSample");
element.style.height = "30px";
element.style.top = "70px";
}
function hideOrderSample() {
setTimeout(function () {
document.getElementById("orderSample").style.height = "0px";
}, 500);
}
My example uses just JavaScript, html and fixed sizes but it does what was asked for.
Look at the Fiddle here:
https://jsfiddle.net/ag7to93q/9/
<script>
function showOrderSample(element) {
element.children[1].style.height = "30px"; // access the second child of the div element
element.children[1].style.top = "70px";
}
function hideOrderSample(element, event) {
if (event && event.target.classList.contains("hoverDiv")) {
alert("buy buy buy!");
setTimeout(function () {
element.children[1].style.height = "0px";
}, 200);
}
else {
// do something here
}
}
</script>
<div style="position:absolute;top:50px;left:50px;width:200px;height:100px;background:green;" onmouseenter="showOrderSample(this);" onclick="hideOrderSample(this, event);" onmouseleave="hideOrderSample(this, event);" >
<img style="position:absolute;height:100px;width:200px;" src="https://jsfiddle.net/img/logo.png" ></img>
<div id="orderSample" class="hoverDiv" style="position:absolute;height:0px;top:100px;width:200px;display:block;overflow:hidden;background:white;opacity:.65;"><b>+ Order Sample<b>
</div>
</div>
Look at the following jsFiddle. Keep in mind accurate answers require more detail, so based on your question I came up with an approximate (hopefully as accurate as possible) response. Let me know if it helped in getting you closer to where you want to be, we can work on something closer if needed.
HTML:
<div class="popup-overlay--gray">a</div>
<a class="popup-btn__open" href="#">Open Popup</a>
<div>
<a class="popup-btn__close" href="#">Close Popup</a>
<img class="popup" src="http://placehold.it/300x300"/>
</div>
CSS
[class*="popup-btn"] { text-decoration: none; color: white; background-color: gray; }
.popup-btn__close { top: 0; right: 0; }
.popup { display: none; }
.popup-overlay--gray { position: absolute: width: 100%; height: 100%; background-color: #333; opacity: 0.7; z-index: 1000; }
jQuery 2.1.3
var timer,
delay = 500;
$(".show-popup").hover(function(){
// on mouse in, start a timeout
timer = setTimeout(function(){
// showing the popup
$('.popup').fadeIn(500);
}, delay);
}, function() {
// on mouse out, cancel the timer
clearTimeout(timer);
});
Fiddle
Jquery solution
$('document').ready(function () {
$('#myimage').hover(
//hover in
function () {
$("#backgroundDIv").css('z-index', 101);
},
//hover out
function () {
$("#backgroundDIv").css('z-index', 99);
});
});
HTML
<div id="mainDiv">
<img id="myimage" src="http://i48.fastpic.ru/big/2013/0606/5c/aa5f8d03b34f8e79f18c07343573bc5c.jpg" />
<input type="text" value="add me" id="backgroundDIv"/>
</div>
CSS
#myimage {
z-index:100;
position: absolute;
}
#backgroundDIv {
z-index=99;
position: absolute;
top:200px;
background-color:#fff200;
opacity:0.4;
}

Mobile slider only responding every other touch

I am trying to build a slider based upon http://css-tricks.com/the-javascript-behind-touch-friendly-sliders/. My goal is to make a horizontal, mobile-only slider that allows you to slide back and forth between the steps in a registration process.
The code works for the most part, but the slider only moves every other touch, and I'm not sure why.
http://codepen.io/anon/pen/zKhao
HTML:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<div class="visible-xs mobile-tabs">
<div class="slider-wrap">
<div class="slider" id="slider">
<div class="holder">
<div class="slide-wrapper">
<h4 class="complete">Before you begin</h4>
</div>
<div class="slide-wrapper">
<h4 class="complete">1. Terms & Conditions</h4>
</div>
<div class="slide-wrapper">
<h4 class="current">2. Teams</h4>
</div>
<div class="slide-wrapper">
<h4>3. Add-Ons</h4>
</div>
<div class="slide-wrapper">
<h4>4. Review & Submit</h4>
</div>
</div>
</div>
</div>
</div>
CSS:
a
{
color: #5fa4db;
text-decoration: none;
}
.mobile-tabs
{
height: 45px;
overflow: hidden;
border-bottom: 1px solid #f1f2f4;
white-space: nowrap;
margin-bottom: 10px;
}
.mobile-tabs h4
{
color: #9fa9b2;
display: inline-block;
padding-right: 10px;
padding-bottom: 10px;
font-weight: bold;
font-size: 18px;
}
.mobile-tabs h4.current
{
border-bottom: 5px solid #5fa4db;
color: #0f2034;
}
.mobile-tabs h4.complete
{
color: #5fa4db;
}
/* CSS for mobile tab slider.
Source: http://css-tricks.com/the-javascript-behind-touch-friendly-sliders/
*/
.mobile-tabs .animate {
transition: transform 0.3s ease-out;
}
.mobile-tabs .slider-wrap {
width: 100%;
position: absolute;
}
.mobile-tabs .slider {
width: 100%;
height: 100%;
overflow: hidden;
}
.mobile-tabs .ms-touch.slider {
overflow-x: scroll;
overflow-y: hidden;
-ms-overflow-style: none;
/* Hides the scrollbar. */
-ms-scroll-chaining: none;
/* Prevents Metro from swiping to the next tab or app. */
-ms-scroll-snap-type: mandatory;
/* Forces a snap scroll behavior on your images. */
-ms-scroll-snap-points-x: snapInterval(0%, 1%);
/* Defines the y and x intervals to snap to when scrolling. */
}
.mobile-tabs .holder {
width: 300%;
overflow-y: hidden;
}
.mobile-tabs .slide-wrapper {
float: left;
position: relative;
overflow: hidden;
}
.mobile-tabs .slide div {
width: 300px;
height: 500px;
z-index: 0;
}
JavaScript:
if (navigator.msMaxTouchPoints) {
$('#slider').addClass('ms-touch');
$('#slider').on('scroll', function () {
$('.slide-image').css('transform', 'translate3d(-' + (100 - $(this).scrollLeft() / 6) + 'px,0,0)');
});
} else {
var slider = {
el: {
slider: $("#slider"),
holder: $(".holder")
},
slideWidth: $('#slider').width(),
touchstartx: undefined,
touchmovex: undefined,
movex: 0,
index: 0,
longTouch: undefined,
init: function () {
this.bindUIEvents();
},
bindUIEvents: function () {
this.el.holder.on("touchstart", function (event) {
slider.start(event);
});
this.el.holder.on("touchmove", function (event) {
slider.move(event);
});
this.el.holder.on("touchend", function (event) {
slider.end(event);
});
},
start: function (event) {
// Test for flick.
this.longTouch = false;
setTimeout(function () {
window.slider.longTouch = true;
}, 250);
// Get the original touch position.
this.oldx = this.movex;
// The movement gets all janky if there's a transition on the elements.
$('.animate').removeClass('animate');
},
move: function (event) {
// Continuously return touch position.
this.touchmovex = event.originalEvent.touches[0].pageX;
// Calculate distance to translate holder.
this.movex = -this.oldx - this.touchmovex;
// Defines the speed the images should move at.
var panx = 100 - this.movex / 6;
if (this.movex < 600) { // Makes the holder stop moving when there is no more content.
this.el.holder.css('transform', 'translate3d(-' + this.movex + 'px,0,0)');
}
},
end: function (event) {
}
};
slider.init();
}
In order to emulate the issue, you'll have to view the code on a mobile device (or use Chrome's mobile emulation) and try to slide the slider back and forth. It will move, but only every other time you attempt to slide it.
I am completely lost, and any help will be appreciated.
This isn't really an answer, per se, but I've decided to throw the entire thing out and use jquery UI's Draggable feature to do what I need to do.
http://jqueryui.com/draggable/#constrain-movement

Categories