How can I make the area around a button also clickable? [duplicate] - html

This question already has answers here:
Increasing clickable area of a button
(4 answers)
How to increase the clickable area of a <a> tag button?
(13 answers)
Closed 3 months ago.
If the mouse is about 20px close to the button, I want that the button should be clickable. I tried increasing the width of the button by 20px and making the opacity 0.1 so the big size won't show. Then in the button:hover rule I made the opacity 1.
I did the above cause I don't really know how go about it.

Using vanilla js:
document.getElementById("my-button").onclick = function (e) {
e.stopPropagation();
window.alert("here we go");
};
button {
margin: 20px;
cursor: pointer;
}
div {
cursor: pointer;
background: gray;
width: fit-content;
}
body {
background: gray;
}
<div onclick="document.getElementById('my-button').click()">
<button id="my-button">Button</button>
</div>

$(function() {
var $win = $(window); // or $box parent container
var $box = $(".box");
var $log = $(".log");
$win.on("click.Bst", function(event) {
if (
$box.has(event.target).length == 0 //checks if descendants of $box was clicked
&&
!$box.is(event.target) //checks if the $box itself was clicked
) {
$log.text("you clicked outside the box");
} else {
$log.text("you clicked inside the box");
}
});
});
body,
div,
p {
margin: 0;
padding: 0;
}
body {
background-color: #d6d6d6;
}
.log {
position: relative;
top: 10px;
left: 10px;
color: #000;
}
.box {
position: relative;
top: 50px;
left: 100px;
width: 100px;
height: 100px;
font-size: 18px;
text-align: center;
color: white;
background-color: #79abff;
}
.box p {
color: black;
}
<p class="log">You clicked on: </p>
<div class="box">
Click me
<p>nested p</p>
</div>

Related

How to show different values inside different Modals in HTML

