Prototype - Show one element, hide siblings - javascript

I've got this html below.
I need all div's inside div#ProductImagesContainer to be hidden at startup, all but div#productImageA.
When you click a.productImageB, the corresponding div#productImageB inside div#ProductImagesContainer should be shown and it's siblings should hide.
I need to use Prototype for this project, but I'm not a javascript genious. Would know what to do with jQuery but can't do it with Prototype.
<ul>
<li>
A
</li>
<li>
B
</li>
<li>
C
</li>
<li>
D
</li>
</ul>
<div id="ProductImagesContainer">
<div id="productImageA">maybe flash video</div>
<div id="productImageB">imageB</div>
<div id="productImageC">imageC</div>
<div id="productImageD">imageD</div>
</div>

My JavaScript is a bit rusty, but I believe you want the following:
Hide everything:
$$('#ProductImagesContainer div').invoke('hide');
Show the one you want:
$('ProductImageA').show();
Edit: documentation on prototype's api can be found here

Here is the jsfiddle to achieve what you are looking for in prototype:
Given HTML:
<ul>
<li>
A
</li>
<li>
B
</li>
<li>
C
</li>
<li>
D
</li>
</ul>
<div id="ProductImagesContainer">
<div id="productImageA">maybe flash video</div>
<div id="productImageB">imageB</div>
<div id="productImageC">imageC</div>
<div id="productImageD">imageD</div>
</div>
Prototype JavaScript:
//declare global variables to access within functions and etc...
var myLi = $$('li'); //get all the li a links
var myDiv = $('ProductImagesContainer').children; //get all the children of div#ProductImagesContainer
hideAllBut(null); //first hide all the divs
//function to hideAllBut the child div element of #ProductImagesContainer w/ the following classname as id
function hideAllBut(el) {
var toShow = el;
for (var index = 0; index < myDiv.length; index++) {
if (myDiv[index].identify() == toShow)
myDiv[index].show();
else
myDiv[index].hide();
};
}
//oops through each li
myLi.each(function(myLiEl) {
//attached on click event for each of the hyperlinks and use the hyperlink's class name to call hideAllBut(theclassname)
Event.observe(myLiEl, 'click', function() {
hideAllBut(myLiEl.firstDescendant().className); //gets the className of first decendant based on your example
});
});
First we declare two global variables to hold all the li's a links and children of div#ProductImagesContainer. Then we create a function called hideAllBut(el); where it hides all but the child div element of #ProductImagesContainer w/ the classname as id. A parameter, which is the classname of link that is associated w/ the div element's id name that we need to hide. Then we proceed to oop through each li and add an onclick event so whenever the li is clicked it'll call hideAllBut(); and pass its classname as the param.

Based on kjy112's detailed answer, here is a shorter version.
HTML:
<ul id="ProductImagesLinks">
<li>
A
</li>
<li>
B
</li>
<li>
C
</li>
<li>
D
</li>
</ul>
<div id="ProductImagesContainer">
<div id="productImageA">maybe flash video</div>
<div id="productImageB">imageB</div>
<div id="productImageC">imageC</div>
<div id="productImageD">imageD</div>
</div>
Javascript:
$('ProductImagesLinks').on('click', 'a', function(event, element){
var target = $(element.readAttribute('data-target'));
if (target) {
target.show();
$$('#ProductImagesContainer > div[id!='+target.identify()+']').invoke('hide');
}
});
$('ProductImagesContainer').down().siblings().invoke('hide');
The advantage here is it adapts if the list changes by utilising event bubbling.

Related

How to copy part of a tag to another tag?

