The problem I'm facing is that currently I have 2 elements, one is visible by default and the other one is hidden. When a button is clicked the state in both elements are exchanged, which means that the element which was not visible not it is and viceversa. What I want to accomplish now is that when I click in any other part of the page except in that given element, the state is reversed.
<script type="text/javascript">
function hidesearch() {
var target = event.target || event.srcElement;
if (event.currentTarget == target) {
document.getElementById('elem1').style.display = "none";
document.getElementById('elem2').style.display = "true";
}
}
function showsearch() {
document.getElementById('elem2').style.display = "none";
document.getElementById('elem1').style.display = "true";
event.stopPropagation();
}
</script>
This is the current code inside my head tag. Tried to add the onclick and onload attributes into the body too but isn't working still.
<h:body onload="hidesearch();"/>"
The page is .xhtml as everything is being coded using JSF + BootsFaces.
Is there anything I'm missing out?
document.getElementById('elem2').style.display = "true";
display property value of element style can be "block", "inline-block", "inline", "none" but "true" value doesn't exist.
Please assign appropriate value one you want.
Related
I am trying to change the innerHTML of my page to become the innerHTML of the element I click on, the only problem is that i want it to take the whole element such as:
<section class="homeItem" data-detail="{"ID":"8","Name":"MacBook Air","Description":"2015 MacBook A…"20","Price":"899","Photo":"Images/Products/macbookAir.png"}"></section>
Whereas the code that i have written in javascript:
function selectedProduct(event){
target = event.target;
element = document.getElementById("test");
element.innerHTML = target.innerHTML;
}
will target the specific element that i click on.
What i would like to achieve is when i click on anywhere in the <section> element, that it will take the innerHTML of the whole element rather than the specific one that i have clicked.
I would presume it is something to do with selecting the parent element of the one that is clicked but i am not sure and can't find anything online.
If possible i would like to stay away from JQuery
I think what you need is to use the event.currentTarget. This will contain the element that actually has the event listener. So if the whole <section> has the eventlistener event.target will be the clicked element, the <section> will be in event.currentTarget.
Otherwise parentNode might be what you're looking for.
link to currentTarget
link to parentNode
To use the parent of an element use parentElement:
function selectedProduct(event){
var target = event.target;
var parent = target.parentElement;//parent of "target"
}
handleEvent(e) {
const parent = e.currentTarget.parentNode;
}
function getParent(event)
{
return event.target.parentNode;
}
Examples:
1. document.body.addEventListener("click", getParent, false); returns the parent element of the current element that you have clicked.
If you want to use inside any function then pass your event and call the function like this :
function yourFunction(event){
var parentElement = getParent(event);
}
var _RemoveBtn = document.getElementsByClassName("remove");
for(var i=0 ; i<_RemoveBtn.length ; i++){
_RemoveBtn[i].addEventListener('click',sample,false);
}
function sample(event){
console.log(event.currentTarget.parentNode);
}
$(document).on("click", function(event){
var a = $(event.target).parents();
var flaghide = true;
a.each(function(index, val){
if(val == $(container)[0]){
flaghide = false;
}
});
if(flaghide == true){
//required code
}
})
Here's a pen with the full html: https://codepen.io/froggomad/pen/WLdzoB
I'm writing 2 functions - one to show hidden content, and one to hide it. I'm wanting the show() function to execute on the parent div and the hide() function to execute on the div with the selector .click-text.
However, I'm switching text on .click-text from show to hide so I don't want the hide function to remain on the text at all times. I also want it obvious that its interactive text when changing to a hide function, so I make it a link.
That's all well, but when attempting to set the onclick Attr of the parent back to the show() function, nothing in the hide block executes at all.
If I remove the line setting the parent's onclick Attr, the script executes as expected. If I set another element's onclick Attr, the script executes as expected.
However, with that line in there, nothing happens and there's no output in the console to indicate an error. I even set an alert with the type of element and classname to ensure I'm targeting the right element.
Get closest parent of element matching selector:
var getClosest = function (element, selector) {
for ( ; element && element !== document; element = element.parentNode ) {
if ( element.matches(selector) ) return element;
}
return null;
}
Show Hidden Element ul.service-category-menu
function show(elem) {
var menu = elem.querySelector("ul.service-category-menu"),
click = elem.querySelector(".click-text"),
parent = getClosest(elem, '.service-category');
;
if (menu.style.display === "none" || menu.style.display === "") {
menu.style.display = "block";
click.innerHTML = "<a href=\"#\">Click to Hide<\/a>";
click.setAttribute('onclick','hide(this);');
elem.setAttribute('onclick', 'null');
}
}
Hide Element
function hide(elem) {
var parent = getClosest(elem, '.service-category'),
menu = parent.querySelector("ul.service-category-menu"),
click = parent.querySelector(".click-text")
;
alert(parent + "\n" + parent.className);
//Outputs div element with expected class name (class name is unique on each div)
if (menu.style.display === "block") {
menu.style.display = "none";
click.innerHTML = "Click to Show";
click.setAttribute('onclick', 'null');
//the above lines don't execute when the following line is in place. There's no error in console.
parent.setAttribute('onclick','show(this)');
}
}
First off, I must confess that I'm against using onclick attributes. If you're not using a framework such as VueJS or React, I think HTML and JS should remain separated for better control and maintainability.
You can use addEventListener, removeEventListener, and e.stopPropagation() to avoid triggering multiple event handlers.
Events have two phases:
Event capture: the event spreads from the document all the way down to the target element.
To catch an event during this phase, do:
elm.addEventListener('click', myFunc, true);
Event bubbling: the event bounces back from the target to the document.
To catch an event during this phase, do:
elm.addEventListener('click', myFunc, false); /* or just omit the 3rd param */
Using e.stopPropagation() allows you to break that chain.
// When the DOM is ready
window.addEventListener("DOMContentLoaded", init);
function init() {
// Get all categories
var $categories = document.querySelectorAll(".service-category");
// For each of them
Array.from($categories).forEach(function($category) {
// Add an event listener for clicks
$category.addEventListener("click", show);
});
}
function getClosest(element, selector) {
for (; element && element !== document; element = element.parentNode) {
if (element.matches(selector)) return element;
}
return null;
}
function show(e) {
var $menu = this.querySelector("ul.service-category-menu"),
$click = this.querySelector(".click-text");
if (["none", ""].includes($menu.style.display)) {
$menu.style.display = "block";
$click.innerHTML = 'Click to Hide';
$click.addEventListener("click", hide);
// Remove the `show` event listener
this.removeEventListener("click", show);
}
e.stopPropagation();
}
function hide(e) {
var $parent = getClosest(this, ".service-category"),
$menu = $parent.querySelector("ul.service-category-menu"),
$click = $parent.querySelector(".click-text");
if (!["none", ""].includes($menu.style.display)) {
$menu.style.display = "none";
$click.innerHTML = "Click to Show";
$click.removeEventListener("click", hide);
$parent.addEventListener("click", show);
}
e.stopPropagation();
}
.service-category{display:inline-block;border:3px solid #ccc;margin:1%;font-weight:700;font-size:3.5vw;cursor:pointer;background-color:#fff;z-index:3;background-position:center;background-size:cover;color:#000}.click-text{text-align:right;font-size:1.25vw;font-style:italic;font-weight:700;padding-right:1%}.service-category:hover .click-text{color:#b22222}.service-category-menu{display:none;margin-left:8%;margin-right:8%;margin-top:1%;background-color:#fff;font-weight:700;font-size:1.6vw;border-radius:10px}
<div class="service-category web-back" id="web-back">
<div class="row-overlay">
Web <br /> Development
<div class="click-text">Click to Show</div>
<ul class="service-category-menu web">
<li>
Some text...
</li>
</ul>
</div>
</div>
<div class="service-category web-front" id="web-front">
<div class="row-overlay">
Web <br /> Design
<div class="click-text">Click to Show</div>
<ul class="service-category-menu web">
<li>
Some text...
</li>
</ul>
</div>
</div>
It is executed, it's just after you click that Click to Hide, the event continues to parent and the event handler of the parent executed. Thus, what exactly happen is (with that line), after hide() called, you inadvertently called show().
In javascript it's usually called bubbles (when you click the children, the click handler of parent will also be executed after click handler of children complete).
So the solution, you can add this line at the end of the hide() function
event.stopPropagation();
To stop the event from continuing to the parent
Setting event.stopPropagation as mentioned in the other answer will potentially fix your issue. Alternatively, you can change the last line of your hide function to window.setTimeout(e => parent.setAttribute('onclick','show(this)'), 0).
What's happening right now is:
You click
it executes your hide function, and during that function it binds a click event to the parent
The click propagates to the parent and executes the newly bound function, re-showing the content.
By using setTimeout(fn, 0), you're making sure the click event completes before the function is bound to the parent.
I have this piece of code:
<div id="mydiv" onclick="ajax_call()">
Mylink
</div>
I'd like ajax_call() to be called only when clicking on empty space inside div but not on "Mylink". Is it possible without any external javascript framework?
Moreover I have this piece of css:
div#mydiv:hover{
background-color: blue;
}
Is it possible to disable the :hover stylesheet when the cursor is placed over "Mylink" (in order to suggest that clicking on "Mylink" won't trigger ajax_call() but will take to myurl)?
Attach the function at child element with click event, After clicked on child element it's handler stops the immediate propagation, As a result ajax_call() will not be invoked.
HTML
<div id="mydiv" onclick="ajax_call()">
Mylink
</div>
javaScript
function ajax_call(){
alert("empt space");
}
//this function stops the propagation and not triggered above
//function when clicked on child element.
function notCall(event) {
event.stopImmediatePropagation();
return false;
}
DEMO
I'm not sure what you want but if I keep my imagination may be that this work, lucky !
$("div#mydiv a").hover(function(){
$(this).parent().css("background-color","transparent")
})
Sure, what you need is the event target || scrElement
Like
function ajax_call() {
var target = event.target ? event.target : event.srcElement;
if(target.id==="mydiv") { alert("good to go"); }
}
See : http://jsbin.com/qujuxufo/1/edit
Edit/Update ( missed the second part ) - Started to answer this before the q was closed - but might as well as it now ..
For the second part of the question - it is not possible to set parent elements in CSS ( it flows top to bottom ) - for that some more JS is needed.
See http://jsbin.com/cileqipi/1/edit
CSS
#mydiv:hover { background-color:green; color:#fff}
#mydiv.anchorhover, #mydiv.anchorhover:hover { background-color:white;}
Then JS
var _mydiv = document.getElementById("mydiv");
var _mydiv_anchors = _mydiv.getElementsByTagName("a");
function toggleClass() {
var addClass=true, cls="anchorhover";
if((_mydiv.className).indexOf(cls) >= 0){ addClass=false; }
if(addClass) {
_mydiv.className=_mydiv.className+=' '+cls;
} else {
/* remove */
_mydiv.className=_mydiv.className.replace(new RegExp('(\\s|^)'+cls+'(\\s|$)'),' ').replace(/^\s+|\s+$/g, '');
}
}
for(var i=0, len=_mydiv_anchors.length; i<len; ++i) {
_mydiv_anchors[i].onmouseover = toggleClass;
_mydiv_anchors[i].onmouseout = toggleClass;
}
^ That feels like quite a trip compared to how simple jquery abstracts it .. >
$("#mydiv a").hover(function() {
$(this).parent().addClass("anchorhover");
}, function() {
$(this).parent().removeClass("anchorhover");
});
Either way, the principle is : to add a style class to the parent element on mouseover and remove it on mouseout
I am working with this plugin that runs off of the data attribute. Basically when you click anywhere on the body it will determine if the click target has this specific data-vzpop. The problem is lets say I have a div and inside the div is an a href. It only acknowledges the a href as the click target and not the div (which makes sense).
What I want to try and do in some cases is put the data attribute on the containing div that way anything within the div works on click.
Here is a sample of the issue with jsfiddle it requires viewing the console so you can actually see which element is registered as being clicked.
<div data-vzpop>
Click Me
</div>
$('body').on('click', function(evt){
var clickTarget = evt.target;
if ($(clickTarget).attr('data-vzpop') !== undefined){
evt.preventDefault();
console.log('called correctly')
} else {
console.log('not called correctly')
}
console.log(clickTarget)
});
fiddle
You would use Event delegation:
$('body').on('click', '[data-vzpop]', function(evt) {
This will only trigger when the evt.target has a data attribute of data-vzpop, no matter the value.
If you want items inside the [data-vzpop] to trigger it as well, you would use your original click event but check that the $(clickTarget).closest('[data-vzpop]').length > 0 to determine if it's a nested target.
$('body').on('click', function(evt){
var clickTarget = evt.target;
if ($(clickTarget).attr('data-vzpop') != null ||
$(clickTarget).closest('[data-vzpop]').length > 0){
evt.preventDefault();
console.log('called correctly')
} else {
console.log('not called correctly')
}
console.log(clickTarget)
});
I show us the code:
(function (){
var element = document.getElementById('bar'), hideElement = document.getElementById('foo'),
var html = document.getElementsByTagName('html')[0];
tool.onclick = function() {
hideElement.style.display = 'block';
html.onclick = function() {
hideElement.style.display = 'none';
}
}
})();
This piece of code work's fine, but, after clicking html, I can not reopen the hidden element.
I want to click the html element and give display:none to hideElement, then to click the element id="bar", give to the hidden element display:block, but instead of click the element foo, click the html element. What I can do?
Oh, i need help WITHOUT JQUERY, thanks :)
EDIT: something like that : click on body except some other tag not working , but without JQuery,
I'm not sure it's going to answer your question, but here it is: how to handle an event on the body except one element:
document.documentElement.onclick = function(e) {
var evt = e || window.event, // IE...
target = evt.target || evt.srcElement // IE again...
// There, "target" is the element clicked. See where I'm going?
if (target.id !== "foo") {
// Do w/e you want if the page was clicked, except for "foo"
}
}
This is the concept of "event bubbling". You can listen to one element and all its children at once, and get the target as specified in the code up there.
First, you don't appear to be defining tool anywhere that I can see.
Second, you forgot .style in hideElement.display (should be hideElement.style.display).
Third, document.getElementsByTagName('html')[0] is redundant. Just use document.documentElement instead.
Change
html.onclick = function() {
hideElement.display = 'none';
}
to
html.onclick = function() {
hideElement.style.display = 'none';
}