I just want to share my code here where I got the Idea on W3schools. I already search of the same topic, but it didn't solve the problem of my Code.
/* The Modal (background) MY CSS CODE*/
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* The Modal1 (background) */
.modal1 {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
And heres the Javascript Code
<!-- Javascript -->
<script>
// Get the modal
var modal = document.getElementByclass("myModal");
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks the button, open the modal
btn.onclick = function() {
modal.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
</script>
<script>
// Get the modal1
var modal = document.getElementByIclass("myModal1");
// Get the button that opens the modal
var btn = document.getElementById("myBtn1");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close1")[0];
// When the user clicks the button, open the modal
btn.onclick = function() {
modal.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
</script>
And Lastly, the HTML Code
<!-- Trigger/Open The Modal -->
<button id="myBtn">Apply Now</button>
<!-- The Modal -->
<div class="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<p>Some text in the Modal..</p>
</div>
</div>
<!-- Trigger/Open The Modal1 -->
<button id="myBtn1">Apply Now</button>
<!-- The Modal -->
<div class="myModal1" class="modal1">
<!-- Modal content -->
<div class="modal-content">
<span class="close1">×</span>
<p>Some text in the Modalsssssss..</p>
</div>
</div>
I've been kinda stuck with this for a long time. Any opinion or suggestions will be greatly appreciated.
**** UPDATE**
Read your comment and I agree, this is pretty "hacky" and I personally would almost never do this. So I want to show you a solution which is closer to what I would do on a production site. A quick overview:
The code for the actual modal is good, so we can use that.
What I think is "hacky" here is the way we get the data to feed to the modal. Storing data in HTML elements is not terrible, but there are way better ways to do this.
A good way to store this kind of data (strings, numbers, etc.) is with JSON.
We can include the JSON data in the document itself, or we can use AJAX to store it in a different location. Could be a file on the server, or maybe a database somewhere.
More info on $.getJSON() method.
/* Same code from previous example. New code marked with comments */
$("body").on("click", ".toggle-modal", function() {
if ($(".modal").is(":visible")) {
$(".modal").fadeOut("fast", function() {
$(this).remove()
});
} else {
/* Get the data ID from the html element */
const data_id = $(this).data("modal-text");
/* Get JSON data from file on server (simplified)
Replace the url with the path to your JSON file on the server. */
$.getJSON("https://httpbin.org/json", function(response) { // <-- Callback function
/* This is the "callback" function from the "getJSON" method
This fires when the AJAX request has been completed
This function has access to the AJAX response variable which contains the returned data */
/* Light validation here just checks if the response is json */
if (typeof response == 'object') {
/* For kicks let's check out the response */
console.log(response);
/* The response is obviously not our data. Next variable emulates correct response */
response = {
primary_modal: "The message for the primary modal",
secondary_modal: "The message for the secondary modal"
}
/* Get the correct message from the response.
Use the value from the data attribute as the key to find our data in the json structure */
const msg = response[data_id];
/* Launch the modal */
const modal = $("<div />", {
"class": "modal"
}).append(
$("<div />", {
"class": "modal-overlay toggle-modal"
}),
$("<div />", {
"class": "modal-container"
}).append(
$("<div />", {
"class": "modal-close toggle-modal"
}),
$("<div />", {
"class": "modal-content"
}).text(msg) // <-- The message
)
).appendTo("body")
.fadeIn("fast")
.css("display", "flex");
} else {
return "Couldn't get the data";
}
});
}
})
body,
html {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
background: cyan;
display: flex;
justify-content: center;
align-items: center;
}
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9000;
padding: 20px;
}
.modal-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
background: rgba(0, 0, 0, .8);
cursor: pointer;
}
.modal-container {
background: white;
margin: auto;
position: relative;
font-size: 16px;
line-height: normal;
text-align: center;
font-weight: bold;
z-index: 20;
}
.modal-close {
position: absolute;
top: 0;
right: 0;
width: 12px;
height: 12px;
font-family: sans-serif;
font-size: 14px;
line-height: 1;
overflow: hidden;
cursor: pointer;
padding: 8px 20px;
background: coral;
color: white;
display: flex;
justify-content: center;
align-items: center;
}
.modal-close:before {
content: "X"
}
.modal-content {
padding: 35px 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- We removed the modal data and added a reference to the data in the json -->
<div>
<button class="toggle-modal" data-modal-text="primary_modal">Click Here</button>
<button class="toggle-modal" data-modal-text="secondary_modal">Click Here</button>
</div>
Here is a really easy way to re-purpose a modal template for different content using jQuery. Basically you store the message right in the button's data attribute, then just append that content to the dynamically generated modal.
/* Listen for the click event on the button */
$("body").on("click", ".toggle-modal", function() {
/* Check if modal is open */
if ($(".modal").is(":visible")) {
/* if modal is already visible close it out */
$(".modal").fadeOut("fast", function() {
$(this).remove()
});
} else {
/* Get message from button */
const msg = $(this).data("modal-text");
/* dynamically create modal elements */
const modal = $("<div />", {
"class": "modal"
}).append(
$("<div />", {
"class": "modal-overlay toggle-modal"
}),
$("<div />", {
"class": "modal-container"
}).append(
$("<div />", {
"class": "modal-close toggle-modal"
}),
$("<div />", {
"class": "modal-content"
}).text(msg) /* Append text to modal */
)
).appendTo("body") /* Append modal to body */
.fadeIn("fast") /* Fade in modal */
.css("display", "flex") /* Flexbox to center content */
}
})
body,
html {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
background: cyan;
display: flex;
justify-content: center;
align-items: center;
}
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9000;
padding: 20px;
}
.modal-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
background: rgba(0, 0, 0, .8);
cursor: pointer;
}
.modal-container {
background: white;
margin: auto;
position: relative;
font-size: 16px;
line-height: normal;
text-align: center;
font-weight: bold;
z-index: 20;
}
.modal-close {
position: absolute;
top: 0;
right: 0;
width: 12px;
height: 12px;
font-family:sans-serif;
font-size:14px;
line-height:1;
overflow: hidden;
cursor: pointer;
padding: 8px 20px;
background: coral;
color: white;
display: flex;
justify-content: center;
align-items: center;
}
.modal-close:before {
content: "X"
}
.modal-content {
padding: 35px 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Set the modal text right in the data attribute of the button. This approach works for short messages but may not be well suited for more complex content -->
<div>
<button class="toggle-modal" data-modal-text="Short message to be displayed in the first modal">Click Here</button>
<button class="toggle-modal" data-modal-text="A different message for the secondary modal">Click Here</button>
</div>

How to drag and drop same element multiple times into another div box in JavaScript or jQuery?

I have two HTML div boxes. Let's say box A and box B. I want to drag and drop box A multiple times into box B. If I drop box A outside of box B then box A will revert back to it's original position. After I dropped the box A (clone) into box B I want to move box A (clone) into any position in box B. For now I did the codes to do that.
Now what I want is after I dropped box A into Box B, then if I drag and drop box A (clone) outside of box B, then box A (clone) need to hide or revert into it's original position (box A parent position).
HTML Codes
<div id="boxB"></div>
<br>
<div class="boxA">BOX A</div>
CSS Codes
#boxB {
width: 200px;
border: 5px solid black;
padding: 50px 50px;
margin: auto;
text-align: center;
background-color: #FFFFFF;
}
.boxA {
width: 40px;
border: 2px solid black;
text-align: center;
background-color: #F5D938;
cursor: pointer;
}
JavaScript + jQuery Codes
$(document).ready(function()
{
var x;
$(".boxA").draggable(
{
helper: "clone",
cursor: "move",
revert: true
});
$("#boxB").droppable(
{
accept: ".boxA",
drop: function(event, ui)
{
x = ui.helper.clone();
ui.helper.remove();
x.appendTo('#boxB');
$(x).draggable();
}
});
});
You can see demo : https://jsfiddle.net/zajjith/3kedjgb0/10/
If I drag and drop box A (clone) outside from box B then that clone box A need to revert back to it's original parent box A position or hide or delete.
I hope you understand what I want. Please check my codes and help me.
Refer to the Example at https://jqueryui.com/droppable/#revert
Using your code, you can do the following.
$(function() {
function getBounds(el) {
var p = $(el).position();
p.right = p.left + $(el).width();
p.bottom = p.top + $(el).height();
return p;
}
function isOver(a, b) {
var ap;
if (typeof a == "object") {
ap = a;
} else {
ap = getBounds(a);
}
var bp = getBounds(b);
return (ap.left > bp.left && ap.right < bp.right) && (ap.top > bp.top && ap.bottom < bp.bottom);
}
$(".boxA").draggable({
helper: "clone",
cursor: "move",
revert: "invalid"
});
$("#boxB").droppable({
accept: ".boxA",
drop: function(event, ui) {
var cl = ui.helper.clone();
cl.appendTo(this).draggable({
appendTo: "body",
stop: function(e, ui) {
if (isOver($.extend({}, ui.position, {
right: ui.position.left + ui.helper.width(),
bottom: ui.position.top + ui.helper.height()
}), $("#boxB")) == false) {
var a = getBounds($("body > .boxA"));
ui.helper.animate({
top: a.top,
left: a.left
}, function() {
ui.helper.remove();
});
} else {
console.log("Drop Inside");
}
}
});
ui.helper.remove();
}
});
});
#boxB {
width: 200px;
border: 5px solid black;
padding: 50px 50px;
margin: auto;
text-align: center;
background-color: #FFFFFF;
}
.boxA {
width: 50px;
border: 2px solid black;
text-align: center;
background-color: #F5D938;
cursor: pointer;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="boxB"></div>
<br />
<div class="boxA">BOX A</div>

How to create a box around around controls in webprgramming

I have a few controls that I am attempting to encapsulate on my webpage. I have tried a few different methods on encapsulating my controls and they have not succeeded. I tried using a div and this did not work too well and I have also tried this post:
Create a group box around certain controls on a web form using CSS
What is happening is that a box is being created but it is at the top of my webpage instead of around the controls.
I would like to create a grey box similar to the ones found on this webpage:
https://img.labnol.org/di/trigger1.png
Below, I am attaching a copy of the CSS and HTML code that I am using in order to create my form. The form is a simple file upload form that I tweaked from an example. I am using this on my own, personal website.
Here is the HTML:
<!DOCTYPE html>
<html>
<head>
<script>
/* Script written by Adam Khoury # DevelopPHP.com */
/* Video Tutorial: http://www.youtube.com/watch?v=EraNFJiY0Eg */
function _(el){
return document.getElementById(el);
}
function uploadFile(){
var file = _("file1").files[0];
// alert(file.name+" | "+file.size+" | "+file.type);
var formdata = new FormData();
formdata.append("file1", file);
var ajax = new XMLHttpRequest();
ajax.upload.addEventListener("progress", progressHandler, false);
ajax.addEventListener("load", completeHandler, false);
ajax.addEventListener("error", errorHandler, false);
ajax.addEventListener("abort", abortHandler, false);
ajax.open("POST", "file_upload_parser.php");
ajax.send(formdata);
}
function progressHandler(event){
//_("loaded_n_total").innerHTML = "Uploaded "+event.loaded+" bytes of "+event.total;
var percent = (event.loaded / event.total) * 100;
_("progressBar").value = Math.round(percent);
_("status").innerHTML = Math.round(percent)+"% uploaded... please wait";
}
function completeHandler(event){
_("status").innerHTML = event.target.responseText;
_("progressBar").value = 0;
document.getElementById('p1').innerHTML = "Drag your file here or click in this area.";
}
function errorHandler(event){
_("status").innerHTML = "Upload Failed";
}
function abortHandler(event){
_("status").innerHTML = "Upload Aborted";
}
function changeText()
{
document.getElementById('p1').innerHTML = "1 file selected";
}
</script>
<link rel="stylesheet" href="test.css">
</head>
<body>
<h2>Upload</h2>
<fieldset>
<legend>Group 1</legend>
<form id="upload_form" enctype="multipart/form-data" method="post">
<input type="file" name="file1" id="file1"><br>
<p id="p1">Drag your file here or click in this area.</p>
<input type="button" value="Upload File" onclick="uploadFile()">
<progress id="progressBar" value="0" max="100" style="width:508px; margin-left: -4px; margin-top: 10px;"></progress>
<h3 id="status"></h3>
<p id="loaded_n_total"></p>
</form>
</fieldset>
<script>
// self executing function here
(function() {
document.getElementById('upload_form')[0].onchange = changeText;
})();
</script>
</body>
</html>
Here is the CSS (which is referred to in the html as test.css):
body{
background: rgba(0,0,0,0.0);
}
form{
position: absolute;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -250px;
width: 500px;
height: 200px;
border: 4px dashed #0D0D0D;
}
form p{
width: 100%;
height: 100%;
text-align: center;
line-height: 140px;
color: #0D0D0D;
font-family: Arial;
}
h2{
text-align: center;
}
form input[type="file"]{
position: absolute;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
outline: none;
opacity: 0;
}
form input[type="button"]{
margin: 0;
color: #fff;
background: #16a085;
border: none;
width: 508px;
height: 35px;
margin-top: -20px;
margin-left: -4px;
border-radius: 4px;
border-bottom: 4px solid #117A60;
transition: all .2s ease;
outline: none;
}
form input[type="button"]:hover{
background: #149174;
color: #0C5645;
}
form input[type="button"]:active{
border:0;
}
form progressBar{
text-align: center;
}
Coming back to the HTML, the fieldset tags are placed around the controls that I am attempting to encapsulate. I left them there so that anyone can see the main issue that I am running into.
I apologize but I am very new to web programming. Any help will be greatly appreciated, thank you.
Note: how the box is created doesn't really matter to me. I would expect that the box is created in HTML and then I can style it using CSS.
The structure of your HTML is fine, but the position: absolute properties in your CSS are clashing with the fieldset.
Since <fieldset> is wrapping all your controls, I would suggeset giving it a fixed width and height and position your child elements based on that, i.e. use width: 100% for your children and give all of them the same margin so they align nicely. Also make sure you either edit your #progressBar style in the markup.
Here's a snippet with the changes I just mentioned:
body {
background: rgba(0, 0, 0, 0.0);
}
fieldset {
width: 508px;
height: 270px;
/* fixed width and height*/
margin: 13vh auto;
}
#p1 {
border: 4px dashed #0D0D0D;
/* modified the actual text box instead of the entire form */
width: 508px;
height: 140px;
line-height: 140px;
margin-top: 0px;
}
form p {
text-align: center;
color: #0D0D0D;
font-family: Arial;
}
h2 {
text-align: center;
}
form input[type="file"] {
position: absolute;
margin: 0;
outline: none;
width: 508px;
height: 140px;
margin: 22px 4px;
opacity: 1;
background-color: orange;
/* Last two properties are a visual representation. Delete background-color and set opacity to 0 */
}
form input[type="button"] {
margin: 0;
color: #fff;
background: #16a085;
border: none;
width: 100%;
/* width relative to parent fieldset */
height: 35px;
margin-top: -20px;
border-radius: 4px;
border-bottom: 4px solid #117A60;
transition: all .2s ease;
outline: none;
}
form input[type="button"]:hover {
background: #149174;
color: #0C5645;
}
form input[type="button"]:active {
border: 0;
}
form progressBar {
text-align: center;
}
<!DOCTYPE html>
<html>
<head>
<script>
/* Script written by Adam Khoury # DevelopPHP.com */
/* Video Tutorial: http://www.youtube.com/watch?v=EraNFJiY0Eg */
function _(el) {
return document.getElementById(el);
}
function uploadFile() {
var file = _("file1").files[0];
// alert(file.name+" | "+file.size+" | "+file.type);
var formdata = new FormData();
formdata.append("file1", file);
var ajax = new XMLHttpRequest();
ajax.upload.addEventListener("progress", progressHandler, false);
ajax.addEventListener("load", completeHandler, false);
ajax.addEventListener("error", errorHandler, false);
ajax.addEventListener("abort", abortHandler, false);
ajax.open("POST", "file_upload_parser.php");
ajax.send(formdata);
}
function progressHandler(event) {
//_("loaded_n_total").innerHTML = "Uploaded "+event.loaded+" bytes of "+event.total;
var percent = (event.loaded / event.total) * 100;
_("progressBar").value = Math.round(percent);
_("status").innerHTML = Math.round(percent) + "% uploaded... please wait";
}
function completeHandler(event) {
_("status").innerHTML = event.target.responseText;
_("progressBar").value = 0;
document.getElementById('p1').innerHTML = "Drag your file here or click in this area.";
}
function errorHandler(event) {
_("status").innerHTML = "Upload Failed";
}
function abortHandler(event) {
_("status").innerHTML = "Upload Aborted";
}
function changeText() {
document.getElementById('p1').innerHTML = "1 file selected";
}
</script>
<link rel="stylesheet" href="test.css">
</head>
<body>
<h2>Upload</h2>
<fieldset>
<legend>Group 1</legend>
<form id="upload_form" enctype="multipart/form-data" method="post">
<input type="file" name="file1" id="file1"><br>
<p id="p1">Drag your file here or click in this area.</p>
<input type="button" value="Upload File" onclick="uploadFile()">
<!-- changed progressBar style -->
<progress id="progressBar" value="0" max="100" style="width:100%; margin-top: 10px;"></progress>
<h3 id="status"></h3>
<p id="loaded_n_total"></p>
</form>
</fieldset>
<script>
// self executing function here
(function() {
document.getElementById('upload_form')[0].onchange = changeText;
})();
</script>
</body>
</html>
Hope it helps!