I want to insert the (ul) tag that comes after the (div) tag in class (copy1).
Then, by clicking on the tag (div) in the class (copy1), insert the (ul) tag after the tag (div) into the class (copy2). The first step is running the code, but I don't know the second step.
$(document).ready(function() {
$('ul ul').hide();
$('ul div').click(function() {
var x = $(this).next().html();
$('.copy1').html(x);
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li>
<div>01</div>
<ul>
<li>01-01</li>
<li>
<div>01-02</div>
<ul>
<li>01-02-01</li>
<li>01-02-02</li>
<li>01-02-03</li>
</ul>
</li>
<li>01-03</li>
</ul>
</li>
<li>
<div>02</div>
<ul>
<li>02-01</li>
<li>02-02</li>
<li>02-03</li>
</ul>
</li>
</ul>
<hr>
<ul class="copy1"></ul>
<ul class="copy2"></ul>
After clicking on the first div tag, the following values are inserted into the copy1 class.
01-01
01-02
01-03
But by clicking on 01-02 the following values
01-02-01
01-02-02
01-02-03
Those that are in the copy1 class are not copied to the Copy2 class.
Because the elements in .copy1 are created dynamically, you either need to add events after they are created or use event delegation
$(document).on("click", ".copy1 div", function() { ...
as you want copy1->copy2, it needs to be separate from the src->copy1 code (or have additional logic within the click handler).
In the snippet below, I've kept them separate for clarity. I've also added some css to show which ones can be clicked as it was slightly confusing that 01-01 does nothing as there are no child nodes.
$(document).ready(function() {
$('ul ul').hide();
$('ul div').click(function() {
var x = $(this).next().html();
$('.copy1').html(x);
})
$(document).on("click", ".copy1 div", function() {
var x = $(this).next().html();
$('.copy2').html(x);
});
});
ul div { color: red }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li>
<div>01</div>
<ul>
<li>01-01</li>
<li>
<div>01-02</div>
<ul>
<li>01-02-01</li>
<li>01-02-02</li>
<li>01-02-03</li>
</ul>
</li>
<li>01-03</li>
</ul>
</li>
<li>
<div>02</div>
<ul>
<li>02-01</li>
<li>02-02</li>
<li>02-03</li>
</ul>
</li>
</ul>
<hr>
<ul class="copy1"></ul>
<ul class="copy2"></ul>

How to pass a Javascript parameter through Onclick function when there is no id is defined

I want to pass which li is clicked. The clicked li number i have to pass through onclick function. There is no id is defined to any li.
Example is second li is clicked, i want to pass onclick="imageDisplayClick(2) but i am not able to get the count.
<div id="slider_text">
<ul onclick="imageDisplayClick()">
<li><h1 style="color:orange;">SPORTS & FITNESS</h1></li>
<li><h1>ACCU - CHEK Strips</h1></li>
<li><h1>NATURE'S BOUNTY</h1></li>
<li><h1>Beauty Care</h1></li>
</ul>
</div>
Please help me to solve this issue
For starters, I would not recommend using the onclick attribute, but rather making use of Unobtrusive JavaScript and separating it out to a function.
After separating out the logic, it's only a small extra step to loop over the elements, which can be acquired with .querySelectorAll.
From here you now have a click handler on each individual <li> element that can reference the element in question with the this keyword. Because you have access to the element directly, you shouldn't actually need to pass through the relevant offset into the function in question.
var points = document.querySelectorAll('#slider_text > ul > li');
for (var i = 0; i < points.length; i++) {
points[i].addEventListener('click', function() {
console.log(this.innerHTML);
})
}
<div id="slider_text">
<ul>
<li>
<h1 style="color:orange;">SPORTS & FITNESS</h1>
</li>
<li>
<h1>ACCU - CHEK Strips</h1>
</li>
<li>
<h1>NATURE'S BOUNTY</h1>
</li>
<li>
<h1>Beauty Care</h1>
</li>
</ul>
</div>
Hope this helps! :)
Use this, it will pass a reference to the DOM element itself.
<ul onclick="imageDisplayClick(this)">
You should consider using https://developer.mozilla.org/fr/docs/Web/API/EventTarget/addEventListener as it makes everything lie in your javascript file and prevents from having js fragments scattered in your html.
You can then use the event parameter to find out in detail what was clicked:
Test it here https://jsfiddle.net/jteLw8qa/
HTML:
<div id="slider_text">
<ul id="selection">
<!-- data-XXX can be accessed in javascript with element.dataset.XXX AS A STRING -->
<li data-yourdata="42"><h1 style="color:orange;">SPORTS & FITNESS</h1></li>
<li data-yourdata="elephant"><h1>ACCU - CHEK Strips</h1></li>
<li data-yourdata="pink"><h1>NATURE'S BOUNTY</h1></li>
<li data-yourdata="stackoverflow"><h1>Beauty Care</h1></li>
</ul>
</div>
JS:
function imageDisplayClick(event)
{
// find the clicked li element
var target = event.target;
// find first parent li or ul
while(target.tagName != 'LI' && target.tagName != 'UL')
target = target.parentNode;// because you have <h1> in your <li>
// if li is a parent the user clicked on it, else he clicked on the side but still on the ul
if(target.tagName == 'LI')
alert('clicked li with data-yourdata=' + target.dataset.yourdata);
}
// have the click event being listened on our ul#selection element
document.getElementById('selection').addEventListener('click', imageDisplayClick);
On top of the other answers provided, an event argument is also passed to the click handler, which should provide you with information on what specific thing was clicked on.
In your case, you could do something like this:
imageDisplayClick = function(event){
var target = event.target.tagName=="H1"?event.target.parentNode:event.target;
console.log(target);
}
<div id="slider_text">
<ul onclick="imageDisplayClick(event)">
<li><h1 style="color:orange;">SPORTS & FITNESS</h1></li>
<li><h1>ACCU - CHEK Strips</h1></li>
<li><h1>NATURE'S BOUNTY</h1></li>
<li><h1>Beauty Care</h1></li>
</ul>
</div>

jquery, move element to closest div

I want to move some span elements to closest div. I found the solution to my problem but it does not work for me. I have some Html code:
<ul>
<li>
<a><span>Some info</span></a>
</li>
<div class="cl1">...</div>
<li>
<a><span>Some info 2</span><a>
</li>
<div class="cl1">
...
</div>
...
</ul>
and to move <span> like this:
$('span').each(function () {
$(this).parent().parent().closest('.cl1').append(this);
})
but nothing happened. Any help would certainly be appreciated
you can't put a div in a ul, only li's.
your html has to be valid (a's, ul need to be closed)
Closest searches anscetors, not siblings.
since your markup is not valid as is, i'm not sure if you want the divs in the list or not. This example removes them from the lis, which breaks the list into two lists.
$('button').click(function() {
$('span').each(function() {
var $div = $(this).closest('ul').siblings('.cl1');
$(this).clone().appendTo($div);
$(this).remove();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>
<a><span>Some info</span></a>
</li>
</ul>
<div class="cl1">...</div>
<ul>
<li>
<a><span>Some info 2</span></a>
</li>
</ul>
<div class="cl1">...</div>
<button>Do Stuff</button>

jquery get the height of the submenu

I have the <ul> tag as below. When clicked on the anchor link it should display a div with the ul list items underneath. On the click function of anchor tag, I need to get the complete height of the div (in fact the height of the ul with li items), the submenu
<ul>
<li>
<a></a>
<div>
<ul>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</li>
</ul>
The html code is as below:
<ul class="menu level-1 plain" id="header-menu">
#{
var i = 1; //Used for submenu ID
}
#foreach (var menuItem in Model.Header.TopLevelNavigation)
{
if (i < 6)
{
<li #Html.Raw(i > Model.MenuMidPoint ? "class=\"sub-menu-nudge-left\"" : "")>
#if (menuItem.ContentLink.HasChildPages())
{
<a href="#sub-menu-#i" class="menu-link js-ui-header-all-menu-drill-down" aria-haspopup="true">
<span class="icon icon-chevron-left #Model.GetBoxIcon(i)"></span>
<span>#menuItem.Name</span>
</a>
<div id="sub-menu-#i" class="sub-menu" aria-label="submenu" aria-hidden="true">
#Html.DisplayEnumerableIContent("<ul class=\"level-2 plain\">{0}</ul>", "<li>{0}</li>", "menu-link", menuItem.ContentLink.GetChildPages(true, true))
</div>
}
</li>
}
i++;
}
</ul>
I tried the jquery function as below:
I tried as below, but I am unable to get the height of the submenu. It never gets into the foreach loop at all. Could anyone please help
$(".menu-link").click(function () {
var $subnavdev = $(this).parent().sublings('sub-menu').siblings('level-2 plain')
var totalHeight = 0;
$subnavdev.find('li').each(function() {
totalHeight += $(this).outerHeight(true);
});
alert(totalHeight);
});
Some of your class selectors were not specified correctly, plus there was a typographical error (all on Line 2).
Update - It also seems the siblings() methods may not be behaving as you intend them to... - And I got the .level-2 selector wrong still - since you need another . before plain. (See below example)
By using the closest() method you can go up to the nearest parent (for example, <li>), then use find() to pick out all .level-2.plain items nested within that parent.
Remember that your $(this) inside the handler function refers to the handled element, (in this case the .menu-link item being clicked.
$(".menu-link").click(function () {
var $subnavdev = $(this).closest('li').find('.level-2.plain');
// ...
});

How to map every element and its children

I am trying to get every element and alls its children and there children and add them to a list. But at the moment its only showing the first two children.
Is there a better way for doing this?
here is jsfiddle, http://jsfiddle.net/7mNsH/2/
here is what i have so far
$('#main').children().each(function(){
var classs = $(this).attr('class');
$('#hell ul').append('<li class="'+classs+'">'+classs+'</li>');
});
<div id="main">
<div class="inner">
<div class="innerinner"></div>
</div>
<div class="inner2">
<div class="inner2inner2">
<div class="inner2inner2inner2"></div>
</div>
</div>
</div>
so at the moment its currently showing this
<ul>
<li class="inner">inner</li>
<li class="inner2">inner2</li>
</ul>
but i need it to look like this
<ul>
<li class="inner">inner
<ul>
<li class="innerinner">innerinner</li>
</ul>
</li>
<li class="inner2">inner2
<ul>
<li class="innerinner">innerinner
<ul>
<li class="inner2inner2inner2">inner2inner2inner2</li>
</ul>
</li>
</ul>
</li>
</ul>
You seem to be looking for a recursive solution. If you look at your current code, what you are accomplishing is iterating over #main's children, appending them to a ul, and then finishing. You need to be sure to keep checking each child for their own children (and all of their children!) in order to get the fully recursive list of children.
Check out working JSFiddle here: http://jsfiddle.net/uK6kG/5/
function listChildren(element, container) {
//Get the current node's class
var parentClass = element.attr('class');
//Go ahead and construct a list element
var parentContainer = $('<li class="' + parentClass + '">' + parentClass + '</li>');
//Now iterate over the current node's children (if there are any)
if (element.children().length > 0) {
var childList = $('<ul></ul>');
element.children().each(function () {
//Recursively call the list children function!
listChildren($(this), childList);
});
//Actually add the children to the current node
parentContainer.append(childList);
}
//Add us to our own container
container.append(parentContainer);
}
$('#main').children().each(function () {
listChildren($(this), $('#list-container #top-ul'));
});

Categories

Resources