modal not opening when user clicks on modal trigger - javascript

I have a pretty basic modal function on my website which displays a like, repost & comment modal, above the track, in which trigger has been clicked.
However, I have had to set it up in an odd way due to the tracks being displayed procedurally through PHP.
This is my simplified markup:
<div class="f-wave-send">
<div class="t__trigger-actions"> <!-- this is the modal trigger button !-->
<span id="trigger-actions-modal"></span>
</div>
<div class="f-track__actions" id="track-actions"> <!-- this is the modal !-->
<div class="close-actions"> <!-- this is the close button !-->
<span></span>
</div>
<div class="f-track-actions-inner">
<!-- modal contents !-->
</div>
</div>
</div>
This markup is duplicated across the page (to represent each track within the database); similar to Facebook's feed.
This is the JS which controls all the modals functionalities:
$(".t__trigger-actions").click(function(){ // when one of the modal triggers is clicked
var parent = $(this).parent();
parent.find(".f-track__actions").css("display", "block"); // get the modal within ONLY the same container to display
parent.addClass("modal__open"); // and add the class modal__open to the container
});
$(".close-actions").click(function(){ // when the close button is clicked
$(".modal__open").children(".f-track__actions").css("display", "none"); // hide the modal
$(".f-wave-send").removeClass("modal__open"); // remove the modal__open class from the container
});
$(document).bind('click', function(e) { // if user clicks on anything but the main container
if(!$(e.target).is('.modal__open')) {
$(".modal__open").children(".f-track__actions").css("display", "none"); // hide the modal
$(".f-wave-send").removeClass("modal__open"); // remove the modal__open class from the container
}
});
I have commented where possible trying to explain what is going on. But I'll explain here once again;
When a user clicks on one of the many modal triggers within the document, it will get that triggers modal, and display it (and add the class modal__open to it's parent container).
If a user clicks on the close button (or on the document), close that same modal.
I've been stuck trying to figure this out for a little while now, so all help (and suggestions) are appreciated.
Thanks.
EDIT:
What I want to happen is, when the modal opens, it ONLY closes when the user clicks out of the modal, OR on the close button (if that makes sense).

Is this what you want?
- Added closest() instead of parent just in case its not a direct parent.
- Added e.stopPropagation() to the 'open' button.
$(document).ready(function() {
$(".t__trigger-actions").click(function(e) {
var topClass = $(this).closest('.f-wave-send');
topClass.find(".f-track__actions").css("display", "block");
topClass.addClass("modal__open");
$(this).next().addClass("modal__open");
e.stopPropagation();
});
$(".close-actions").click(function() {
$(".modal__open").children(".f-track__actions").css("display", "none");
$(".f-wave-send").removeClass("modal__open");
});
$(document).bind('click', function(e) {
var container = $(".modal__open");
if (!container.is(e.target) && container.has(e.target).length === 0) {
$(".modal__open").children(".f-track__actions").css("display", "none");
$(".f-wave-send").removeClass("modal__open");
$(".f-track__actions").removeClass("modal__open");
}
});
})
.f-track__actions {
display: none;
}
.f-wave-send {
border: 2px solid red;
}
.t__trigger-actions {
height: 40px;
border: 1px solid green;
}
.f-track__actions {
height: 60px;
border: 1px solid blue;
}
.close-actions {
display: inline-block;
width: 50px;
height: 30px;
background-color: #ddd;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="f-wave-send">
<div class="t__trigger-actions">
<!-- this is the modal trigger button !-->
<span id="trigger-actions-modal">Open</span>
</div>
<div class="f-track__actions" id="track-actions">
<!-- this is the modal !-->
<div class="close-actions">
<!-- this is the close button !-->
<span>Close</span>
</div>
<div class="f-track-actions-inner">
<input/>
<!-- modal contents !-->
</div>
</div>
</div>

Related

Show and keep div visible while action is within div or input field?

I want to show a div under input field when user click/focus a input field and hide the div when focus is out or User clicks outside the div or input field.
In this fiddle example, when i click input, a div is shown and when i click outside the input field it gets hidden.
But i want to keep the div visible in below conditions :
1. When input is focused/clicked.
2. When click is within the div(.options).
The div should be hidden when:
1. Input is unfocused and click in not within div.
2. Click outside div.
Fiddle URL
You can try using relatedTarget like the following way:
$(function () {
var inputField = $('#input_field');
var optionsResult = $('#options');
inputField.focusin(function (e) {
e.preventDefault();
optionsResult.show();
}).focusout(function (e) {
if(e.relatedTarget){
if(e.relatedTarget.tagName != 'A')
optionsResult.hide();
}
else{
optionsResult.hide();
}
});
});
$(document).on('click', function(e){
if(e.target.tagName == 'HTML'){
$('#options').hide();
}
});
.options{
display:none;
position: absolute;
float: left;
width: 300px;
height: 200px;
background: #eee;
}
a{
display:block;
float: left;
width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="app">
<div class="header">
<div id="main_container" class="box">
<div class="inputs">
<input id="input_field" type="text" placeholder="Demo account"/>
</div>
<div id="options" class="options">
Common Link
Common Link 2
</div>
</div>
</div>
<div class="Data">
Another Data Set
</div>
</div>
make sure the body tag contains your app and it's full width and height of the window. add en event listener to see if the click event is outside of the options div and not the input field. hide the options div if that is the case.
JsFiddle
body {
height: 100vh;
width: 100%;
}
$(function () {
var inputField = $('#input_field');
var optionsResult = $('#options');
var options = document.querySelector('#options');
// Listen for click events on body
document.body.addEventListener('click', function (event) {
// hide options if click is outside of options div and not the input element
if (!options.contains(event.target) && event.target.id !== 'input_field') {
optionsResult.hide();
}
});
inputField.focusin(function (e) {
e.preventDefault();
optionsResult.show();
});
});

How can I delete an editable div by clicking on it and then pressing the Delete key on the keyboard with Jquery?

I have a div with the attribute contenteditable = true. I can activate the div content editing by double clicking the div, this is because my div is draggable, so I use the dooble click event to activate the div edition. The fact is that I want to eliminate the complete div by clicking on it and then pressing the Delete key on the keyboard. How can I do that? How can I make it so that when I write something on the div and press the delete key, the entire div will not be deleted? I only want to delete the div when the div edition is not activated, just click on the div and then hit the delete key and voila, it is deleted.
This is my HTML Code:
$(document).ready(function() {
$('.draggable').draggable({
containment: "parent"
});
$(".draggable").resizable();
$('#MyFirstDiv').click(function() {
//HERE I WANT TO PUT THE CODE TO DELETE THE DIV.
});
$("#myContainer").on("dblclick", "#MyFirstDiv", function(e) {
e.preventDefault();
$(".draggable").draggable('disable');
this.querySelector(":scope > :first-child").focus();
});
$("#myContainer").on("blur", "#MyFirstDiv", function(e) {
e.preventDefault();
$(".draggable").draggable('enable');
});
});
#myContainer {
border: 1px solid black;
height: 400px;
width: 100%;
}
#DraggableDiv {
border: 1px solid blue;
}
<!DOCTYPE html>
<html>
<head>
<title>My Delete Div</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
</head>
<body>
<div id="myContainer">
<div id="MyFirstDiv">
<div class="draggable" contenteditable="true" id="DraggableDiv">
THIS IS MY TEXT INSIDE THE DIV
</div>
</div>
</div>
</body>
</html>
Easiest way to to capture the keydown on the delete key.
$('#MyFirstDiv').click(function(e){
e.preventDefault();
});
$('#MyFirstDiv').keydown(function(e){
e.preventDefault();
if(e.keyCode == 46) {
this.remove();
}
});
You could first just make a variable: divClicked, I store the clicked state of the div
var divClicked = false;
Then in your event listener, update divClicked (it'll be a toggled button):
$("#MyFirstDiv").click(function(e) {
e.preventDefault();
divClicked = !divClicked;
}
Finally, add a delete key event listener like so:
$("#MyFirstDiv").keydown(function(e) {
e.preventDefault();
if (e.keyCode == 46) {
if (divClicked) {
$(this).remove();
} else {
alert("Click the div first then press Delete to remove it");
}
}
})
Full code:
var divClicked = false;
$("#MyFirstDiv").click(function(e) {
e.preventDefault();
divClicked = !divClicked;
}
$("#MyFirstDiv").keydown(function(e) {
e.preventDefault();
if (e.keyCode == 46) {
if (divClicked) {
$(this).remove();
} else {
alert("Click the div first then press Delete to remove it");
}
}
})
It is not advisable to use Delete while the content is being edited. You will want to ensure that the user can click the <div> element itself without editing the content.
Since the <div> is draggable, I would advise using a handle since the click event and keypress events may get capture for content editing and not for your script.
$(function() {
function disDrag(part) {
var drag = part.closest(".draggable");
drag.draggable("disable");
$(".drag-content", drag).removeAttr("contenteditable").blur();
part.toggleClass("ui-icon-locked ui-icon-unlocked");
}
function enDrag(part) {
var drag = part.closest(".draggable");
drag.draggable("enable");
$(".drag-content", drag).attr("contenteditable", true).focus();
part.toggleClass("ui-icon-locked ui-icon-unlocked");
}
function delDrag(part) {
var drag = part.closest(".draggable");
var res = confirm("Are you sure you wish to delete this item?");
if (res) {
drag.remove();
}
}
$('.draggable')
.draggable({
containment: "parent",
handle: ".ui-drag-handle",
start: function() {
$(".ui-drag-handle", this).data("selectable", false);
},
stop: function() {
$(".ui-drag-handle", this).data("selectable", true);
}
})
.resizable();
$(".ui-drag-handle")
.data("selectable", true)
.click(function(e) {
var drag = $(this).closest(".draggable");
if ($(this).data("selectable")) {
drag.toggleClass("drag-selected");
}
});
$(".btn").click(function(e) {
switch (true) {
case $(this).hasClass("ui-icon-unlocked"):
disDrag($(this));
break;
case $(this).hasClass("ui-icon-locked"):
enDrag($(this));
break;
case $(this).hasClass("ui-icon-close"):
delDrag($(this));
break;
}
});
$(document).keyup(function(e) {
if (e.which == 46 && $(".drag-selected").length) {
delDrag($(".drag-selected"));
}
});
});
#myContainer {
border: 1px solid black;
height: 400px;
width: 100%;
}
.draggable {
border: 1px solid blue;
}
.draggable.drag-selected {
border: 1px solid #0f0;
}
.center {
margin-left: 50%;
}
.right {
float: right;
}
.ui-icon.btn {
border: 1px solid #ccc;
border-radius: 3px;
margin-top: 0px;
margin-left: 1px;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<div id="myContainer">
<div class="draggable ui-widget" id="DraggableDiv">
<div class="ui-widget-header">
<span class="right ui-icon ui-icon-close btn" title="Delete the item."></span>
<span class="right ui-icon ui-icon-unlocked btn" title="Lock and disable Drag"></span>
<div class="ui-drag-handle" style="width: calc(100% - 42px);">
<span class="center ui-icon ui-icon-grip-dotted-horizontal"></span>
</div>
</div>
<div class="drag-content" contenteditable="true">
THIS IS MY TEXT INSIDE THE DIV
</div>
</div>
</div>
You can see that this is draggable, resizable, and editable. The user can disable drag by clicking the lock icon. If the select the div and click Delete (or key code 46), or they click the close icon, they will be prompted to confirm that they want to delete the item. Once they confirm that Yes they want to, the item is removed.
Since the delete could be triggered by two different ways, I created a delete function.
In regards to structure, you may not be able to get away with such simple HTML structures when dealing with more complex UI interactions. This one <div> element had all sorts of interactions tied to the click event. The user clicks to edit, select, drag... It is better to make more specific targets for some of these events so that you can better script your events.
You could save yourself a lot of time by using Dialog Widget: https://jqueryui.com/dialog/
Hope that helps.
Test
Click on the text to select.
Press D to delete. [sadly delete key didn't work on stack overflow. Simply change the key code in the if statement to change the key from D to DELETE]
Explanation
There are two functions that help solve this problem.Select: Selected the div clicked.EventListener:Listens for the keypress and deletes the selected div.
Select function
Global variable selected stores the information on the div selected.
In select function we are fetching the id name of the div clicked by using currentTarget.id from the event object 'e'.
If statements inside the select function select and deselect the div.
EventListener
Uses event object from the keypress listener to fetch the key pressed.
e.keyCode gives the key. e.which is a fallback. [for ie users]
If they keyCode is 100 (D key), then use the selected variable to get the selected div and change its css display to 'none'.
Additionally there is a else statement, where u can add js to when nothing is selected and the key is pressed.Also the css for class selected is for feedback of when the div is selected.
Here is the code snippet:
let selected;
const select = e => {
//If already selected, this will deselect the div
if(selected == e.currentTarget.id) {
document.getElementById(selected).classList.remove('selected'); //some CSS
selected = null;
} else {
//select this div
selected = e.currentTarget.id;
document.getElementById(selected).classList.add('selected'); //some CSS
}
}
window.addEventListener('keypress', e => {
//Get key pressed
let key = e.keyCode || e.which;
if(selected != undefined) {
if(key == 100) {//If D is pressed
let target = document.getElementById(selected); //get the div
target.style.display = 'none'; //hide div
console.log('deleted: ' + selected);
}
} else {
//Runs if nothing is selected. Do as you please here.
}
})
.selected {
background: black;
color: white;
}
#DraggableDiv {
user-select: none;
cursor: pointer;
font-family: sans-serif;
width: 400px;
text-align: center;
padding: 10px 5px;
}
<!DOCTYPE html>
<html>
<head>
<title>My Delete Div</title>
</head>
<body>
<div id="myContainer">
<div id="MyFirstDiv">
<div id="DraggableDiv" onclick="select(event)">
Click me and press D
</div>
</div>
</div>
</body>
</html>

How to keep changes in the same element even when page is changed using javascript?

In my web application there is a left menu that is of very big size. I have placed a button to make small it. Everything is working when I click on button my menu is being hidden and another small menu is being shown. When I click on any link in small menu, another page is loaded and big menu is shown. If I want to see small menu again I need to click button. I want that if any page is loaded, menu should be shown in last form that was on last page (It can be big also if it was in big form on last page).
My code is here
HTML
<div class="flLeft similarHeight">
<ul class="nav metismenu" id="side-menu">
<li class="nav-header">
<div class="logo">Brand Name</div>
</li>
</ul>
</div>
<div class="flLeftsmall">
<ul class="nav smallnavigation">
<li class="nav-header">
<div class="logo">Brand</div>
</li>
</ul>
</div>
<div class="pull-left">
<span><i class="glyphicon glyphicon-triangle-left menu-big"></i></span>
</div>
CSS
.flLeft {
background:#1b3b5e;
width: 220px;
height: 200px;
}
.flLeftsmall {
display: none;
background:#1b3b5e;
width: 80px;
height: 200px;
color: #fff;
}
a{color: #fff;}
jQuery
$(document).ready(function () {
$('.menu-big').click(function () {
$(this).toggleClass('glyphicon-triangle-right glyphicon-triangle-left');
$('.flLeft').toggle('slide');
$('.flLeftsmall').toggle('slide');
});
});
I am using bootstrap and jQuery plugins properly.
You can see my jsfiddle here.
Please help me.!
Can be achieved using sessionStorage or LocalStorage. It's not elegant, but it works.
Within your click event for collapsing the menu, add a storage item to save the state of the menu
sessionStorage.setItem('menuSize', 'small'); // Or big etc, will need to break this up into two click events.
Then on the pages subsequent, check this storage item to see whether the user has chosen the small or bigger menu.
if (sessionStorage.getItem('menuSize') == 'small') {
$('.flLeft').css("display", "none");
$('.flLeftsmall').css("display", "block");
}
Updated fiddle: https://jsfiddle.net/5vjf0ffs/2/
Try this
It uses localStorage. To store value and then use it to check if we shall display either the small or big box.
$(document).ready(function() {
if (localStorage.getItem("slide") == "small") {
$('.flLeft').toggle('slide');
$('.flLeftsmall').toggle('slide');
}
$('.menu-big').click(function() {
$(this).toggleClass('glyphicon-triangle-right glyphicon-triangle-left');
if (localStorage.getItem("slide") == null) {
localStorage.setItem("slide", "small");
} else {
localStorage.removeItem("slide");
}
$('.flLeft').toggle('slide');
$('.flLeftsmall').toggle('slide');
});
});

JQuery Hamburger Menu Functions

Below is the script I am trying to write to control two functions when the website's menu button is clicked; it is a hamburger menu that toggles the menu links. The first function shows/hides the menu links and the second fades an element on the page, both activated when the menu button is clicked.
In the first function, I am having trouble creating a delay/fadeIn for the menu links. I need '.navbar-item' to fade in and out when the menu is clicked. In the second function, I need to revert the opacity to 1.0 when the menu is clicked a second time. I can not get any of the effects to occur after the first effect has completed, i.e Menu is clicked to fade in menu links and dim '.values', menu is clicked to fade out menu links and revert '.values' to 100% opacity.
<div class="container">
<section class="header">
<h2 class="title">Title
<li class="client-item"><a class="client-link" href="#"><i class="fa fa-bars"></i></a></li></h2>
</section>
<nav class="navbar" style="display: none;">
<ul class="navbar-list">
<li class="navbar-item"><a class="navbar-link" href="#" target="_top">Contact</a></li>
<li class="navbar-item navbar-link">Store</li>
</ul>
</nav>
<div class="section values">
<div class="container">
<div class="row">
<div class="one-full column">
</div>
</div>
</div>
</div>
// Main Script For Site
$(document).ready(function() {
$('.client-link').click(function() {
$('.navbar').slideToggle("fast");
$('.values').animate({opacity:'0.6'});
});
});
This answer gives how to get simultaneous animations. jQuery's own docs describe slideToggle, including the bits you'd need to set similarly to how animate would need to be set.
I might also point out that there's no reason to separate the animate calls like you have. Since they're triggered by the same thing, they should be called from the same place.
Something like this, I think:
$(document).ready(function() {
$('.client-link').click(function() {
var $this = $(this);
var opening = !$this.data('isOpen');
$this.data('isOpen',opening);
if(opening) {
// opening animations
$('.navbar').slideDown({duration:'fast',queue:false});
$('.values').animate({opacity:1},{queue:false});
} else {
// closing animations
$('.navbar').slideUp({duration:'fast',queue:false});
$('.values').animate({opacity:0},{queue:false});
}
});
});
Though you may be better off moving your animations to CSS and just toggling a class.
You were very close, you have just made some simple mistakes. Here is a JSFiddle gives you a solution to your problem: https://jsfiddle.net/nv1gytrs/1/
HTML:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<div class="client-link"></div>
<div class="navbar"></div>
<div class="values"></div>
CSS:
.client-link {
height: 100px;
width: 100px;
border: 2px solid green;
}
.navbar {
height: 100px;
width: 100px;
border: 2px solid red;
}
.values {
height: 100px;
width: 100px;
border: 2px solid blue;
transition: all 1s;
}
.fade {
opacity: 0.2;
}
JS:
// Main Script For Site
$(document).ready(function() {
$('.client-link').on("click", function() {
$('.navbar').slideToggle("fast");
$('.values').toggleClass("fade");
});
});
Of course, all of your HTML and CSS would be unique to what you are trying to accomplish, this is just an example.

Weird event binding issue on FF and Chrome - only on first click

This is on my plugin page on Git and I have two interactive demo in the web page. In one of the demo page, I have a small dialog that opens when you click on a div.
The weird issue is that this dialog is getting opened when I click on the top title that says attrchange beta . This happens only if the first click is on the title attrchange beta, clicking any other element in page fixes this issue.
The plugin page http://meetselva.github.io/attrchange/ [Fixed, use the below URL to see the problem]
http://meetselva.github.io/attrchange/index_so_issue.html
Below is the code,
<!-- The title -->
<h1 id="project_title">attrchange <span class="beta" style="text-decoration: line-through;" title="Almost there...">beta</span></h1>
<!-- Main dialog that has link to the sub-dialog -->
<div id="attributeChanger">
<h4 class="title">Attribute Changer</h4>
<p>Listed below are the attributes of the div:</p>
<div class="attrList"></div>
<div class="addAttribute text-right">add new attribute</div>
</div>
<!-- Sub-dialog -->
<div id="addOrmodifyAttr" title="Add/Modify Attribute">
<h4 class="title">Add/Modify Attribute</h4>
<p><b>Attr Name</b> <input type="text" class="float-right attrName"></p>
<p><b>Attr Value</b> <input type="text" class="float-right attrValue"/></p>
<div class="clear"> </div>
<button type="button" class="float-right close">Close</button>
<button type="button" class="float-right update">Update</button>
<div class="clear"></div>
</div>
JS:
var $attributeChanger = $('#attributeChanger');
var $attrName = $('.attrName', '#addOrmodifyAttr'),
$attrValue = $('.attrValue', '#addOrmodifyAttr'),
$attrAMUpdate = $('.update', '#addOrmodifyAttr');
//Handler to open the sub-dialog
$attributeChanger.on('click', '.addAttribute', function () {
$attrName.val('').removeClass('nbnbg');
$attrValue.val('');
$('#addOrmodifyAttr, #overlay').show();
});
The problem is the CSS applied to your #attributeChanger div.
If you look at the CSS applied to it:
#attributeChanger {
background-color: #FEFFFF;
border: 1px solid #4169E1;
color: #574353;
font-size: 0.9em;
margin: 10px;
min-height: 50px;
min-width: 150px;
opacity: 0;
padding: 2px;
position: absolute;
top: -200px;
z-index: 1;
}
You'll notice that the position is absolute, and it's positioned over your logo. So what you're clicking is actually your #attributeChanger div.
To fix it, you can hide #attributeChanger using display: none;, then use $('#attributeChanger').show(); in jQuery when it comes into actual view.
The pop up is showing because this code is running:
}).on('click', '.addAttribute', function () {
$attrName.val('').removeClass('nbnbg');
$attrValue.val('');
$('#addOrmodifyAttr, #overlay').show();
This is because the DIV with the class addAttribute is over the title DIV.
You can either move the 'addAttribute' DIV, or remove the last line of that onclick function.
That is because you element is hover your title and detect the click on himself and open(i don't know why it open, i didnt examine your entire code). But when you click anywhere else, your code is changing his position so it is not over the title.
The easiest fix is to change you #attributeChanger CSS top to -100px (that's the value when you click on the document) OR add a display : none.
EDIT : Axel answer show what I mean by "element is hover your title".

Categories