How to convert toggle function to module pattern in javascript? - javascript

I'm a new javascript, i have heard that declaring global variables it's pretty much bad idea in javascript, we have to less or avoid as much as we can.
I have found page https://www.w3.org/wiki/JavaScript_best_practices#Avoid_globals and i saw module pattern it seems a good way to go.
So, i've been practicing about toggle function my first code it works fine
function toggle() {
var mainTopics = document.querySelector("#maintopics"); // target the li
mainTopics.addEventListener("click", function (e) { // passed "e" to get the event
e.preventDefault(); // prevent anchor to navigate
mainTopics.classList.toggle("show"); // changed to toggle for the
// the purpose of this demo
});
}
toggle();
body {
margin: 0;
}
li, a{
text-decoration: none;
list-style-type: none;
text-decoration-line: none;
color: black;
}
/*main-menu*/
#mainmenu {
position: relative;
}
#mainmenu ul {
margin: 0;
padding: 0;
}
#mainmenu li {
display: inline-block;
}
#mainmenu a {
display: block;
width: 100px;
padding: 10px;
border: 1px solid;
text-align: center;
}
/*sub-topics*/
#subtopics {
position: absolute;
display: none;
margin-top: 10px;
width: 100%;
left: 0;
}
#maintopics.show #subtopics {
display: block;
}
#subtopics ul {
margin: 0;
padding: 0;
}
#subtopics li {
display: block;
}
#subTopics a {
text-align: left;
}
/*columns*/
#column1, #column2, #column3 {
position: relative;
float: left;
left: 125px;
margin: 0px 5px 0px 0px;
}
/*hover underline*/
#mainmenu li:hover {
text-decoration: underline;
}
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" type="text/css" href="index2.css" />
</head>
<body>
<div id="mainmenu">
<ul>
<li>Logo</li>
<li>Home</li>
<li id="maintopics">Topics
<div id="subtopics">
<div id="column1" class="columns">
<ul>
<li>example1</li>
<li>example2</li>
<li>example3</li>
</ul>
</div>
</div>
</li>
</ul>
</div>
<script src="index2.js"></script>
</body>
</html>
I changed code javascript to module pattern.However it didn't work, im not sure if my code is wrong or there is some important rule that i don't know.
If anyone would like to give me some advices i will appreciate it thank you very much.
var toggle = (function() {
var mainTopics = document.getElementById("maintopics");
mainTopics.addEventListener("click", function(e) {
e.preventDefault();
mainTopics.classList.toggle("show");
});
return {
toggle()
}
})();
Hi, everyone i suddenly found the solution for my case. i just need to specific the function that i want to return to object again for example in my case return toggle function it would be toggle: toggle()
var toggle = (function () {
var mainTopics = document.getElementById("maintopics");
mainTopics.addEventListener("click", function (e) {
e.preventDefault();
mainTopics.classList.toggle("show");
});
return {
toggle: toggle()
}
})();

Related

Toggling menu problematic

