I am trying to make a span within a button clickable. The span has a .png image within it. It will only act as a button when I click around the actual image, but not when I click on the image itself. I cant find any solutions that directly relates to my issue.
HTML
<button id="btn3"><span class"btn3"></span></button>
CSS
span.btn3 {
background: url("./images/raincloud.png") no-repeat top left;
background-size: contain;
cursor: pointer;
display: inline-block;
height: 80px;
width: 80px;
}
Edit:
Here is the JS function. It is meant to change the audio/video file when a certain button is clicked.
[].forEach.call(document.getElementsByClassName('btn'),
function(btn) {
btn.addEventListener('click', function(e) {
switch (e.target.id) {
case "btn3":
video.src = "./video/rain2.mp4";
video.play();
break;
case "btn4":
video.src = "./video/rain1.mp4";
video.play();
break;
case "btn5":
audio.src = "./audio/rain.mp4";
audio.play();
break;
case "btn6":
audio.src = "./audio/rain2.mp4";
audio.play();
break;
}
})
})
Missing =in class="btn3"
You want the ID of the parent of the target
your forEach is not very convincing. I delegate instead from the nearest container
const audio = document.getElementById("audio");
const video = document.getElementById("video");
document.getElementById("container").addEventListener("click", function(e) {
var tgt = e.target;
if (tgt.tagName == "SPAN") {
var id = tgt.closest("button").id;
console.log(id)
switch (id) {
case "btn3":
video.src = "./video/rain2.mp4";
video.play();
break;
case "btn4":
video.src = "./video/rain1.mp4";
video.play();
break;
case "btn5":
audio.src = "./audio/rain.mp4";
audio.play();
break;
case "btn6":
audio.src = "./audio/rain2.mp4";
audio.play();
break;
}
}
})
span.btn3 {
background: url(https://img.icons8.com/cotton/2x/cloud.png) no-repeat top left;
background-size: contain;
cursor: pointer;
display: inline-block;
height: 80px;
width: 80px;
}
<div id="container">
<button id="btn3"><span class="btn3"></span></button>
<button id="btn3"><span class="btn3"></span></button>
<button id="btn4"><span class="btn3"></span></button>
<button id="btn5"><span class="btn3"></span></button>
</div>
<audio id="audio" />
<video id="video" />
Add the onClick property via JavaScript to the span element (https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onclick)
HTML
<button id="btn3"><span class="btn3" id="span_in_button"></span></button>
JavaScript
document.getElementById('span_in_button').onclick = function changeContent() {
// Your functionality here.
}
or by https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event
or add onclick property directly into the HTML span element https://www.w3schools.com/TAgs/att_onclick.asp
in HTML body:
<button id="btn3"><span class="btn3" onclick="myFunction()"></span></button>
in HTML head:
<script>
function myFunction() {
// Your functionality here.
}
</script>
Related
In the very initial state, I need to click on Read More button TWICE to have the content below show. Weird - how do i fix this problem? I only want to click on Read More button once to show the content underneath it.
function myFunction() {
var x = document.getElementById("myDIV");
var btnText = document.getElementById("myBtn");
if (x.style.display === "none") {
x.style.display = "block";
btnText.innerHTML = "Read less";
} else {
x.style.display = "none";
btnText.innerHTML = "Read More";
}
}
#myDIV {
display: none;
width: 100%;
padding: 50px 0;
text-align: center;
background-color: lightblue;
margin-top: 20px;
}
<p>Click the "Try it" button to toggle between hiding and showing the DIV element:</p>
<div id="myDIV">
This is my DIV element.
</div>
<button onclick="myFunction()" id="myBtn">Read More</button>
<p><b>Note:</b> The element will not take up any space when the display property set to "none".</p>
You should include a check if myDiv's display style is empty.
function myFunction() {
var x = document.getElementById("myDIV");
var btnText = document.getElementById("myBtn");
if (x.style.display === "none" || x.style.display === "") { // notice this line
x.style.display = "block";
btnText.innerHTML = "Read less";
} else {
x.style.display = "none";
btnText.innerHTML = "Read More";
}
}
#myDIV {
display: none;
width: 100%;
padding: 50px 0;
text-align: center;
background-color: lightblue;
margin-top: 20px;
}
<p>
Click the "Try it" button to toggle between hiding and showing the DIV element:
</p>
<div id="myDIV">
This is my DIV element.
</div>
<button onclick="myFunction()" id="myBtn">Read More</button>
<p>
<b>Note:</b> The element will not take up any space when the display property set to "none".
</p>
The reason it's working on two clicks is that the DOM is ready but the script does not knows that the div's style is display: none.
There are two ways you can fix this:
Using window.getComputedStyle()
The Window.getComputedStyle() method returns an object containing the values of all CSS properties of an element, after applying active stylesheets and resolving any basic computation those values may contain.
This way it will ensure that content will show in one click.
Demo:
function myFunction() {
var x = document.getElementById("myDIV");
var displayDiv = window.getComputedStyle(x).display; //this function
var btnText = document.getElementById("myBtn");
if (displayDiv === "none") {
x.style.display = "block";
btnText.innerHTML = "Read less";
} else {
x.style.display = "none";
btnText.innerHTML = "Read More";
}
}
#myDIV {
display: none;
width: 100%;
padding: 50px 0;
text-align: center;
background-color: lightblue;
margin-top: 20px;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
</style>
</head>
<body>
<p>Click the "Try it" button to toggle between hiding and showing the DIV element:</p>
<div id="myDIV">
This is my DIV element.
</div>
<button onclick="myFunction()" id="myBtn">Read More</button>
<p><b>Note:</b> The element will not take up any space when the display property set to "none".</p>
</body>
</html>
Using Inline styling on the div
You could simply set the display to inline style as display:none.
This way it will ensure that content will show in one click.
Demo:
function myFunction() {
var x = document.getElementById("myDIV");
var btnText = document.getElementById("myBtn");
if (x.style.display === "none") {
x.style.display = "block";
btnText.innerHTML = "Read less";
} else {
x.style.display = "none";
btnText.innerHTML = "Read More";
}
}
#myDIV {
width: 100%;
padding: 50px 0;
text-align: center;
background-color: lightblue;
margin-top: 20px;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
</style>
</head>
<body>
<p>Click the "Try it" button to toggle between hiding and showing the DIV element:</p>
<div id="myDIV" style="display: none;">
This is my DIV element.
</div>
<button onclick="myFunction()" id="myBtn">Read More</button>
<p><b>Note:</b> The element will not take up any space when the display property set to "none".</p>
</body>
</html>
This code will turn the bulb on/off but i want to make the lightbulbs keeps flashing. I've tried different methods and nothing works
<!DOCTYPE html>
<html>
<body>
<img id="bulb" onclick="switch()" src="off.png" width="100" height="180">
<p>On/Off</p>
<script>
function
switch () {
var image = document.getElementById('Bulb');
if (image.src.match("on")) {
image.src = "off.png";
} else {
image.src = "on.png";
}
}
</script>
</body>
</html>
Here is an example, using setInterval(). I have swapped the image to a div thats background changes color, but same principal applies.
I think its also worth pointing out that you could also do this with a css animation and then just use javascript to toggle the class onto the element. But assuming you just wanna stick to JS for now:
let flashInterval = null;
let flashSpeed = 100;
let bulb = document.getElementById('bulb');
function toggleBulb() {
if (bulb.classList.contains('on')) {
bulb.classList.remove('on');
} else {
bulb.classList.add('on');
}
}
function flashBulb() {
if (flashInterval === null) {
flashInterval = setInterval(() => {
toggleBulb();
}, flashSpeed);
} else {
clearInterval(flashInterval);
flashInterval = null;
}
}
document.getElementById('toggleBlub').addEventListener('click', toggleBulb);
document.getElementById('toggleFlash').addEventListener('click', flashBulb);
#bulb {
width: 50px;
height: 50px;
border-radius: 50%;
border: 1px solid #ccc;
background: transparent:
}
.on {
background: #fcba03;
}
<div id="bulb" class=""></div>
<br>
<button id="toggleBlub">Bulb On/Off</button>
<br><br>
<button id="toggleFlash">Flash On/Off</button>
in my opinion, don't use setInterval but u can use a CSS animation rather than it.
You should know about js event and js reserve keyword and be sure to use good code editor so that you can see your error.
I see you trying to keep flashing but you used onclick event that is clickable it will not flashing.
here is the code below, which you want,
<!DOCTYPE html>
<html>
<body>
<img id="bulb" src="off.jpg" width="100" height="180">
<p>On/Off</p>
<script>
var myImage = document.querySelector('#bulb');
var update = setInterval(myUpdate, 1000);
function myUpdate() {
setTimeout(() => {
if (myImage.src.match('off.jpg')) {
myImage.src = 'on.jpg'
} else {
myImage.src = 'off.jpg'
}
}, 500)
}
</script>
</body>
</html>
or you can use onclick event, when you click than it will start flashing
here is the code below
<!DOCTYPE html>
<html>
<body>
<img id="bulb" onclick="mySwitch(this)" src="off.jpg" width="100" height="180">
<p>On/Off</p>
<script>
function mySwitch(myImage) {
var update = setInterval(myUpdate, 500);
function myUpdate() {
setTimeout(() => {
if (myImage.src.match('off.jpg')) {
myImage.src = 'on.JPG'
} else {
myImage.src = 'off.jpg'
}
}, 100)
console.log(myImage)
}
}
</script>
</body>
</html>
I changed your function name to switchBulb because switch is reserved
var intervalID = window.setInterval(switchBulb, 1000);
function switchBulb() {
var image = document.getElementById('bulb');
if (image.src.match("on")) {
image.src = "off.png";
} else {
image.src = "on.png";
}
}
Firefox will not load images with display: none until they are required to be shown to the user. Chromium will stall until the image is loaded, and then display it.
With smaller file sizes, there is a brief flash if the image is not already loaded on Firefox. With larger file sizes, there is a much longer delay that will also make Chromium's stall noticeable.
I would like to have images with display: none preloaded so there is no delay when displaying them.
I have tried using Javascript to declare a new Image object, but this does not work with Firefox or Chromium.
You can cycle between images in this example with the right and left arrow keys.
<!DOCTYPE html>
<html>
<head>
<style>
body, html {
height: 100%;
margin: 0;
padding: 0;
}
.imgs {
width:50%;
height: 50%;
}
</style>
</head>
<body>
<img src="https://picsum.photos/200/100" style="display: block;" class="imgs">
<img src="https://picsum.photos/200/200" style="display: none;" class="imgs">
<script>
imgs = document.getElementsByClassName("imgs");
// THIS DOES NOT WORK
//~ function preloadImage(url)
//~ {
//~ var img = new Image();
//~ img.src = url;
//~ }
//preloadImage("myImg.jpg"); THIS DOES NOT WORK
document.onkeydown = checkKey; // directional keys
function checkKey(e) {
if (document.activeElement.tagName != "INPUT") {
e = e || window.event;
switch (e.keyCode) {
case 38:
// up arrow
break;
case 40:
// down arrow
break;
case 37:
// left arrow
imgs[0].style.display = "block";
imgs[1].style.display = "none";
break;
case 39:
// right arrow
imgs[0].style.display = "none";
imgs[1].style.display = "block";
break;
}
}
}
</script>
</body>
</html>
I have figured out my own solution to this problem.
I use a class called "imgBuffer" to hold images that need to be displayed immediately. Images of this class will hold the source of images that need to be readily displayed, but will not display the images themselves.
The tricky part is making sure the hidden images are in a location on screen that does not affect the layout in any way.
Notice the width and height of the hidden buffered image matches that of the displayed images. If you adjust the dimensions of the hidden image, the page may behave differently such as adding a scrollbar when it's not really necessary.
<!DOCTYPE html>
<html>
<head>
<style>
body, html {
height: 100%;
margin: 0;
padding: 0;
}
.imgs {
width:50%;
height: 50%;
}
.imgBuffer {
position: absolute;
height: 50%;
width: 50%;
visibility: hidden;
z-index: -1;
}
</style>
</head>
<body>
<img src="https://picsum.photos/200/100" style="display: block;" class="imgs">
<img src="https://picsum.photos/200/200" style="display: none;" class="imgs">
<img src="https://picsum.photos/200/100" class="imgBuffer">
<img src="https://picsum.photos/200/200" class="imgBuffer">
<script>
imgs = document.getElementsByClassName("imgs");
// THIS DOES NOT WORK
//~ function preloadImage(url)
//~ {
//~ var img = new Image();
//~ img.src = url;
//~ }
//preloadImage("myImg.jpg"); THIS DOES NOT WORK
document.onkeydown = checkKey; // directional keys
function checkKey(e) {
if (document.activeElement.tagName != "INPUT") {
e = e || window.event;
switch (e.keyCode) {
case 38:
// up arrow
break;
case 40:
// down arrow
break;
case 37:
// left arrow
imgs[0].style.display = "block";
imgs[1].style.display = "none";
break;
case 39:
// right arrow
imgs[0].style.display = "none";
imgs[1].style.display = "block";
break;
}
}
}
</script>
</body>
</html>
I have a modal where I want to print the full contents of it. I don't want anything else printed aside what is within the modal.
Here I created the button within the modal:
This should not be printed...
<button id="btnPrint">Print (this btn should not be printed!)</button>
<hr />
<div id="printThis">
This should BE printed!
</div>
<div id="printThisToo">
This should BE printed, too!
</div>
I have some text next to the button, but this text should not show when you click the button to preview the print view.
Here I wrote some js to show what content should be printed:
document.getElementById("btnPrint").onclick = function() {
printElement(document.getElementById("printThis"));
printElement(document.getElementById("printThisToo"), true, "<hr />");
window.print();
}
function printElement(elem, append, delimiter) {
var domClone = elem.cloneNode(true);
var $printSection = document.getElementById("printSection");
if (!$printSection) {
var $printSection = document.createElement("div");
$printSection.id = "printSection";
document.body.appendChild($printSection);
}
if (append !== true) {
$printSection.innerHTML = "";
}
else if (append === true) {
if (typeof(delimiter) === "string") {
$printSection.innerHTML += delimiter;
}
else if (typeof(delimiter) === "object") {
$printSection.appendChlid(delimiter);
}
}
$printSection.appendChild(domClone);
}
Finally, I wrote some css:
#media screen {
#printSection {
display: none;
}
}
#media print {
body {
font-family: 'Open Sans', sans-serif;
font-size: 12px;
font-weight: 500;
color: #101010;
background: #f6f5fa;
visibility:hidden;
}
#printSection, #printSection {
visibility:visible;
}
#printSection {
position:absolute;
left:0;
top:0;
}
}
When I click the button in the modal, nothing happens and no errors appear in the console. Not sure what the issue is. Any help would be much appreciated.
UPDATED CODE:
(HTML)
<div>
This should not be printed...
<button ng-click="printPreview()">Print (this btn should not be printed!)</button>
</div>
<hr />
<div id="printThis">
This should BE printed!
</div>
(JS)
var app = angular.module('dmdesktop');
app.controller('PrintViewCtrl', rollUpCtrl);
rollUpCtrl.$inject = ['$scope', '$rootScope', '$http', '$uibModal','headersvc','locFiltersvc']
function rollUpCtrl($scope, $rootScope, $http, $uibModal, headersvc, locFiltersvc) {
$scope.printPreview = function() {
printElement(document.getElementById("printThis"));
}
function printElement(elem) {
alert ("printing!");
var domClone = elem.cloneNode(true);
var $printSection = document.getElementById("printSection");
if (!$printSection) {
var $printSection = document.createElement("div");
$printSection.id = "printSection";
document.body.appendChild($printSection);
}
$printSection.innerHTML = "";
$printSection.appendChild(domClone);
window.print();
}
}
(CSS)
same as before
With the updated code and window.print inside a evalAsync function allows you to print the content inside a modal
$scope.$evalAsync(function () {
window.print();
});
I have this code for making a nav bar. I am trying to add image buttons with text below them. The problem is that the images can be of different sizes and thus they are not centered properly in the output.
Also, the title for all images must come at same level but its not the case.
ul.nav-icon {
list-style: none;
display: block;
margin: auto;
width: 800px;
}
ul.nav-icon li {
float: left;
}
ul.nav-icon a {
display: inline-block;
text-decoration: none;
}
ul.nav-icon a:hover {
background: #4095A6;
}
ul.nav-icon img {
margin: 0px 0px 0px 0px;
padding-top: 16px;
padding-left: 30px;
}
.img-box {
width: 160px;
height: 138px;
}
h6 {
color: white;
text-align: center;
}
<ul class="nav-icon">
<li>
<a href="#" class="img-box">
<img src="http://imgur.com/Et4vXHk.png">
<h6>Families</h6>
</a>
</li>
<li>
<a href="#" class="img-box">
<img src="http://i.imgur.com/lubEbTP.png">
<h6>Families</h6>
</a>
</li>
<li>
<a href="#" class="img-box">
<img src="http://i.imgur.com/lubEbTP.png">
<h6>Families</h6>
</a>
</li>
</ul>
Here's a way to deal with your problem: https://github.com/smohadjer/sameHeight
Here's the .js file you'll need to include in your html. It's better if it's an external file. For any confusion, this file can also be found in the link above with both minified/unminified versions.
;(function ($, window, document, undefined) {
'use strict';
var pluginName = 'sameHeight',
defaults = {
oneHeightForAll: false,
useCSSHeight: false
};
//private method
var getHeightOfTallest = function(elms) {
var height = 0;
$.each(elms, function() {
var _h = $(this).outerHeight();
if (_h > height) {
height = _h;
}
});
return height;
};
// The actual plugin constructor
function Plugin(element, options) {
this.$element = $(element);
this.options = $.extend({}, defaults, options);
this.init();
}
// methods
var methods = {
init: function() {
var self = this;
self.index = 0;
self.$elms = self.$element.children();
self.cssProperty = self.options.useCSSHeight ? 'height' : 'min-height';
$(window).on('resize.' + pluginName, function() {
//remove previously set height or min-height
self.$elms.css(self.cssProperty, '');
initSameHeight();
});
//use setTimeout to make sure any code in stack is executed before
//calculating height
setTimeout(function() {
initSameHeight();
}, 0);
function initSameHeight() {
//if there are adjacent elements
if (self.getRow(0).length > 1) {
self.setMinHeight(0);
if (self.options.callback) {
self.options.callback();
}
}
}
},
setMinHeight: function(index){
var self = this;
var row = self.options.oneHeightForAll ? self.$elms : self.getRow(index);
var height = getHeightOfTallest(row);
$.each(row, function() {
$(this).css(self.cssProperty, height);
});
if (!self.options.oneHeightForAll && self.index < self.$elms.length - 1) {
self.setMinHeight(self.index);
}
},
getRow: function(index) {
var self = this;
var row = [];
var $first = self.$elms.eq(index);
var top = $first.position().top;
row.push($first);
self.$elms.slice(index + 1).each(function() {
var $elm = $(this);
if ($elm.position().top === top) {
row.push($elm);
self.index = $elm.index();
} else {
self.index = $elm.index();
return false;
}
});
return row;
},
destroy: function() {
var self = this;
//remove event handlers
$(window).off('resize.' + pluginName);
//remove dom changes
self.$elms.css(self.cssProperty, '');
self.$element.removeData('plugin_' + pluginName);
}
};
// build
$.extend(Plugin.prototype, methods);
// A really lightweight plugin wrapper around the constructor,
// preventing against multiple instantiations
$.fn[pluginName] = function(options) {
this.each(function() {
if(!$.data(this, 'plugin_' + pluginName)) {
$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
}
});
return this;
};
})(jQuery, window, document);
After you include the above .js file, add this script to your current page:
$('.img-box').sameHeight();
This should make all of your boxes with image/text be the same size height wise.
Next in order to make sure the text is always at a certain point within your img-box, add some css inline, or make a class with the css as
h6 {
bottom:10px;
}
The amount of pixels can be anything you'd like it to be. To explain, the text will now always be 10 pixels from the bottom of the img-box.
Either this, or just make the images the background image for the container and set them all to predetermined sizes.