How to make a hover effects like Wikipedia (JavaScript)? - javascript

I am trying to make a hovercard effect using SVG and JavaScript such as Wikipedia and Facebook.
You can say that It can be solved by using tooltips but not because I want to make it dynamic like Wikipedia.
I want to use it on pure js, not jquery. In this case which event is best for me?
onmouseover/onmousemove ? But on mouseover is not working perfectly! try to help me plz, It's very very important for me.
Demo image
Here is a question which is similar to my question, But this question has no answer yet.
How to make a hover effects like Wikipedia and Facebook
<div class="content">
Lorem text <a href="/wiki/mark"> Mark Info will show here
when you hover </a> Dummy text You will show here when you hover on it
</div>
//Define one time only
<div class="modal" style="display: none">
<div class="modal-title"> </div>
<div class="modal-content"> </div>
</div>
(NOTE: I have some problems with my CSS and js link. I am a new programmer, I want to learn more), Sorry about that.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Wikipedia Hover Effects</title>
<style>
.content {
font-family: Segoe UI;
border: 1px solid #ddd;
padding: 30px;
box-sizing: border-box;
line-height: 27px;
}
.v-content-modal {
position: absolute;
background: #fff;
box-shadow: 0 3px 20px 0 #ddd;
width: 350px;
border-top: 3px solid #ddd;
display: none;
box-sizing: border-box;
}
.v-content-modal .modal-title {
background: #f5f5f5;
padding: 0 1.25rem;
font-size: .95rem;
letter-spacing: .03rem;
line-height: 38px;
height: 35px;
border-bottom: 1px solid #ddd;
}
.v-content-modal .modal-content {
padding: 1.75rem 1.25rem;
}
.v-content-modal::before {
content: "";
position: absolute;
top: -23px;
left: 30px;
border: 10px solid transparent;
border-color: transparent transparent #ddd transparent;
}
</style>
</head>
<body>
<div class="content">
Lorem ipsum dolor sit amet One
adipisicing elit. Quisquam, modi neque! Cupiditate itaque vitae aliquid
Two,
pariatur qui sequi minima voluptates voluptatibus quae
nemo! Suscipit Three quibusdam
dignissimos vitae, cum cumque voluptates et hic doloribus dicta, <a href="#" data-title="Four"
data-content="I am the Forth one/" id="info">Four</a> quos,
nostrum in.
</div>
<div class="v-content-modal">
<div class="modal-title">
Title
</div>
<div class="modal-content">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo, quam.
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
$(function () {
let modal = $(".v-content-modal");
let title = $(".v-content-modal > .modal-title");
let content = $(".v-content-modal > .modal-content");
let btns = document.querySelectorAll("#info");
btns.forEach(btn => {
btn.addEventListener("mouseover", (e) => {
modal.css({
top: 'unset',
right: 'unset',
left: 'unset',
bottom: 'unset'
});
title.html(e.target.getAttribute('data-title'));
content.html(e.target.getAttribute('data-content'));
let pageX, pageY, winWidth, winHeight, elmWidth, elmHeight, width_limit, height_limit = '';
pageX = e.pageX;
pageY = e.pageY;
winWidth = $(window).width();
winHeight = $(window).height();
elmWidth = $(".v-content-modal").width();
elmHeight = $(".v-content-modal").height();
width_limit = winWidth - elmWidth;
height_limit = winHeight - elmHeight;
(pageX > width_limit) ? crossWidth(): normalWidth();
(pageY > height_limit) ? crossHeight(): normalHeight();
function crossWidth() {
modal.css({
right: '5px'
});
}
function normalWidth() {
modal.css({
left: pageX
});
}
function crossHeight() {
modal.css({
bottom: '111px'
});
}
function normalHeight() {
modal.css({
top: e.pageY + 30 + 'px'
});
}
// show when all customization is completed...
modal.show();
});
btn.addEventListener("mouseleave", () => {
modal.hide();
});
});
});
</script>
</body>
</html>