How to display custom video controls even in fullscreen

Update: Can't see to get things working in Firefox : (
How can I display custom video controls when the in fullscreen mode in modern browsers?
They disappear as soon as I go fullscreen. I'd like them to be available, and then I'll write some JavaScript to hide them on inactivity and show them once someone wiggles their mouse around.
HTML:
<video#video src="vid.mp4" preload poster="/images/poster.jpg">
<iframe src="https://youtube.com/embed/id" frameborder="0" allowfullscreen>
</video>
JS:
var bigPlayButton = document.getElementById('big-play-button')
var video = document.getElementById('video')
var playPauseButton = document.getElementById('play-pause')
var fullscreen = document.getElementById('fullscreen')
function toggleFullScreen() {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen()
} else {
if (document.exitFullscreen) {
document.exitFullscreen()
}
}
}
fullscreen.addEventListener('click', function (event) {
if (!video.classList.contains('fullscreen')) {
video.requestFullscreen()
} else {
document.exitFullscreen()
}
}, false)
// Detect FullScreen changes and adjust button
document.addEventListener('fullscreenchange', function (event) {
if (document.fullscreenElement) {
fullscreen.children[0].src = '/images/nofullscreen.svg'
video.classList.add('fullscreen')
} else {
fullscreen.children[0].src = '/images/fullscreen.svg'
video.classList.remove('fullscreen')
}
}, false)
CSS
video::-webkit-media-controls {
display: none !important;
}
#custom-video-controls {
z-index: 2147483648;
}
I'm using this polyfill: https://github.com/neovov/Fullscreen-API-Polyfill
Edit
The significant change was targeting the parent tag: .vidFrame for fullscreen instead of the <video> tag as per Kaido's comment.
HTML5 video's controls need special handling if you want to override them. I'm assuming you want to do that since the controls already have the full screen feature built in the controls. This demo implements:
classList for toggling the button#fullScreen states of .on and .off and button#playPause states of .play and .pause.
:fullscreen pseudo-class to insure .vidBar is on the bottom when in full screen mode.
Shadow DOM CSS Styles that are needed to override the native player's controls.
Fullscreen API vendor specific methods to enter and exit full screen mode of course.
There's no volume slider, mute button, or scrubber, just the full screen button (button#fullScreen) and play button (button#playPause). If you want them, ask another question.
Details are commented in source.
It looks as if the Snippet isn't fully functional, so here's a functional Plunker. If that version cannot be reached, then review the embedded Plunker and click the full view button:
Demo
Note: SO sandbox has changed so this demo is not fully functional go to the links mentioned previously or copy and paste the demo on a text editor.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Full Screen Video Toggle</title>
<style>
.vidFrame { position: relative; top: 10%; width: 320px; height: auto; min-height: 180px; outline: 1px dashed red; }
.vidBar { position: absolute; bottom: 0; right: 0; left: 0; height: 40px; width: 99%; }
#fullScreen { position: absolute; bottom: 0; right: 0; width: 36px; height: 36px; outline: none; border: 1px solid transparent; border-radius: 6px; display: block; cursor: pointer; }
#fullScreen:hover { border: 1px groove #0ef; }
.on, .off { background: url('https://i.imgur.com/0FTwh6M.png') no-repeat; width: 36px; height: 36px; }
.off { background-position: 0 0 }
.on { background-position: -1px -50px }
#playPause { position: absolute; bottom: 0; left: 0; width: 36px; height: 36px; background: none; font-size: 36px; color: #0ff; line-height: 1; border: 1px solid transparent; display: block; cursor: pointer; outline: none; }
#playPause.play:before { content: '\25b6'; }
#playPause.pause:before { content: '\275a\275a'; }
.vid { position: absolute; top: 0; left: 0; right: 0; bottom: 0; width: 100%; height: auto; display: block; z-index: 1; outline: 1px dotted blue; }
/*
Fullscreen Pseudo-class:
https://developer.mozilla.org/en-US/docs/Web/CSS/:fullscreen
*/
.vidBar:-moz-full-screen { position: fixed; }
.vidBar:-webkit-full-screen { position: fixed; }
.vidBar:-ms-fullscreen { position: fixed; }
.vidBar:fullscreen { position: fixed; }
/*
Special Shadow DOM Settings to Override Default Controls:
https://css-tricks.com/custom-controls-in-html5-video-full-screen/
*/
video::-webkit-media-controls-enclosure { display:none !important; }
.vidBar { z-index: 2147483648; }
</style>
</head>
<body>
<figure class="vidFrame">
<video id="vid1" class="vid" src="http://techslides.com/demos/sample-videos/small.mp4"></video>
<figcaption class="vidBar">
<button id='playPause' class="play" title="Play/Pause Video"></button>
<button id='fullScreen' class="on" title="Enter/Exit Full Screen"></button>
</figcaption>
</figure>
<script>
/*
Toggle Button with classList:
https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
*/
var fullBtn = document.getElementById('fullScreen');
var playBtn = document.getElementById('playPause');
playBtn.addEventListener('click', function(event) {
var player = document.getElementById('vid1');
if(player.paused) {
playBtn.classList.remove('play');
playBtn.classList.add('pause');
player.play();
} else {
playBtn.classList.add('play');
playBtn.classList.remove('pause');
player.pause();
}
}, false);
fullBtn.addEventListener('click', function(event) {
var tgtEle = document.querySelector('.vidFrame');
var onOrOff = fullBtn.classList.contains('on');
if (onOrOff) {
enterFS(tgtEle);
fullBtn.classList.remove('on');
fullBtn.classList.add('off');
} else {
exitFS();
fullBtn.classList.add('on');
fullBtn.classList.remove('off');
}
}, false);
/*
Fullscreen API:
https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API
*/
function enterFS(element) {
if (element.requestFullscreen) {
element.requestFullscreen();
} else if (element.msRequestFullscreen) {
element.msRequestFullscreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullscreen();
}
}
function exitFS() {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
}
}
</script>
</body>
</html>
Use the Fullscreen API on the container element, not on the video
As #Kaiido says in the comments:
You have to call the enterFS method on the container element, not on
the video one.
So the answer is to use the Fullscreen API on the container element rather than the <video> element. This enables providing custom controls in that container which is now all in fullscreen.
For reference, that is the existing enterFS() function from the question:
function enterFS(element) {
if (element.requestFullscreen) {
element.requestFullscreen();
} else if (element.msRequestFullscreen) {
element.msRequestFullscreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullscreen();
}
}
I posted this answer because I had to read the page three times to figure out what was going on here.
There is great information in #zer00ne's answer that is relevant to others with similar issues, but it doesn't directly answer #Costa's original problem, which was previously only answered in a comment.