I'm trying to hide and show .sub-menu by clicking the .menu anchor, it works only by showing it. If I press to hide it has no reaction, what I am supposed to do and what is the mistake?
Here is the code.
HTML:
<div class="menu">
<a href="javascript:myFunction();" class="nav" onclick="myFunction()">
<div class="unu"></div>
<div class="doi"></div>
<div class="trei"></div>
</a>
<div id="sm">
FAQ
Support
Features
</div>
</div>
CSS:
nav div{
height:7px;
background-color: white;
margin: 5px 0;
border-radius: 25px;
}
.menu {
position: absolute;
display:inline-block;
text-align:center;
right:130px;
top:60px;
}
.unu {
width: 45px;
}
.doi {
width: 20px;
}
.trei {
width:35px;
}
#sm {
display: none;
}
JS:
function myFunction() {
var x = document.getElementById("sm")
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
If you use
console.log(`${x.style.display}`)
you will get
<empty string>
in your first attempt not
none
that is why you need to set
function myFunction() {
var x = document.getElementById("sm")
if (x.style.display === "" || x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
I will add a console.log in window.load event to see what is the value of the sm element when the page load at first. And you can also check what is new properties when you click button.
const myDiv = document.getElementById('sm');
const controlButton = document.querySelector('button')
window.addEventListener('load', () => {
console.log(`${myDiv.style.display}`);
})
controlButton.addEventListener('click', () => {
if (myDiv.style.display === "" || myDiv.style.display === "none") {
myDiv.style.display = "block";
} else {
myDiv.style.display = "none";
}
console.log(`${myDiv.style.display}`);
})
*,
*::before,
*::after{
box-sizing: border-box;
}
body {
font-family: sans-serif;
min-height: 100vh;
margin: 0;
background-color: bisque;
}
nav div{
height:7px;
background-color: white;
margin: 5px 0;
border-radius: 25px;
}
.menu {
position: absolute;
display:inline-block;
text-align:center;
right:130px;
top:60px;
}
.unu {
width: 45px;
}
.doi {
width: 20px;
}
.trei {
width:35px;
}
#sm {
display: none;
}
button{
position: absolute;
width: 5rem;
height: 5rem;
background-color: greenyellow;
top: 5rem;
left: 5rem;
}
<div class="menu">
<div class="unu"></div>
<div class="doi"></div>
<div class="trei"></div>
</a>
<div id="sm">
FAQ
Support
Features
</div>
</div>
<button>Click me</button>
Instead of using display property you can create a .class for toggling which is quite simple than checking styles.
const toggle = document.querySelector('.toggle');
const hidden = document.querySelector('.hidden');
toggle.addEventListener('click', event => {
// because anchor's default behaviour is redirecting
event.preventDefault();
hidden.classList.toggle('revealed');
});
* {
margin: 0;
padding: 0;
outline: 0;
box-sizing: border-box;
}
body {
height: 100vh;
display: grid;
place-items: center;
}
.toggle,
.hidden {
font-family: sans-serif;
font-size: 1.5rem;
}
.hidden {
position: absolute;
margin-top: 6rem;
display: none;
}
.hidden.revealed {
display: block;
}
Click Me For Toggling
<p class="hidden"> I was hidden Initially </p>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Help</title>
<style>
nav div{
height:7px;
background-color: white;
margin: 5px 0;
border-radius: 25px;
}
.menu {
position: absolute;
display:inline-block;
text-align:center;
right:130px;
top:60px;
}
.unu {
width: 45px;
}
.doi {
width: 20px;
}
.trei {
width:35px;
}
.sm {
display: none;
}
.show {
display:block;
}
</style>
</head>
<body>
<div class="menu">
<a href="#">
<div class="unu">lll</div>
<div class="doi"></div>
<div class="trei"></div>
</a>
<div class="sm">
FAQ
Support
Features
</div>
</div>
<script>
var show = document.querySelector("a")
var x = document.querySelector(".sm")
show.addEventListener('click',()=>{
x.classList.toggle("show")
})
</script>
</body>
</html>
I made a lot of changes! You first I use Js Vanilla j. I relied on the "click" event on the "a" tag
By leaving your function in the link, it works but, once it appears, it disappears by itself again. Which means it doesn't overwrite the display property that was in the class sm.
In short, it works well; you can check on snipett

Attach event handler to every li

I have this code and I want to attach DIFFERENT event handlers to every <a> without using id or class.
I tried this but didn't work...
$('#points ul li a').on('click', function(event) {
// I don't know why this selectors doesn't work
if ($(event.target).is(':eq(0)')) {
alert('0') // and do something
}
if ($(event.target).is(':eq(1)')) {
alert('1') // and do something
}
if ($(event.target).is(':eq(2)')) {
alert('2') // and do something
}
})
#points ul {
list-style: none;
font-size: 5em;
padding: 0;
margin: 0;
line-height: .5em;
}
#points ul li {
float: left;
}
#points ul li a {
text-decoration: none;
color: grey;
padding: .1em;
line-height: .1em
}
#points {
position: relative;
margin: 0 auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="points">
<ul>
<li>.
</li>
<li>.
</li>
<li>.
</li>
</ul>
</div>
<script
Thanks in advance.
As suggested there are many alternate solutions, but the specific
error in your code was regarding your usage of :eq(0). Change it to #points>ul>li>a:eq(0) as per the jQuery documentation .
REPLACE
if ($(event.target).is(':eq(1)')) {
WITH
if ($(event.target).is('#points>ul>li>a:eq(0)')) {
Note: I have used #points>ul>li>a so that other <a> tags above and below are not selected. ( in light of your comment regarding the same )
I want to just add that if I was asked to do the same I'd take an
approach like:
var objArr = $('#points>ul>li>a');
objArr.on('click', function(event) {
switch($(objArr).index(this)){
case 0:
alert('0');
break;
case 1:
alert('1');
break;
case 2:
alert('2');
break;
}
});
That said your method works too and the WORKING EXAMPLE with the error I mentioned above adjusted for:
$('#points>ul>li>a').on('click', function(event) {
// I don't know why this selectors doesn't work
if ($(event.target).is('#points>ul>li>a:eq(0)')) {
alert('0') // and do something
}
if ($(event.target).is('#points>ul>li>a:eq(1)')) {
alert('1') // and do something
}
if ($(event.target).is('#points>ul>li>a:eq(2)')) {
alert('2') // and do something
}
})
#points>ul {
list-style: none;
font-size: 5em;
padding: 0;
margin: 0;
line-height: .5em;
}
#points>ul>li {
float: left;
}
#points>ul>li>a {
text-decoration: none;
color: grey;
margin: .1em;
}
#points>ul>li>a {
background-color: yellow;
}
div {
margin-bottom: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
random link
random link
random link
</div>
<br />
<div id="points">
<ul>
<li>.
</li>
<li>.
</li>
<li>.
</li>
</ul>
</div>
<br />
<br />
<br />
<div>
random link
random link
</div>
Include a selector before :eq()
$('#points ul li a').on('click', function(event) {
var el = $(event.target);
if (el.is('a:eq(0)')) {
alert('0') // and do something
}
if (el.is('a:eq(1)')) {
alert('1') // and do something
}
if (el.is('a:eq(2)')) {
alert('2') // and do something
}
})
#points ul {
list-style: none;
font-size: 5em;
padding: 0;
margin: 0;
line-height: .5em;
}
#points ul li {
float: left;
}
#points ul li a {
text-decoration: none;
color: grey;
padding: .1em;
line-height: .1em
}
#points {
position: relative;
margin: 0 auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="points">
<ul>
<li>.
</li>
<li>.
</li>
<li>.
</li>
</ul>
</div>
<script
Try this
var items = $('#points li a');
$('#points ul li a').on('click', function(event) {
var currentItem = event.currentTarget
if (items.index(currentItem) === 0) {
alert('0') ;
}
if (items.index(currentItem) === 1) {
alert('1') ;
}
if (items.index(currentItem) === 2) {
alert('2');
}
})
#points ul {
list-style: none;
font-size: 5em;
padding: 0;
margin: 0;
line-height: .5em;
}
#points ul li {
float: left;
}
#points ul li a {
text-decoration: none;
color: grey;
padding: .1em;
line-height: .1em
}
#points {
position: relative;
margin: 0 auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="points">
<ul>
<li>.
</li>
<li>.
</li>
<li>.
</li>
</ul>
</div>

