Changing Text in div without toggling Div Visiblity - javascript

In my Div (Code Below) there is an onClick function that triggers the visibility of a second div, and there is also a content edible in the div as well. When I click to change the text it also triggers the visibility of the second div. How would I change the code so that I can click the text without changing the second div's visibility?
<div class="div1" id ="div1" onclick="onStepClicked()" style ="text-align:center"><p contenteditable="true" >Step 1</p></div>
Function:
function onStepClicked() {
var elem = document.getElementById('div2');
if (Visible === true) {
elem.style.display = 'none';
Visible = false;
}
else {
if (Visible === false) {
elem.style.display = 'block';
Visible = true;
}
}
}

You may trigger the click on the Parent div only and exclude the click on child in jQuery like this:
$("#div1").click(function(){
$("#div2").css('visibility','hidden');
}).children().click(function(e) {
return false;
});
If you are not OK with jQuery and are after a JavaScript - only solution, please leave a comment and let me know.
UPDATE
If you are after a JavaScript solution, here U R:
HTML
<div id ="div1" onclick="onStepClicked()" >
<p id="editable" contenteditable="true">Step 1</p>
</div>
JS
function onStepClicked(){
document.getElementById('div1').onclick = function(e) {
if(e.target != document.getElementById('editable')) {
document.getElementById('div2').style.visibility = 'hidden';
}
}
}

Try using the element>element selector in your script. It will only affect the first child element and then stop from affecting sub-child elements.
Tutorial:
(http://www.w3schools.com/cssref/sel_element_gt.asp)

Related

jQuery not updating variable info

There are two divs with class of .egg. The user is supposed to click on the div they want to change the background color of and then click the color for the div's new background. Two steps total. I've written a jQuery function to capture the id of the div chosen for the background change and then the id for the color to change to background. Works great, except that when the new div is selected, to change the background color, the previously selected div id is still stored in the variable called clickedId.
To try to fix this problem, I have set clickedId = ''; after the background has been changed for the selected div. However when a new div is selected, it doesn't work anymore. The console says Cannot read property 'style' of null. It looks like the first part of the code, $(".egg").click(function() {... isn't be executed for new div selections.
Does anyone have any suggestions or advice for this? Thanks in advance!
jQuery Code:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
//Select the div to change the background color
$(".egg").click(function() {
var clickedId = $(this).attr("id");
//Updating the background color for selected div
$(".color").click(function() {
var clickedColor = $(this).attr("id");
if(clickedColor == 'red'){
document.getElementById(clickedId).style.backgroundColor = "red";
clickedId = '';
return;
}else if(clickedColor == 'blue'){
document.getElementById(clickedId).style.backgroundColor = "blue";
clickedId = '';
return;
}else if (clickedColor == 'yellow') {
document.getElementById(clickedId).style.backgroundColor = "yellow";
clickedId = '';
return;
}else{
document.getElementById(clickedId).style.backgroundColor = "white";
clickedId = '';
return;
}
});
});
});
</script>
HTML Code:
<body>
<div id="egg-main">
<div id="left-egg"></div>
<div id="center-egg1" class="egg" onclick="semi_left()"></div>
<div id="center-egg2" class="egg" onclick="semi_right()"></div>
<div id="right-egg"></div>
<div id="bottom">
<div id="red" class="color"></div>
<div id="blue" class="color"></div>
<div id="yellow" class="color"></div>
<div id="white" class="color"></div>
</div>
</div>
<script src="demo.js"></script>
</body>
Why it's not working
It looks like the problem is that the event listener for .color is declared inside the event listener for .egg. This means that every time you click .egg a new event handler is being created for .color.
The second time you click on a .color it is still running the event from the first time you clicked it. And, since you have changed the id to '', a getElementById('') is indeed null.
Possible Solution
Move the .color event listener outside the .egg event listener. You'll also have to change the scope of the clickedID variable.
$(document).ready(function(){
var clickedId = '';
//Select the div to change the background color
$(".egg").click(function() {
clickedId = $(this).attr("id");
alert(clickedId);
});
//Updating the background color for selected div
$(".color").click(function() {
var clickedColor = $(this).attr("id");
if(clickedId != '') document.getElementById(clickedId).style.backgroundColor = clickedColor;
});
});

'href' Not Showing Output on Click