How can I make an Upvote/Downvote button?

I'm trying to make an upvote/downvote the same way that it's done on SO and Reddit, from what I can see they use arrow images as backgrounds and then position it, but I'm a CSS newbie and I need someone to walk me through it.
You could do it by adding a different picture to the background, one for every state of the button. There is however a cleaner, easier, more modern way of achieving this result: Sprites.
A sprite is an image that is saved as a part of a larger image. One of the biggest advantages of using sprites is the reduction of round-trips to the server for all the images to just one request for the Sprites. The element to display a picture has the image as background. The background is moved relative to the element so the element displays only part of the image. Like when you move a photo-frame over a poster (or in this case: moving the poster under the frame)
At SO they make an image that contains all the states for the button. They give the element for the button (a span in this case) a fixed width and height and add the background to it with CSS. Then toggle a class for the state (on or off) with javascript on the click event. Now the only thing you have to do in CSS is change the position of the background with CSS classes:
for (const btn of document.querySelectorAll('.vote')) {
btn.addEventListener('click', event => {
event.currentTarget.classList.toggle('on');
});
}
.vote {
display: inline-block;
overflow: hidden;
width: 40px;
height: 25px;
cursor: pointer;
background: url('http://i.stack.imgur.com/iqN2k.png');
background-position: 0 -25px;
}
.vote.on {
background-position: 0 2px;
}
Click to vote (using sprites): <span class="sprite vote"> </span>
You can easily add more states to the sprites like 'hover' and 'active' just the same way. SO even puts all the images for the whole page in a single image. You can verify this with firebug or the Chrome developer tools. Look for 'sprites.png'.
Update (2020)
It's been 10 years since I answered this question and in this time,
the landscape has changed. Now you can use inline svg as well to achieve this effect. I've updated the code snippet to use svg. This is how stackoverflow currently does this.
It works by toggling the color property of a surrounding span element on button click. The span element contains an inline svg image of an arrow. The fill property of the path that makes up the arrow is initialized with currentColor, which instructs it to take whatever is the current text color.
for (const btn of document.querySelectorAll('.vote')) {
btn.addEventListener('click', event => {
event.currentTarget.classList.toggle('on');
});
}
.vote {
display: inline-block;
cursor: pointer;
color: #687074
}
.vote.on {
color: #f48024
}
Click to vote (using svg):
<span class="vote">
<svg width="36" height="36">
<path d="M2 10h32L18 26 2 10z" fill="currentColor"></path>
</svg>
</span>
You can do it by using two simple images ... design two images in some image editors like Photoshop, if u don't have MSPaint...
CSS code is
#voting{
width:30px;
height:40px;
}
.upvote{
width:30px;
height: 20px;
cursor: pointer;
}
.downvote{
width:30px;
height: 20px;
background: url('downvote.jpg') 0 0 no-repeat;
cursor: pointer;
}
HTML code :
<div id="voting">
<div class="upvote"></div>
<div class="downvote"></div>
</div>
I'm doing project on django, and I'm trying to implement up-vote and down-vote on many posts, I've taken #Jan's code partly and finished it.
vote.html
<span onclick="like_function({{user_answer.pk}})" id="like-{{user_answer.pk}}" class="vote_up_off"></span>
<div id="counter-{{user_answer.pk}}">0</div>
<span onclick="dislike_function({{user_answer.pk}})" id="dislike-{{user_answer.pk}}" class="vote_down_off"></span>
vote.css
/* like dislike button */
.vote_up_off {
display: inline-block;
overflow: hidden;
width: 40px;
height: 25px;
cursor: pointer;
background: url(' https://i.stack.imgur.com/nxBdX.png');
background-position: 0 -25px;
margin-left: 5px;
}
.vote_up_on {
background-position: 0 2px;
display: inline-block;
overflow: hidden;
width: 40px;
height: 25px;
cursor: pointer;
background: url('https://i.stack.imgur.com/nxBdX.png');
margin-left: 5px;
}
.vote_down_off {
display: inline-block;
overflow: hidden;
width: 40px;
height: 25px;
cursor: pointer;
background: url('https://i.stack.imgur.com/vWw7n.png');
background-position: 0 -1px;
margin-top: 3px;
}
.vote_down_on {
display: inline-block;
overflow: hidden;
width: 40px;
height: 25px;
cursor: pointer;
background: url('https://i.stack.imgur.com/vWw7n.png');
background-position: 0 -28px;
margin-top: 3px;
}
vote.js
function like_function(answer_id) {
var like_button = document.getElementById('like-'+answer_id);
var dislike_button = document.getElementById('dislike-'+answer_id);
var counter_element = document.getElementById('counter-'+answer_id);
let current_counter = parseInt(counter_element.innerText);
//check if dislike is on(true) or off(false)
let dislike_state = false
if (dislike_button.className == "vote_down_on") {
dislike_state = true
}
else {
dislike_state = false
}
//if dislike is checked
if (dislike_state) {
current_counter += 2;
dislike_button.className = 'vote_down_off'
counter_element.innerText = current_counter
like_button.className = 'vote_up_on'
}
// if dislike is not checked
else {
if (like_button.className == 'vote_up_off') {
like_button.className = "vote_up_on"
current_counter += 1;
counter_element.innerText = current_counter
}
else {
like_button.className = "vote_up_off"
current_counter += -1;
counter_element.innerText = current_counter
}
}
}
function dislike_function(answer_id) {
var like_button = document.getElementById('like-'+answer_id);
var dislike_button = document.getElementById('dislike-'+answer_id);
var counter_element = document.getElementById('counter-'+answer_id);
let current_counter = parseInt(counter_element.innerText);
//check if like is on(true) or off(false)
let like_state = false
if (like_button.className == "vote_up_on") {
like_state = true
}
else {
like_state = false
}
//if like is checked
if (like_state) {
console.log('это тру лайк (лайк нажат)')
current_counter += -2;
like_button.className = 'vote_up_off'
counter_element.innerText = current_counter
dislike_button.className = "vote_down_on"
}
//if like is not checked
else {
if (dislike_button.className == 'vote_down_off') {
dislike_button.className = "vote_down_on"
current_counter += -1;
counter_element.innerText = current_counter
}
else {
dislike_button.className = "vote_down_off"
current_counter += 1;
counter_element.innerText = current_counter
}
}
}