Related

Show HTML/CSS Class after clicking on a button

I have this Jquery-Code that copies the URL when clicked on its button (.clipboard). Now I want it to show another HTML/CSS Class after clicking on it.
I tried to declare it as a variable const success = $('.success-message').html(); and then with $('.success-message').html(success); to run it (as you can see in the code). Unfortunately, that does not work. Is there a other way to do it? I looked it up and found the toggle method. That did not work either, or I just implemented it wrong. Appreciate any help!
Jquery:
var $temp = $("<input>");
var $url = $(location).attr('href');
$('.clipboard').on('click', function() {
const originalText = $('.clipboard').html();
const success = $('.success-message').html();
// CSS function:
const addCSS = s => document.head.appendChild(document.createElement("style")).innerHTML=s;
$("body").append($temp);
$temp.val($url).select();
document.execCommand("copy");
$temp.remove();
$('.clipboard').html(originalText);
$('.success-message').html(success);
// CSS Usage:
addCSS(".clipboard{ font-size: 20px; padding: 4.8px 21.3px 4.8px 21.3px; }")
// Run something in 1 seconds to revert back to the button's text
setTimeout(function() {
addCSS(".clipboard{ font-size: 15px; padding: 9px 21.3px 9px 21.3px}")
$('.clipboard').html(originalText);
}, 1000); // 1 seconds
})
The HTML/CSS Class I want to show:
<div class="success-message">
KOPIERT!
</div>
<style>
.success-message{
color: white;
background-color: #2FAC66;
padding: 1px 50px 1px 50px;
text-align: center;
font-size: 12px;
font-weight: bold;
margin-bottom: 20px;
}
</style>
Here is a complete index.html as minimal working example.
Suppose, you want to show the div.success-message after the button has been clicked.
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/jquery#3.6.0/dist/jquery.min.js"></script>
<style>
.success-message {
visibility: hidden;
color: white;
background-color: #2fac66;
padding: 1px 50px 1px 50px;
text-align: center;
font-size: 12px;
font-weight: bold;
margin-bottom: 20px;
}
</style>
</head>
<body>
<div>Kopieren</div>
<div class="success-message">KOPIERT!</div>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Ullam debitis
accusamus quam nisi. Suscipit rerum nisi placeat tempore accusantium ut
dolorum? Sit assumenda, incidunt voluptate unde optio quo enim voluptas.
</p>
<button class="clipboard">Kopieren!</button>
<script type="text/javascript">
$.when($.ready).then(function () {
// Document is ready.
$(".clipboard").on("click", () => {
$(".success-message").css("visibility", "visible");
});
});
</script>
</body>
</html>

Unable to insert element before and after (both) in jQuery