Im trying to have a href link expand/display extra text when clicked however when I click it nothing happens.
When I run the html code I can click on the link but it does not show the text for some reason.
Any idea why?
Heres the code:
<html>
click to expand
<div id="divID" style="display: none;">this is expanded</div>
</html>
I'm trying to keep the code as short as possible as the above code will have to be repeated hundreds of times for each link.
Assuming you're using jQuery, you are using the CSS selector incorrectly. Your line should be this:
click to expand
The # in #divID represents any element with an id of divID, whereas just using divID will search for divID tags (something like <divID></divID>)
See here for more documentation on the ID Selector and here's a list of all the CSS selectors you can use, including the Element Selector for you to understand why your previous code didn't work.
You can also combine CSS selectors to narrow your selection in the future, although it's not much necessary with an ID selector:
click to expand
And if you absolutely insist on not using jQuery:
click to expand
or breaking it out into its own function:
<script>
function toggleElementById(id) {
if (document.getElementById(id).style.display == 'none') {
document.getElementById(id).style.display = 'block';
} else {
document.getElementById(id).style.display = 'none';
}
}
</script>
click to expand
Add this to your page:
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Then:
$('#divID').toggle();
I see you're using jQuery, right? So I wrote your answer in jQuery..
$('.toggle').click(function () {
var selected = $(this).attr('href');
$('.expandable'+selected).toggle();
});
Check out the jsfiddle
If you're not using jQuery than here is the javascript version (html changed).
var expandable = document.getElementsByClassName("expandable");
for (i = 0; i < expandable.length; ++i) {
expandable[i].setAttribute('style','display: none;');
}
var toggle = document.getElementsByClassName("toggle");
for (i = 0; i < toggle.length; ++i) {
toggle[i].setAttribute('onclick','toggler(this)');
}
function toggler(obj) {
var id = obj.dataset.toggle,
el = document.getElementById(id);
el.style.display = (el.style.display != 'none' ? 'none' : '');
}
Check out the jsfiddle

Getting the parent element with display block

I have this html
<div id="editor" contenteditable="true">
This text is directly under div
<p>Some text under p tag. <span> Some under span tag</span> and this is another text</p>
<p>Another para</p>
</div>
<button>Get block level parent</button>
Javascript
function getParentBlock() {
element = document.getSelection().focusNode;
while (p = element.parentNode) {
displaystyle = window.getComputedStyle(p, null).getPropertyValue('display');
if (displaystyle == 'block') {
return p;
}
element = element.parentNode;
}
}
function alertCurrentParent() {
alert(getParentBlock());
}
btn = document.querySelector('button');
btn.onclick = alertCurrentParent;
The jsfiddle is here: http://jsfiddle.net/shankardevy/aA8Kb/
Now when I place the cursor inside the text 'Another Para' or doubleclick the 'Another Para' (which in my mac selects the whole para) and click the button 'Get block level parent', I get HTMLParagraphElement in alert.
However, when I place the cursor in first para ("Some text under p tag"), and I click the button, I get "HTMLParagraphElement" in alert. And when I double click the second para which selects the entire first paragraph, and click the button, I get "HTMLDivElement".
I want my code to work as in the second paragraph. i.e., double click the sentence and click the button, it should show me "HTMLParagraphElement". How do I do that?
Any help is much appreciated!
The problem is that you start your loop with the parent node. When you select the entire paragraph, its parent is the DIV. So start your loop at the current element instead of the parent.
function getParentBlock() {
var element = document.getSelection().focusNode;
for (var p = element; p; p = p.parentNode) {
var style = window.getComputedStyle(p, null);
if (style) {
var displaystyle = style.getPropertyValue('display');
if (displaystyle == 'block') {
return p;
}
}
}
}
FIDDLE
You have to test the result of getComputedStyle before calling getPropertyValue, because text nodes don't have a style and it returns null.

Toggling div visibility for a graph