Looking for ways to refactor my jQuery code for a div toggle I created

I wrote some code with three things in mind:
Highlighting a selection's border using 'on click'.
Selecting one item will remove the highlight from the other item.
The ability to deselect each item on click.
I've managed to get everything working for the most part, but I don't particularly like how complex the code is for the radial dot that appears when one item is selected.
Below is an example of what I'm talking about, particularly I'm looking for ways to refactor the code below into something a little more legible (shorter).
$(this).children('.radial').children().toggleClass('checked').parents('.itembox')
.siblings().children('.radial').children().removeClass('checked');
Here's a working example for more context (line 10):
var raceInternet = false;
var racePhone = false;
var raceTv = false;
$(function() {
var $targetDiv = $('#race-internet > .itembox');
var $radialDot = $('.radial > .center-dot');
$targetDiv.on('click', function() {
$(this).toggleClass('user-selected').siblings().removeClass('user-selected');
//Is it possible to refactor Line 10?
$(this).children('.radial').children().toggleClass('checked').parents('.itembox').siblings().children('.radial').children().removeClass('checked');
if ($targetDiv.is('.user-selected')) {
raceInternet = true;
} else {
raceInternet = false;
}
})
})
.itembox-container {
display: flex;
}
.boxes-2 {
width: calc((100% - 25px)/2);
margin: 10px;
padding: 10px;
}
.itembox {
position: relative;
display: inline-block;
border: 5px solid #e8e8e8;
border-radius: 10px;
cursor: pointer;
}
.user-selected {
border: 5px solid #E16E5B;
}
.itembox h4 {
color: #22ddc0;
font-weight: 700;
}
span.price {
display: inline-block;
font-weight: 400;
float: right;
color: #22ddc0;
}
.itembox > ul {
list-style: none;
}
.itembox > ul > li {
line-height: 3;
}
.radial {
position: absolute;
float: right;
height: 35px;
width: 35px;
padding: 2px;
border: 5px solid #e8e8e8;
border-radius: 50%;
top: 43%;
right: 10px;
}
.center-dot {
display: none;
position: relative;
height: 21px;
width: 21px;
background-color: #E16E5B;
border-radius: 50%;
}
.checked {
display: block;
}
.prime-aux:first-of-type {
top: 150px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="container">
<!-- Primary Content Container -->
<div class="prime-aux">
<div id="race-internet" class="itembox-container">
<div class="itembox boxes-2">
<h4>Gigabit Internet <span class="price">$60/mo</span></h4>
<ul>
<li>1,000 Mbps</li>
<li>No data caps</li>
</ul>
<div class="radial">
<div class="center-dot"></div>
</div>
</div>
<div class="itembox boxes-2">
<h4>Basic Internet <span class="price">$25/mo</span></h4>
<ul>
<li>25 Mbps</li>
<li>No data caps</li>
</ul>
<div class="radial">
<div class="center-dot"></div>
</div>
</div>
</div>
</div>
</section>
<!-- Primary Content Container End -->
View on JS Fiddle
You can eliminate a lot of your jQuery by just leveraging CSS. Typically, if I want to toggle a feature, I have it either display: block; or display: none; based upon a CSS selector. Then, I just use jQuery to toggle the parent element's class name. So for example:
.item.selected .checkmark {
display: block;
}
.item .checkmark {
display: none;
}
$('.item').click(function(){ $(this).toggleClass('selected') });
JSFiddle

Make element hover when unhovering, add close button so it remembers cookies?

I am trying to make a tooltip, but I need it to stay hovering when user unhovers.
Also, I am trying to add a close button to that tooltip, that will stay with the "hover state" and when user clicks on it, I want to make it to remember cookies so it will not open again for that cookie.
I am a novice at javascript and jQuery and have been breaking my mind on this for several days now.
Here is my code:
#charset "utf-8";
/* Tooltip CSS Created By Deni*/
.tooltip-container {
width: 400px;
height: 300px;
background: #DBDBDB;
border: 1px solid black;
margin: 10% auto;
}
/* Start the tooltip css */
.tooltip {
position: relative;
z-index: 9998;
cursor: help;
}
.tooltip > span {
display: none;
}
.tooltip:hover {
z-index: 9999;
}
.tooltip:hover .tooltip-data {
display: block;
width: 150px;
padding: 5px;
color: #dadada;
background-color: #A35FA1;
font-size: 11px;
border-radius: 5px;
text-decoration: none;
font-family: century gothic;
position: absolute;
bottom: 20px;
left: -10px;
text-align: center;
}
.tooltip-container > a {
margin-right: 10px;
}
.permhover {
display: block;
opacity: 1;
}
**HTML:**
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Tooltip</title>
<link href="tooltip.css" rel="stylesheet" type="text/css" />
<script src="jquery-1.11.3.min.js" type="text/javascript"></script>
</head>
<body>
<div class="tooltip-container">
This is the information<span class="tooltip-data"> This is one Tooltip!</span>
This is the information <span class="tooltip-data"> This another one Tooltip!</span>
</div>
</body>
</html>
I know that is not much but all the help is appreciated. Thank you very much.
First of all you need to change all lines in css from ".tooltip:hover" to ".tooltip.hover".
Next you need to add <button class="btn-close"></button> to your tooltip (this button will close this tooltip)
Then you need to add jquery code, that will add class hover to tooltip when you hover it.
(function(){
$('.tooltip').each(function(){
var tooltip = $(this);
var tooltipId = tooltip.attr('id');
if( !getCookie(tooltipId) ) {
tooltip.on('mouseenter.tooltip', function(){
tooltip.addClass('hover');
tooltip.find('.btn-close').on('click', function(){
var date = new Date();
date.setDate(date.getDate() + 1);
tooltip.removeClass('hover').off('mouseenter.tooltip');
document.cookie = tooltipId + "=true; path=/; expires=" + date.toUTCString();
});
});
}
});
function getCookie(name) {
var matches = document.cookie.match(new RegExp("(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"));
return matches ? decodeURIComponent(matches[1]) : undefined;
}
})();
A possible solution of this would be to register the onmouseout event on the links and display your tooltip.
You could add a x by adding a span to the .tooltip-data.
Then use jQuery to active the tooltip on mousehover and remove it by a click on the x span.
$(function() {
$('.tooltip').on('mouseover', function() {
$(this).find('span').show().append('');
});
$('.tooltip-data span').on('click', function() {
$(this).parent().hide();
});
});
#charset "utf-8";
/* Tooltip CSS Created By Deni*/
.tooltip-container {
width: 400px;
height: 300px;
background: #DBDBDB;
border: 1px solid black;
margin: 10% auto;
}
/* Start the tooltip css */
.tooltip {
position: relative;
z-index: 9998;
cursor: help;
}
.tooltip > span {
display: none;
}
.tooltip:hover {
z-index: 9999;
}
.tooltip-data {
display: block;
width: 150px;
padding: 5px;
color: #dadada;
background-color: #A35FA1;
font-size: 11px;
border-radius: 5px;
text-decoration: none;
font-family: century gothic;
position: absolute;
bottom: 20px;
left: -10px;
text-align: center;
}
.tooltip-data span {
float: right;
}
.tooltip-container > a {
margin-right: 10px;
}
.permhover {
display: block;
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="tooltip-container">
<a href="javascript:;" class="tooltip">
This is the information
<span class="tooltip-data"> This is one Tooltip! <span> x </span></span>
</a>
<a href="javascript:;" class="tooltip">
This is the information
<span class="tooltip-data"> This another one Tooltip!<span> x </span></span>
</a>
</div>

jQuery dropdown advice

I'm currently trying to build a quick dropdown prototype with jQuery and I'm probably at the limit of my jQuery knowledge so I was hoping for some help in solving my problem.
What I'm aiming to achieve: when the user hovers over a link, a dropdown animates down, when the user clicks another link, the next dropdown animates over the top and so on.
Here's the HTML:
<div class="wrapper">
<div class="dropdowns">
<ul>
<li class="call">Call</li>
<li class="chat">Chat</li>
<li class="message">Send a message</li>
</ul>
</div>
<div class="slide call-panel">
<h1>Call now</h1>
</div>
<div class="slide chat-panel">
<h1>Online chat</h1>
</div>
<div class="slide message-panel">
<h1>Send us a message</h1>
</div>
</div>
CSS:
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.wrapper {
max-width: 1200px;
margin: 0 auto;
}
.dropdowns {
overflow: hidden;
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
display: inline;
}
.call a {
background: #f1f1f1;
}
.chat a {
background: #e1e1e1;
}
.message a {
background: #f1f1f1;
}
a {
display: block;
width: 33.333%;
height: 50px;
line-height: 50px;
text-align: center;
float: left;
}
.call-panel {
height: 300px;
background: darkgrey;
display: none;
}
.chat-panel {
height: 300px;
background: darkgrey;
display: none;
}
.message-panel {
height: 300px;
background: darkgrey;
display: none;
}
h1 {
margin: 0;
padding: 0;
}
JS:
$( ".call a" ).click(function() {
toggleSlides( ".call-panel" );
});
$( ".chat a" ).click(function() {
toggleSlides( ".chat-panel" );
});
$( ".message a" ).click(function() {
toggleSlides( ".message-panel" );
});
function toggleSlides(slide){
$(".slide").slideUp ( "slow", function(){
$(slide).slideDown( "slow" );
} );
}
I've set up a quick fiddle here of what I have currently, but as you'll see it's not quite working how I intended, I'm getting animations coming up rather than down, some crazy repeat animations, all sorts - any help would be great!
Link: http://jsfiddle.net/2zwjZ/
you can do this with jquery this.hash;
$('.dropdowns li a').removeClass('active');
$('.dropdowns li a').click(function(){
var tabDiv = this.hash;
$('.slide').hide();
$(this).addClass('active');
$(tabDiv).slideDown();
return false;
});
updated jsFiddle File

Categories