I am using jQuery 3.x. I am trying to append a dynamically created element before and after an element using insertBefore() and insertAfter(). However, only insertBefore() is working, and another one is ignored. When I am commenting one then other is working. why?
p = $("<p></p>").text("This is a dynamicly created element");
p.insertAfter($('nav'));
p.insertBefore($('nav'));
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-size: 20px;
}
header,
nav,
main,
aside,
footer {
padding: 10px 15px;
border: 1px solid mediumseagreen;
text-align: center;
}
header {
background: dodgerBlue;
}
nav {
background: mediumSeaGreen;
}
main {
background: #d3d3d3;
}
main,
aside {
height: 1200px;
}
main {
width: 80%;
float: left;
}
aside {
width: 20%;
float: right;
}
div::after {
content: " ";
float: none;
clear: both;
display: table;
}
main {
text-align: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
This is header
</header>
<nav>
This is navbar
</nav>
<main>
<article>
<h2>This is heading</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum atque fuga, eos neque ipsum enim id inventore necessitatibus laboriosam quo nobis, repellendus maxime veritatis error ut expedita, velit aspernatur asperiores!
</p>
</article>
</main>
<aside>
This is side bar
</aside>
<div></div>
<footer>
This is footer
</footer>
The issue is because the p references only a single element. You insert it in to the DOM in the insertAfter() call, then move the same element to a new location using insertBefore().
To do what you require you can clone() the element before the second insertion. Also note that you don't need to create an entire jQuery object to select nav, you can just pass the selector as a string. Try this:
let p = $("<p />", {
text: "This is a dynamicly created element"
});
p.insertAfter('nav');
p.clone().insertBefore('nav');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-size: 20px;
}
header,
nav,
main,
aside,
footer {
padding: 10px 15px;
border: 1px solid mediumseagreen;
text-align: center;
}
header {
background: dodgerBlue;
}
nav {
background: mediumSeaGreen;
}
main {
background: #d3d3d3;
}
main,
aside {
height: 1200px;
}
main {
width: 80%;
float: left;
}
aside {
width: 20%;
float: right;
}
div::after {
content: " ";
float: none;
clear: both;
display: table;
}
main {
text-align: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>This is header</header>
<nav>This is navbar</nav>
<main>
<article>
<h2>This is heading</h2>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Cum atque fuga, eos neque ipsum enim id inventore necessitatibus laboriosam quo nobis, repellendus maxime veritatis error ut expedita, velit aspernatur asperiores!
</p>
</article>
</main>
<aside>This is side bar</aside>
<div></div>
<footer>This is footer</footer>
One other thing to mention, I would suggest researching flexbox layouts. They're a much more modern and extensible technique than forcing display: table on a div to create a multi-column layout.

How to make a slide(up/down) without jQuery?

I am trying to make a slide(up/down) system for my collapse components (like bootstrap) but I can't get the height of the elements to animate(without height there is no possible way to animate the element I think so- if this is wrong, then how can I animate the element?)!
NOTE: [I want to use pure javascript]
document.getElementById('btn').addEventListener('click', function(){
this.nextElementSibling.classList.toggle('active');
})
body{
font-family: Segoe UI;
font-size: 1rem;
line-height: 1.5;
}
.collapse{
border: 1px solid #e7e7e7;
border-radius: .25rem;
overflow: hidden;
}
#btn{
padding: .75rem 1.25rem;
width: 100%;
border: none;
font-size: inherit;
background-color: #fff;
cursor: pointer;
}
#btn:focus{
outline: 0;
}
.collapse-content{
font-size: 95%;
padding: .75rem .75rem;
display: none;
}
.collapse-content.active{
display: block;
}
<div class="collapse">
<button id="btn"> Click Me </button>
<div class="collapse-content">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Mollitia ut explicabo nesciunt minima pariatur saepe eveniet officia ducimus perferendis suscipit?
</div>
</div>
Bare-bones vanilla javascript implementation that'll account for any internal height (with consistent transition speed) can be achieved with some minor changes to the markup.
<div class="collapse">
<button id="btn"> Click Me </button>
<div class="collapse-wrapper">
<div class="collapse-content">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Mollitia ut explicabo nesciunt minima pariatur saepe eveniet officia ducimus perferendis suscipit?
</div>
</div>
</div>
Note the addition of the collapse-wrapper div. This'll allow you to render the content and measure its height without actually displaying the content. Then it's just a simple case of showing/hiding the content on click:
* {
box-sizing: border-box;
}
.collapse-wrapper {
overflow: hidden;
transition: all 300ms ease-in;
}
const wrapper = document.querySelector('.collapse-wrapper')
const content = document.querySelector('.collapse-content')
const button = document.getElementById('btn')
let open = true
// Set initial height to content height, if shown by default
if (open) {
wrapper.style.height = `${content.getBoundingClientRect().height}px`
}
function toggleOpen () {
if (open) {
wrapper.style.height = '0px'
open = false
} else {
const height = content.getBoundingClientRect().height
wrapper.style.height = `${height}px`;
open = true
}
}
button.addEventListener('click', toggleOpen)
Here's a fiddle
You need to use max-height. Yes, it's nasty, since it means you need to set some arbitrary max height that may need to be adjusted later if the content grows. However, you cannot animate height in this situation because the height is not defined before the content opens.
Something like:
.collapse-content{
font-size: 95%;
padding: .75rem .75rem;
max-height: 0;
transition: max-height .3s;
}
.collapse-content.active{
max-height: 200px; //something bigger than what you need
}
function slide(){
document.getElementById("sliding").style.maxHeight = "1000px";
}
#sliding{
transition: 0.5s;
max-height: 0px;
overflow: hidden;
}
<button onclick ="slide();">Slide it</button>
<div id = "sliding">
<h1>It works</h1>
<p>Hello there</p>
</div>
This is sort of hacky because you have to set maxHeight to the largest you think your content will get.
Source: How can I transition height: 0; to height: auto; using CSS?

