I am trying to create a popup section that contains a form for someone to enter their email address when someone clicks on a link that says 'Mailing List.' The trouble is that when I click the link, the section doesn't appear. It works when I set it to hover but not click. I've run out of ideas on how to debug this. What am I missing?
HTML
<form class="mailing-list-input pull-right">
<input type="text" placeholder="Email Address" class="mailing-list-input">
<button class="mailing-list-btn">
<img src="/assets/arrow.png" style="height: 12px; width: 12px; margin-right: 6px;">
</button>
</form>
<footer class="footer footer-style">
<section class="container pull-right">
<ul class="list-inline btm-list">
<li class="btm-menu-width">
<a href="/" class="btm-menu-heading mailing-list">
Mailing List
</a>
</li>
</ul>
</section>
</footer>
CSS for .mailing-list-input
.mailing-list-input {
margin-right: 10rem;
display: none;
z-index: 98;
position: fixed;
bottom: 5rem;
right: 0;
}
Jquery File
$(document).ready(function() {
$(".mailing-list").click(function() {
$(".mailing-list-input").css('display', 'block');
},
function() {
$(".mailing-list-input").css('display', 'none')
})
})
The click function only accepts a single handler function. To achieve the behaviour you want, use a single handler and toggle() the element. Try this:
$(".mailing-list").click(function(e) {
e.preventDefault();
$(".mailing-list-input").toggle();
});
Example fiddle
Note I also added preventDefault() to stop the default link behaviour.
Based on what the OP appears to be trying to do this should be the Javascript:
$(".mailing-list").click(function(e) {
e.preventDefault();
if ($(".mailing-list-input").css('display') === 'block') {
$(".mailing-list-input").css('display', 'none');
} else {
$(".mailing-list-input").css('display', 'block');
}
});
The click handler callback takes an argument that is the event object, you can call preventDefault on that object to stop the event from continuing through its lifecycle. Then if you want the link to toggle the element on every click you check to see if the element is visible or not and set its value accordingly.
Here is a working fiddle
Related
I'm writing an event handler in Javascript on Codepen that will take a form input and add it to an unordered list. When trying to test, I get a "bad path /boomboom/v2/index.html" error message. I'm not sure if this error is a result of my code or an issue with Codepen. Can anyone point me to how to fix this?
I don't know what to try because I have not idea what this error means.
Here's the HTML:
<div class="card">
<div class="card-body">
<h3 class="card-title">Today's To Do List</h3>
<form id="todo-form">Week 5: To Do List
<div class="form-group">
<input type="text" class="form-control" id="todo-Week 5: To Do Listinput" placeholder="What else do you need to do?">
</div>
<div class="form-group">
<input type="submit" id="todo-btn" class="btn btn-secondary btn-block" value="Add Item To List">
</div>
</form>
</div>
<ul class="list-group list-group-flush" id="todo-ul">
<li class="list-group-item">Pick up groceries
<i class="fas fa-trash-alt"></i>
</li>
<li class="list-group-item">Finish essay
<i class="fas fa-trash-alt"></i>
</li>
<li class="list-group-item">Soccer # 5:00
<i class="fas fa-trash-alt"></i>
</ul>
Here's the CSS:
body
{
background-color: #34495e;
font-family: 'Lato', sans-serif;
}
button {
margin: 0 auto;
float: right;
}
.centered {
margin: 0 auto;
width: 80%
}
.card {
margin: 50px auto;
width: 18rem;
}
i{
float:right;
padding-top:5px
}
Here's the Javascript:
(function(){
//add event handler to form button
formButton = document.querySelector("#todo-btn");
formButton.onclick = addNewTodo;
function addNewTodo() {
//get value of form field
newTask = document.getElementById("todo-Week 5: To Do Listinput").value;
//console.log(newTask);
//create new ul list item element
const newItem = document.createElement('li');
const newItemContent = document.createTextNode(newTask);
//add new li element item to ul
newItem.appendChild(newItemContent);
document.getElementById("todo-ul").appendChild(newItem);
}
})();
Code can also be viewed on my pen at https://codepen.io/raquelocasio/pen/XwwKLZ
When I enter some text into the form field and click the button, the error displays.
The expected output is to be able to add the text entered in the form field as a new list item. Any help or pointers would be greatly appreciated.
it's due to the forms default behaviour which is to reload the page. In this case the error is related to codepen. You need to add the event preventDefault method to your addNewTodo function. You'll need to do this for most form submit events.
function addNewTodo(event) {
event.preventDefault()
// Rest of your add todo code here...
}
I saw a similar issue when I used <form> tags in Codepen. I switched the <form> tag to a <div> tag and the error went away.
Can you try this?
I got the same problem with a form on my codepen.io pen, but it got fixed when i changed button type="submit" to type="button".
It seems like this error (which is agreeably confusing - or enjoyably named) is brought up when a <form> is submitted in the sandbox. CodePen itself is a web application (built on rails I believe) with forms - and I'm not sure how that all plays out - but it probably has some scope to those - and can't just be having forms submitted to their server by its many many users.
Here is an example of an error: https://codepen.io/sheriffderek/pen/VwLQjZY
We've run across these a few times - but it has always been our fault - and when we've basically tried to submit a form - to a server we have no access to: (which can be unexpected - but makes sense)
and
are the messages we've seen. Does that mean 'poop' ? ; ) .... or...
and here is the documentation for preventing the default form submission https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault
and how to use that in a Pen: https://codepen.io/sheriffderek/pen/abOqZoM
element.addEventListener('click', function(event) {
event.preventDefault();
// some instructions etc.
});
We should tell the people there - and maybe they can detect the type of submission error and direct people to information on why it occurs. : )
Here is my code:
$(".drop-down-arrow-open i").click(function(){
console.log("click function for .drop-down-arrow-open is applied even when it is closed");
let thisParent = $(this).closest(".projects-container").find(".needed-while-hiding");
thisParent.hide();
$(this).closest(".drop-down-arrow-open").removeClass("drop-down-arrow-open").addClass("drop-down-arrow-closed");
$(this).removeClass("fa-chevron-down").addClass("fa-chevron-right");
});
$(".drop-down-arrow-closed i").click(function(){
console.log("This is never applied");
let thisParent = $(this).closest(".projects-container").find(".needed-while-hiding");
thisParent.show();
$(this).closest(".drop-down-arrow-closed").removeClass("drop-down-arrow-closed").addClass("drop-down-arrow-open");
$(this).removeClass("fa-chevron-right").addClass("fa-chevron-down");
});
span.drop-down-arrow-open, span.drop-down-arrow-closed{
font-size: 22px;
color: #636b6f;
float: right;
padding-right: 25px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
<div class="projects-container">
<h1>Project Name<span class="drop-down-arrow-open"><i class="fas fa-chevron-down"></i></span></h1>
<div class="needed-while-hiding">
<p class="description-background full-width adjust-properties">Description</p>
<div class="a-little-inside">
<ul class="list-without-bullets">
<li><span>Duration: </span><span>Some Duration</span></li>
<li><span>Roles: </span><span>Some Role related to development</span></li>
<li><span>Controller: </span><span>Pipeline</span></li>
<li><span>Official Website: </span>Random Link</li>
</ul>
</div>
</div>
</div>
In the above code, I am trying to open and close a drop down. I have two click functions, one for each open and close class. By default, the buttons have open class. At first, all drop downs are open by default, but when the fa-chevron-down is clicked, the close class is added and open is removed from the element using jQuery.
I have seen that in the web inspector, this logic works fine, but when the closed class is appended in the DOM, the click function of that class is never applied, instead the click function for open keeps on applying.
Am I missing something here. Please help me solve this issue. I am trying to make a portfolio, and I am stuck at this issue.
Note : By open class I mean, .drop-down-arrow-open and by close class I mean, .drop-down-arrow-closed.
Thanks in advance.
The issue is that $(selector) binds the click handler at the time it is called. So you're binding the closing handler on the element, and not binding the opening handler anywhere, as such elements don't exist when running the code.
To overcome this, you could remove the callback within the callback itself, while also adding the alternate callback.
$el = $(".drop-down-arrow-open i")
var closeFn = function() {
let thisParent = $el.closest(".projects-container").find(".needed-while-hiding");
thisParent.hide();
$el.closest(".drop-down-arrow-open").removeClass("drop-down-arrow-open").addClass("drop-down-arrow-closed");
$el.removeClass("fa-chevron-down").addClass("fa-chevron-right");
$el.off("click");
$el.click(openFn);
});
var openFn = function(){
let thisParent = $el.closest(".projects-container").find(".needed-while-hiding");
thisParent.show();
$el.closest(".drop-down-arrow-closed").removeClass("drop-down-arrow-closed").addClass("drop-down-arrow-open");
$el.removeClass("fa-chevron-right").addClass("fa-chevron-down");
$el.off("click");
$el.click(closeFn);
});
$el.click(closeFn);
This happens because the class "drop-down-arrow-closed" is not found on the time of DOM creation. To make sure always use
$('body').on('event', 'element', funciton)
So it will bind the event for the element which is already created or created later
$('body').on('click',".drop-down-arrow-open i",function(){
let thisParent = $(this).closest(".projects-container").find(".needed-while-hiding");
thisParent.hide();
$(this).closest(".drop-down-arrow-open").removeClass("drop-down-arrow-open").addClass("drop-down-arrow-closed");
$(this).removeClass("fa-chevron-down").addClass("fa-chevron-right");
});
$('body').on('click',".drop-down-arrow-closed i",function(){
console.log("This is never applied");
let thisParent = $(this).closest(".projects-container").find(".needed-while-hiding");
thisParent.show();
$(this).closest(".drop-down-arrow-closed").removeClass("drop-down-arrow-closed").addClass("drop-down-arrow-open");
$(this).removeClass("fa-chevron-right").addClass("fa-chevron-down");
});
span.drop-down-arrow-open, span.drop-down-arrow-closed{
font-size: 22px;
color: #636b6f;
float: right;
padding-right: 25px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
<div class="projects-container">
<h1>Project Name<span class="drop-down-arrow-open"><i class="fas fa-chevron-down"></i></span></h1>
<div class="needed-while-hiding">
<p class="description-background full-width adjust-properties">Description</p>
<div class="a-little-inside">
<ul class="list-without-bullets">
<li><span>Duration: </span><span>Some Duration</span></li>
<li><span>Roles: </span><span>Some Role related to development</span></li>
<li><span>Controller: </span><span>Pipeline</span></li>
<li><span>Official Website: </span>Random Link</li>
</ul>
</div>
</div>
</div>
As #vijoc said the problem is that when you bind the events to the elements.
As a possible solution you can re-bind the correct event every time it has to change the click function.
Code
$(function(){
bindOpen($(".open"));
bindClose($(".closed"));
});
function bindOpen(element){
$(element).unbind("click").bind("click",function(){
//your open stuff here
console.log("open");
bindClose(element);
})
}
function bindClose(element){
$(element).unbind("click").bind("click",function(){
//your open stuff here
console.log("close");
bindOpen(element);
})
}
Really, the click handler is bound to a known DOMElement matching the specified selector during runtime and when the selector changes you need to take care to update your selectors.
A workaround for this is to use the JQuery.on method to set a listener on a common parent DOMElement and filter through with another selector. An example for this using your use case is.
$(".parent-container").on("click", ".drop-down-arrow-open i", function() {
...
})
However, judging by your intent to reveal project details when the arrow icon is clicked and hide it when it is clicked again I find implementing it this way to be more readable by adding another class drop-down-arrow to target the arrow with.
function toggleProjectDetails() {
const $this = $(this)
$this
.closest(".projects-container")
.find(".needed-while-hiding")
.toggle();
$this
.toggleClass("drop-down-arrow-open drop-down-arrow-closed")
$this.find('i')
.toggleClass("fa-chevron-down fa-chevron-right")
}
$(".drop-down-arrow").on('click', toggleProjectDetails);
span.drop-down-arrow-open,
span.drop-down-arrow-closed {
font-size: 22px;
color: #636b6f;
float: right;
padding-right: 25px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
<div class="projects-container">
<h1>Project Name<span class="drop-down-arrow drop-down-arrow-open"><i class="fas fa-chevron-down"></i></span></h1>
<div class="needed-while-hiding">
<p class="description-background full-width adjust-properties">Description</p>
<div class="a-little-inside">
<ul class="list-without-bullets">
<li><span>Duration: </span><span>Some Duration</span></li>
<li><span>Roles: </span><span>Some Role related to development</span></li>
<li><span>Controller: </span><span>Pipeline</span></li>
<li><span>Official Website: </span>Random Link</li>
</ul>
</div>
</div>
</div>
I have two divs with dynamic links that sometimes are populated and sometimes aren't. If you a click a link that looks like this:
<a href="#">
Nothing happens, I prevent the default action, but if the link is:
<a href="/path/to/a/page">
It will follow.
I want to able to click on the surrounding div, and using the same logic as above. So if I click on the red and there is a valid link the link will follow. I'm using trigger() to attempt this.
The situation is below:
$(function() {
$(".container").click(function(e) {
var clickTarget = $(e.target).attr("href");
var clickTargetLink = $(this).find(".container-link");
if ((clickTarget != "#") || (clickTarget != undefined)) {
clickTargetLink.trigger("click");
} else {
e.preventDefault();
}
});
});
.container {
padding: 50px;
margin-bottom: 1rem;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<a class="container-link" href="google.com">link</a>
</div>
<div class="container">
<a class="container-link" href="#">link</a>
</div>
What ends up happening is clicking on the red div with google.com in the link throws:
jquery.js:3988 Uncaught RangeError: Maximum call stack size exceeded
at String.replace ()
at camelCase (jquery.js:3988)
at Data.get (jquery.js:4069)
at HTMLDivElement.dispatch (jquery.js:5146)
at HTMLDivElement.elemData.handle (jquery.js:4991)
at Object.trigger (jquery.js:8249)
at HTMLAnchorElement. (jquery.js:8327)
at Function.each (jquery.js:354)
at jQuery.fn.init.each (jquery.js:189)
at jQuery.fn.init.trigger (jquery.js:8326)
Maximum call stack size exceeded error
- this suggests that there is an infinity loop somewhere in this code. I'm lost as to how that could be the case here?
Why is this code causing a maximum call stack size error?
EDIT: more research led me to: Maximum call stack size exceeded on trigger click
going
.triggerHandler() just renders nothing and the link doesn't follow. Is there a different action I need to use that I'm not aware of?
EDIT #2: a few more details:
I cannot change/add markup structure.
the red div needs to be fully clickable, as there is another action tied to it when the link is empty: <a href="#">
I tried e.stopPropagation(); - which resolves the error, but then the link doesn't follow
I tried triggerHandler() - http://api.jquery.com/triggerhandler/
Your click handler is triggering a new click event, which is handled by the click handler, which triggers a new click event, which is handled by the click handler, which... eventually overflows the stack.
In comments (and now in the updated question) you've clarified the purpose of this code:
The red area needs to be clickable, not just the link. That's why I'm trying to use .trigger() so that I can trigger a click in the child link inside the div when the div is clicked on.
This necessitates a few more changes beyond just fixing your infinite loop:
Your existing code was looking for the href on the event target itself, which would not have allowed the red area to be clickable (because the event target isn't necessarily the element with an href attribute). I've changed this to ignore the event target (which isn't really what you care about) and instead just pluck the href from the link inside the container element.
In your if clause you used || when you meant && ("if it's not X or it's not Y" will always be true; "if it's not X and it's not Y" is what you meant there.)
The infinite recursion is resolved here by simply setting the window location directly, rather than firing another click event.
$(function() {
$(".container").click(function(e) {
var clickTarget = $(this).find("a.container-link").attr("href");
if (clickTarget && clickTarget !== "#") {
window.location=clickTarget;
} else {
// prevent link navigation from occurring
console.log("Blocking click");
e.preventDefault();
}
});
});
.container {
padding: 10px;
margin-bottom: 1rem;
background-color: red;
cursor: pointer
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<a class="container-link" href="https://example.com">Normal link</a>
</div>
<div class="container">
<a class="container-link" href="#">Blocked link</a>
</div>
You could optionally check to see if it is the link or the container that was clicked. If it was the link, do not trigger another click.
$(function() {
$(".container").click(function(e) {
var $containerLink = $(this).find('.container-link');
//check to see if the container was clicked, or if the link was clicked
var linkWasClicked = $(e.target).is('.container-link');
if (['#', undefined].indexOf($containerLink.attr('href')) > -1) {
e.preventDefault();
} else if (!linkWasClicked) { //only trigger the link if it was not clicked
$containerLink[0].click();
}
});
});
.container {
padding: 50px;
margin-bottom: 1rem;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<a class="container-link" href="https://google.com">link</a>
</div>
<div class="container">
<a class="container-link" href="#">link</a>
</div>
When the container is clicked, you trigger a click on the link inside it which propagates back to the container, clicking on the link again, and so on. You are recursively clicking on the link over and over again, which is causing the error. In your click event handler for the container, you need to check if the event's currentTarget is equal to the event's target to click on the link (preventing recursion). To trigger the click on the link to redirect to another page, you will need to get the actual DOM element to click on (not the jQuery object) like this: clickTargetLink[0].click() (jQuery always returns an Array of elements).
.container {
padding: 50px;
margin-bottom: 1rem;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<a class="container-link" href="http://www.example.com">link</a>
</div>
<div class="container">
<a class="container-link" href="#">link</a>
</div>
<script>
$(function() {
$(".container").click(function(e) {
var clickTarget = $(e.target).attr("href");
var clickTargetLink = $(this).find(".container-link");
if (e.currentTarget==e.target) {
clickTargetLink[0].click();
} else {
if(clickTarget!==undefined&&clickTarget == "#"){
e.preventDefault();
}
}
});
});
</script>
Because .container-link is inside .container the click event of the .container-link triggers a click also for .container unless you do stopPrpogation(), what causes the infinite loop.
Use stopPropagation() inside the if (after triggering the click).
as you can see in comments you are triggering click in the handler for the click which is causing to go in a loop . click-> handler-> trigger click-> handler --->
so basically attach handler to link itself, or if you want to attach it to parent only check if the target is link
you can also look at this thread for more breadth on topic In jQuery, how can I tell between a programmatic and user click?
Just improve your JS this way:
$(function () {
$(".container").click(function (e) {
var clickTarget = $(e.target).attr("href");
var clickTargetLink = $(this).find(".container-link");
if ((clickTarget === "#") || (clickTarget === undefined)) return false
})
})
I have a Javascript application which allows users to enable/disable controls at runtime. I have been successful in disabling/enabling nested inputs and buttons, but so far I have had no success in disabling an onclick event in a Div, so that the circled icon will not be selectable:
The generated HTML looks like:
<div id="56f81c3d-9666-4dab-8f35-d36e894f426f" class="field alert-success">
<div class="field-name">By default I am disabled - Single Photo</div>
<div id="56f81c3d-9666-4dab-8f35-d36e894f426fPhoto" class="clearfix" style="cursor: pointer; max-width: 100%; max-height: 100%;" onclick="ffffield.getFieldHandler('PhotoPicker').showPhotoCapture(this, '56f81c3d-9666-4dab-8f35-d36e894f426f');">
<img class="pull-right" src="/MySite.Web/Content/device/images/chevronRight.png" style="width: 20px; position:relative; top: 7px;">
<img class="pull-right" src="/MySite.Web/Content/device/images/photoPickerPlaceholder#2x.png" style="width: 40px; position:relative; top: -5px;">
</div>
</div>
</div>.
In this snippet, it is the "onclick" that I need to disable. I am not picky - it can be disabling the pointer or the onclick.
I have tried the following attempts to make this work:
$("#56f81c3d-9666-4dab-8f35-d36e894f426f").children().off('click');
and
$("#56f81c3d-9666-4dab-8f35-d36e894f426f input").prop("disabled", true);
and
$("#"#56f81c3d-9666-4dab-8f35-d36e894f426f input").attr("disabled", true);
and
$(""#56f81c3d-9666-4dab-8f35-d36e894f426f input").attr("disabled", "disabled");
based on some other stackoverflow questions.
.off() can only disable event listeners that were added with .on() (or other jQuery methods, since they all call .on() internally). To remove an event listener that was added using the onclick attribute, you need to reassign the onclick property:
$("#56f81c3d-9666-4dab-8f35-d36e894f426f").children().prop('onclick', null);
Try this code:
function disableDiv( div ) {
div.addEventListener( "click", function ( event ) {
event.stopPropagation();
}, true );
}
// call the disable div handler
disableDiv( document.getElementById( "56f81c3d-9666-4dab-8f35-d36e894f426f" ) );
I'm placing the following content in a Twitter Bootstrap popover, which contains a link for which I want to listen for clicks:
<div id="popover-content">
<a id="link" href="#">click</a>
</div>
I'm using a button to reveal the popover which contains the above content:
<button id="trigger" data-placement="bottom" title="title">Reveal popover</button>
I then associate the button with the popover and use jQuery's click() function in attempt to listen for clicks on the link contained in the popover:
$(function(){
$('#trigger').popover({
html: true,
content: function() {
return $('#popover-content').html();
}
});
$('#link').click(function() {
alert('beep');
});
});
However, upon clicking the button to reveal the popover and then clicking the link, the click seems to not be detected as intended above. My understanding of the DOM and javascript and jQuery is fairly limited, so I'm not sure what's going on here. How can you select/listen for actions on elements contained in a popover?
Reference: Popovers in Bootstrap
You do not need to perform Event delegation here.Instead use $('#popover-content') instead of $('#popover-content').html() while setting the content. This will have the events registered attached by default without requiring any delegation.
Demo
$(function(){
$('#trigger').popover({
html: true,
content: function() {
return $('#popover-content'); //<-- Remove .html()
}
});
$('#link').click(function() {
alert('beep');
});
});
You can try this:
$(document).on('click', '#link', function(){
alert('beep');
});
You can mannuly use popover:
html
<div id="popover-wrapper">
<button id="trigger" data-placement="bottom" title="title">Reveal popover</button>
<div class="popover right popup-area popover-pos">
<div class="popover-content">
<div id="popover-content">
<a id="link" href="#">click</a>
</div>
</div>
</div>
</div>
css
#popover-wrapper {
.popover {
left: auto;
right: 0;
width: 250px;
top: 35px;
.popover-content {
// ..
}
}
&.open .popover {
display: block;
}
}
js
$('#trigger').hover(function() {
$(this).stop(true, true).delay(250).queue(function(next){
$(this).addClass('open');
next();
});
}, function() {
$(this).stop(true, true).delay(250).queue(function(next){
$(this).removeClass('open');
next();
});
}
);