I'm creating a flow graph using HTML, CSS and JS.
This is the fiddle:
http://jsfiddle.net/Newtt/HRedA/3/
This is my JS:
var flag = false;
function showdiv(id) {
var div = document.getElementById(id);
div.style.display = flag ? 'none' : 'block';
flag = !flag;
}
It shows the root node of the graph and has to be clicked on to increase the levels.
As you can see there are some issues regarding the number of clicks required to show the divs that are hidden. I would like some help to fix two things:
Number of clicks required
When I open stage two and stage three, clicking on stage one should collapse all the open stages. However, with the current code, that doesnt seems to be working.
By setting the display-flag on the actual element you will avoid toggling a global state:
function showdiv(id) {
var div = document.getElementById(id);
var divFlag = div.expandedFlag == true
div.style.display = divFlag ? 'none' : 'block';
div.expandedFlag = !divFlag;
}
Or even simpler by using the elements display-state to decide if show/hide:
function showdiv(id) {
var div = document.getElementById(id);
div.style.display = (div.style.display == 'block') ? 'none' : 'block';
}
Including Part 2:
For part two. Including a structure containing children nodes for recursive hiding:
function showdiv(id) {
var div = document.getElementById(id);
var hideFlag = (div.style.display == 'block');
div.style.display = (hideFlag ? 'none' : 'block');
if(hideFlag){hideChildren(id)}
}
var children = {
'two' : ['three-one','three-two']
};
function hideChildren(parent) {
if(children[parent] !== undefined){
for(var i = 0; i<children[parent].length; i++){
var id = children[parent][i]
document.getElementById(id).style.display = 'none';
hideChildren(id)
}
}
}
For part 2 I would again use the DOM to your advantage. I agree that if you intend to generate these dynamically it's going to take some rework of the DOM structure and code.
For this example however, I created the following JSFiddle
http://jsfiddle.net/HRedA/15/
<div class="wrapper">
<div class="stage-one">
<div class="box node-one"></div>
<div class="stage-two" id="two" style='display:none'>
<div class="box node-two">
<div class="stage-three-one" id="three-one" style="display:none;">
<div class="box node-four"></div>
<div class="box node-five"></div>
</div>
</div>
<div class="box node-three">
<div class="stage-three-two" id="three-two" style="display:none;">
<div class="box node-six"></div>
</div>
</div>
</div>
</div>
</div>
So the html above is reduced so it's not cluttering the page, but you'll notice that instead of all the elements being at the same level the nodes are structured inside of one another just like the flow diagram is structured. This means that when you hide a parent it will also hide it's children. This has the side-effect/feature of also remembering what you had expanded. For example if you hide the root and then show it again all your previous expansions will remain.
The reason this won't work dynamically is that all the lines and boxes are positioned by hand. I even had to move some around when they became children of other nodes.
Hope this helps.

make a button to change the parent's CSS classname attribute

so I have a javascript function that changes the class name of a div
function flip (event)
{
var element = event.currentTarget;
element.className = (element.className == 'card') ? 'card flipped' : 'card';
}
How can I make it so my onclick="flip(event)" can be attached to a button (or preferably an image) and the button will then flip the card instead of just clicking inside the div. So something like
<div id="card" class="card">
<p>
whatever
</p>
<img onclick="flip(event)" src="foo">
</div>
What do I need to change in my javascript function?
This should work
<img onclick="javascript:flip('card');" />
function flip (elementId)
{
var element = document.getElementById(elementId)
element.className = (element.className == 'card') ? 'card flipped' : 'card';
}
I'm not sure but I think that John solution's can have problem if you have several elements with class 'card' and you only want to change the one that was clicked.
To do this, use 'this' as argument :
<img onclick="javascript:flip(this.parentElement);" />
function flip (element)
{
element.className = (element.className == 'card') ? 'card flipped' : 'card';
}
$('imgSelector').click(function() {
$(".card").toggleClass('card flipped');
});
Using jQuery you can do it Like this.
with Simple javascript you will have to give a id to your DIV. and then instead of using event.target just simply use document.getElementById('myDIVID');
the event object has a reference to the element that originated the event.
you can use parentNode to work back up the tree.
this will work with your html example.
function flip (event)
{
var image = event.target || event.srcElement;
var div = image.parentNode;
div.className = (div.className == 'card') ? 'card flipped' : 'card';
}
target is the originating element in ff/chrome, srcElement is the same element in IE. currentTarget in ff/chrome is the element which called the handler, which may not be the same element you clicked on. for example, if you attached a click handler right on the div, it would fire when you clicked on the image within. when the div's handler fires, currentTarget would be the div and target would be the image. IE has no parallel for currentTarget that i'm aware of.

Categories

Resources