screen.height & screen.width not returning correct values

I am enabling an overlay upon clicking on button, then when user minimizes the screen overlay is not covering full page. User able to click on buttons when minimizes the screen.
I am setting the screen.height & screen.width to overlay div. But upon minimizes to certain level again buttons are visible.
id1 is a id of overlay division
document.getElementById("id1").style.height=screen.height;
document.getElementById("id1").style.width=screen.width;
i want overlay to display over complete web page
Ok, Here is what we do to create Overlays..
You should have a parent div like
<div class="body_wrapper">
<div class="overlay"></div>
<div class="page_content">
<-- You Page Content -->
</div>
</div>
Here inside <body> tag you got a body_wrapper and inside that you got overlay and page__content. Now in your style sheet:
.body_wrapper {
position: relative;
}
.overlay {
position: absolute;
right: 0;
top: 0;
left: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
}
The screen.height doesn't always return the valid screen height,
check this for more information.
Your task can be achieved by CSS and a little bit of JavaScript.
The CSS has two units that are likely the keys to your issue : the vw and the vh units. Check this MDN article for more information.
So, here's a demo that shows how you can achieve your task by the help of CSS and some JavaScript for the event handling.
let trigger = document.getElementById('trigger'),
triggersClose = document.querySelectorAll('.trigger-close'),
fullScreen = document.getElementById('fullscreen');
/** click event listener for the button to show the overlay **/
trigger.addEventListener('click', e => {
e.preventDefault();
fullScreen.classList.add('visible'); /** add .visible class so the overlay is shown **/
});
/** cycle through the buttons that can hide the overlay and add a click event for them **/
triggersClose.forEach(el => {
el.addEventListener('click', e => {
e.preventDefault();
fullScreen.classList.remove('visible'); /** remove .visible class so the overlay becomes hidden **/
});
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.overlay {
display: none; /** the overlay is initially hidden **/
position: fixed; /** stays on the same place even when scrolling in the background **/
width: 100vw; /** vw : viewport width = 1% of the viewport's width. It changes accordingly when zooming (responsive) **/
height: 100vh; /** vh : viewport height = 1% of the viewport's height. It changes accordingly when zooming (responsive) **/
top: 0;
left: 0;
justify-content: center; /** center the content horizontally **/
align-items: center; /** center the content vertically **/
padding: 15px;
background: rgba(24, 24, 24, .6);
z-index: 999; /** stays on top **/
}
.overlay.visible {
/** this class is used by JavaScript to show the overlay **/
display: flex; /** flex makes our life easier ! **/
}
.overlay .overlay-wrapper {
display: flex;
flex-direction: column;
width: 65%;
max-height: 100%;
overflow-y: auto; /** adds scrollbars when the content is too much **/
background-color: #fff;
}
.overlay .overlay-wrapper .overlay-header {
position: relative;
background-color: #1548a6;
}
.overlay .overlay-wrapper .overlay-header>.text,
.overlay .overlay-wrapper .overlay-body {
padding: 15px 5px;
}
.overlay .overlay-wrapper .overlay-header>.trigger-close {
position: absolute;
width: 45px;
right: 0;
top: 0;
bottom: 0;
margin: auto;
font-size: 1.1rem;
font-weight: bold;
border: 0;
color: #fff;
background-color: #dc3545;
cursor: pointer;
border-top-right-radius: 4px
}
.overlay .overlay-wrapper .overlay-footer>.trigger-close {
float: right;
margin-bottom: 5px;
margin-right: 5px;
padding: 8px 15px;
color: #fff;
background-color: #007bff;
border: 0;
border-radius: 4px;
}
<button id="trigger">click me !</button>
<div id="fullscreen" class="overlay">
<div class="overlay-wrapper">
<div class="overlay-header">
<h3 class="text">Message heading</h3>
<button class="trigger-close">×</button>
</div>
<div class="overlay-body">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. In facere fugiat aperiam officiis debitis voluptas soluta assumenda cumque reiciendis blanditiis nostrum, consequuntur vero corporis doloribus! Expedita voluptatem illum maiores culpa.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Beatae ex temporibus, possimus commodi, obcaecati nostrum maiores cupiditate voluptas voluptate unde qui quasi accusantium earum dolores pariatur fuga. Optio, officia praesentium.</p>
</div>
<div class="overlay-footer"><button class="trigger-close">close</button></div>
</div>
</div>
Learn more about flexbox (display: flex).
Hope I pushed you further.

Targeting a toggle button within an accordion

I'm trying to target my on/off toggle control which is embedded in a link that also toggles an accordion when you tap on it. Both toggles work, but I want them to work independently of each other. The on/off switch is not supposed to toggle the accordion. I'm using Ratchet as the framework, if that means anything. Here's my JS Fiddle
<li class="table-view-cell toggle-handle accordion">
Kitchen Light
<div class="toggle">
<div class="toggle-handle"></div>
</div>
<!-- toggle -->
</li>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui, officiis asperiores totam. Amet, beatae explicabo placeat consequatur repellendus quia rerum saepe cumque autem facilis! Perferendis, exercitationem eius vitae alias ad.</p>
</div>
li.accordion {
curser: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
li.accordion.active,
button.accordion:hover {
background-color: #ddd;
}
li.accordian:after {
content: '\002B';
color: #777;
font-weight: bold;
float: right;
margin-left: 5px;
}
div.panel {
padding: 0 18px;
background-color: white;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
}
div.toggle {
z-index: 1;
}
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].onclick = function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + 'px';
}
}
} //end function
The key piece you are missing is event.stopPropagation(); as this prevents the toggle from also triggering the accordion.
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].getElementsByClassName("toggle")[0].onclick = function() {
event.stopPropagation();
this.classList.toggle("active");
}
acc[i].onclick = function() {
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + 'px';
}
}
} //end function
li.accordion {
/* change the button tag to li tag */
curser: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
li.accordion.active,
button.accordion:hover {
background-color: #ddd;
}
li.accordian:after {
content: '\002B';
color: #777;
font-weight: bold;
float: right;
margin-left: 5px;
}
div.panel {
padding: 0 18px;
background-color: white;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
}
div.toggle {
z-index: 1;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/ratchet/2.0.2/css/ratchet.css" rel="stylesheet"/>
<li class="table-view-cell toggle-handle accordion">
Kitchen Light
<div class="toggle">
<div class="toggle-handle"></div>
</div>
<!-- toggle -->
</li>
<div class="panel">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Qui, officiis asperiores totam. Amet, beatae explicabo placeat consequatur repellendus quia rerum saepe cumque autem facilis! Perferendis, exercitationem eius vitae alias ad.</p>
</div>
<!-- end panel -->
I have functional your button
https://jsfiddle.net/Lpppha37/5/
I have updated some html code
<li class="table-view-cell toggle-handle accordion ">
Kitchen Light
<div class="toggle toggle-handle accordion">
<div class="toggle-handle "></div>
</div>
<!-- toggle -->
</li>
Use JavaScript to handle the click event of the target element. That's it really. Just use the .classList toggle method.

Categories