Toggle Back and Forth Between Two Active Tabs On Click - jQuery - html

Basically I have two tabs - I'd like to toggle back and forth between styles when one or the other gets clicked.
Initially, the left tab is 'active' and the right tab is 'inactive'. Active has a blue background, inactive has a grey background.
JSFiddle
With my logic, I'm trying to say, if the tab is currently active when clicked on, do nothing.
Otherwise, turn the tab that's been clicked on into an active tab and the other tab into an inactive tab:
function toggleActive () {
$(document).on('click', '.tab-tab', function () {
//if the element that's clicked on has the class 'active',
//prevent anything from happening
if ($(this).hasClass('active')) {
event.preventDefault();
}
//otherwise, switch the active class to the tab that's clicked on,
//and make the other tab inactive
else {
$(this).toggleClass("active");
$(this).siblings('.tab-tab').toggleClass('inactive');
}
});
}
toggleActive();
.my-card-table {
width: 100%;
border: 1px solid #D9D7D6;
table-layout: fixed!important;
}
.exam-or-tutorial-tabs {
display: flex;
cursor: pointer;
}
.exams-tab {
border-top-left-radius: 3px;
}
.tutorial-tab {
border-top-right-radius: 3px;
}
.tab-tab {
font-family: "Proxima Nova Bold";
display: flex;
padding: 10px 20px 10px 20px;
color: #000000;
}
.tab-tab.active {
background-color: #1481C3;
}
.tab-tab.inactive {
background-color: #a7a7a7;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="my-card-table">
<div class="exam-or-tutorial-tabs">
<div class="exams-tab tab-tab active">Exams</div>
<div class="tutorial-tab tab-tab inactive">Tutorial</div>
</div>
</table>
It's only (partially) working once, then fails. Can you please explain why that's the case?

Replace the Javascript code with the below code:
$(document).on('click', '.tab-tab.inactive', function () {
$(this).siblings('.tab-tab').removeClass('active').addClass('inactive');
$(this).removeClass('inactive').addClass("active");
});

Related

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

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>

Why does the condition in the function not work?

Why does the condition in the function not work?
Please tell me why the .not() condition does not work.
$(".one").not(".two").on("click", function() {
console.log("click one");
})
.one {
width: 500px;
height: 300px;
background: grey;
position: relative;
}
.two {
background: red;
position: absolute;
top: 20px;
right: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="one">
<input type="file" class="two">
</div>
That's because of event bubbling.
When you click on .two, as it is a child of .one, the click event happens also on .one
To prevent this, you can use event.stopPropagation() but it might not be the right choice as it - indeed - stops the event propagation to every other element, and this could not be desirable if there are other events you listen to in your code and introduce bugs. Stopping propagation of events is something that should be used carefully:
Dangers of stopping Event propagation
Pros/Cons of using e.stopPropagation()
Another - and in my opinion preferred - option is to use the event.currentTarget and event.target. The first is the element to which the event is attached (.one in your case). The second is the actual HTML element that has been clicked.
So, you can check if the event.target is two or one and code different behavior for each alternative.
$(".one").on("click", function(event) {
console.log("event.target is: ", event.target);
console.log("event.currentTarget is: ", event.currentTarget);
if ($(event.target).hasClass('two')) {
console.log("Mmh... you clicked two, please click one");
} else if ($(event.target).hasClass('one')) {
console.log("YEAH! You clicked one this time");
}
})
.one {
width: 500px;
height: 300px;
background: grey;
position: relative;
}
.two {
background: red;
position: absolute;
top: 20px;
right: 0px;
}
.as-console-wrapper { max-height: 4.5em !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="one">
<input type="file" class="two">
</div>
$(".two").on("click", function(e) {
e.stopPropagation();
})

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>

Start Content from bottom of container and push up

So what I'm trying to accomplish seems like easy CSS etc. Im changing a messaging system and what the conversations to start at the bottom sorta like Facebook or text message where it has one person on the left and the other on the right.
How do I get the divs to go up as new content is added via ajax? I saw this similar question but didn't quite understand what he mean focus on the LI. An example would be great.
Something like this perhaps?
<!DOCTYPE html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e);}
function newEl(tag){return document.createElement(tag);}
function newTxt(txt){return document.createTextNode(txt);}
function prependChild(parent, element)
{
if (parent.childNodes)
parent.insertBefore(element, parent.childNodes[0]);
else
parent.appendChild(element)
}
window.addEventListener('load', mInit, false);
function mInit()
{
byId('btnAddNew').addEventListener('click', onAddBtnClicked, false);
}
function onAddBtnClicked()
{
var txtInputElem = byId('newMsgTxtInput');
var msgTxt = txtInputElem.value;
var li = newEl('li');
li.appendChild( newTxt( msgTxt ) );
var ulTgt = byId('msgTarget');
var existingLiItems = ulTgt.querySelectorAll('li');
var numItemsExisting = existingLiItems.length;
if (numItemsExisting%2 != 0)
li.className = 'even';
else
li.className = 'odd';
prependChild(ulTgt, li);
}
</script>
<style>
.controls
{
display: inline-block;
padding: 8px;
margin: 8px;
border: solid 1px #555;
border-radius: 4px;
color: #777;
background-color: #ddd;
}
#msgTarget
{
width: 275px;
border: solid 1px #555;
margin: 8px;
border-radius: 4px;
}
/*
Doesn't work 'properly' - since we add items at the top, rather than the bottom
The first item added will be 'even', then the second item gets added and now it's the first child 'even'
so, the item added first is now an 'odd' child. A better way may be to count the number of existing li
items the ul contains, before assigning the new li elements a class of even or odd that will enable css
styling.
#msgTarget li:nth-child(odd)
{
background-color: #CCC;
}
#msgTarget li:nth-child(even)
{
background-color: #5C5;
}
*/
.odd
{
background-color: #CCC;
}
.even
{
background-color: #5C5;
}
</style>
</head>
<body>
<div class='dlg'>
<div class='controls'>
<input id='newMsgTxtInput'/><button id='btnAddNew'>Add message</button>
</div>
<ul id='msgTarget'></ul>
</div>
</body>
</html>

Get away with built-in dragging html elements

I have a problem with html-objects that moving when I´m dragging them, you know the transparent "ghost" -copy of the element that appears when you holding down the mouse and drag it. My problem is that it interrupt my mouse event. I have a image that should be able to move inside a div when you dragging it with the mouse. I have to events for that, first one for mousedown that trigger mousemove-event, mousemove handles the movement of the image. mousedown is no problem but when I´m moving the mouse with the button down the transparent "ghost" - copy of the elements appear and interrupt my mousemove-event. Is that any one how knows how to get around or fix this thing?
Could you provide a sample?
From what it sounds like, the first thing to check is that the events are actually being hit. Writing messages out to console whenever each event fires should help prove or disprove that the events are occurring as-expected.
Then you start your mousemove event, set a timeout for the appended class 'hide' in 0 ms. Its work.
const dragAndDrop = () => {
const card = document.querySelector('.dragDrop');
const cells = document.querySelectorAll('.block');
const dragStart = function () {
// i added timeout for appended class
setTimeout(() => {
this.classList.add('hide');
}, 0);
};
const dragEnd = function () {
// i added timeout for appended class
setTimeout(() => {
this.classList.remove('hide');
}, 0);
};
const dragOver = function (event) {
event.preventDefault();
}
const dragEnter = function (event) {
event.preventDefault()
this.classList.add('hovered');
}
const dragLeave = function () {
this.classList.remove('hovered');
}
const dragDrop = function () {
this.append(card);
this.classList.remove('hovered')
}
cells.forEach((cell) => {
cell.addEventListener('dragover', dragOver);
cell.addEventListener('dragenter', dragEnter);
cell.addEventListener('dragleave', dragLeave);
cell.addEventListener('drop', dragDrop);
})
card.addEventListener('dragstart', dragStart);
card.addEventListener('dragend', dragEnd);
}
dragAndDrop()
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
width: 100%;
height: 100vh;
display: flex;
justify-content: space-around;
padding-top: 20px;
}
.block{
width: 100px;
height: 100px;
background-color: rgb(99, 99, 99);
display: flex;
justify-content: center;
align-items: center;
}
.card{
width: 80px;
height: 60px;
background-color: black;
cursor: grab;
}
.hide {
display: none;
}
.hovered {
background-color: rgb(254, 164, 164);
}
<div class="block">
<div draggable="true" class="drag dragDrop">
<div class="card"></div>
<div class="text">Hello, world</div>
</div>
</div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
I wrote this 12 years ago but if I remember right the solution was something like,
imageElement.addEventListener('dragover', function(e) {
e.preventDefault()
});
This should prevent the user from clicking and dragging on the image which means the browser won't add any visual effects.