jQuery button click, get div with class - javascript

I'm currently working on a client script in jQuery and I'm trying to make it as generic as possible.
I'm looking for a way to select a div with the class ".targets" from a button click.
My markup looks something like this:
<form>
<!-- Products section -->
<div class="products">
<div class="container">
<div class="form-group">
<div class="col-md-12">
<button type="button" class="btn-add">Add</button>
</div>
</div>
<div class="targets">
...
</div>
</div>
</div>
<!-- Resources section, slightly different markup -->
<div class="resources">
<div class="container">
<br/>
<div class="form-group">
<button type="button" class="btn-add">Add</button>
</div>
<br/>
<div class="targets">
...
</div>
</div>
</div>
</form>
My jQuery looks like this:
$("form").on("click", "btn-add", function(e){
var targets = $(this).parent().parent().next();
});
This solution works "somehow", but what if the markup changes?
Is there a way in jQuery to select the closest div with the class ".targets" on button click?
Thanks :)

Use (this).closest(".container").find(".targets");
this will select the closest element with the class container and search for an element in that with the class targets
$("form").on("click", ".btn-add", function(e){
var targets = $(this).closest(".container").find(".targets");
console.log($(targets).text().trim())
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<!-- Products section -->
<div class="products">
<div class="container">
<div class="form-group">
<div class="col-md-12">
<button type="button" class="btn-add">Add</button>
</div>
</div>
<div class="targets">
target1
</div>
</div>
</div>
<!-- Resources section, slightly different markup -->
<div class="resources">
<div class="container">
<br/>
<div class="form-group">
<button type="button" class="btn-add">Add</button>
</div>
<br/>
<div class="targets">
target2
</div>
</div>
</div>
</form>

If you know they will always be within the .products element, you could do:
$(this).closest('.products').find('.targets');
A helpful guide for jQuery traversing methods: http://api.jquery.com/category/traversing/

Try this:
$(this).closest('.container').find('.targets')

You could use closest() which searches for selector higher up in tree and find() which searches for selector going down the tree
$(this).closest('.container').find('.targets')

Related

How to create a Xpath of the clicked element using Javascript or Jquery?

I have a webpage where I bind a click event on the element. When user clicks on the particular element. I want to get generate the XPath of the element starting from html or body tag. i.e "The Absolute Xpath"
Suppose in below html sample I click on span having text as "USA" so the Absolute Xpath would be
/html[1]/body[1]/div[2]/div[1]/div[1]/span[1]
<html>
<body>
<div class="header">Countries</div>
<div class="row">
<div class="row_in">
<div class="row_in_in">
<span>India</span>
</div>
</div>
</div>
<div class="row">
<div class="row_in">
<div class="row_in_in">
<span>USA</span>
</div>
</div>
</div>
<div class="row">
<div class="row_in">
<div class="row_in_in">
<span>UK</span>
</div>
</div>
</div>
<div class="row">
<div class="row_in">
<div class="row_in_in">
<span>France</span>
</div>
</div>
</div>
</body>
</html>
Do we have any library where it can help me generate the XPath where I pass the element Dom and it can generate it?
I came across few libraries but that help detect the Content inside the html based on provided Xpath.
You need to loop through clicked element and it parents to do this work. So you can call a function nesting to do this work.
var xpath;
$("*").click(function(e){
xpath = '';
addXpath($(this));
console.log(xpath);
e.stopPropagation();
});
function addXpath($ele){
var tagName = $ele[0].tagName.toLowerCase();
var index = $ele.parent().children(tagName).index($ele)+1;
xpath = '/'+tagName +'['+index+']'+ xpath;
!$ele.parent().is(document) ? addXpath($ele.parent()) : "";
}
body {background: green}
.header {background: orange}
.row_in {background: yellow}
.row_in_in {background: blue}
span {background: red}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="header">Countries</div>
<div class="row">
<div class="row_in">
<div class="row_in_in">
<span>India</span>
</div>
</div>
</div>
<div class="row">
<div class="row_in">
<div class="row_in_in">
<span>USA</span>
</div>
</div>
</div>
<div class="row">
<div class="row_in">
<div class="row_in_in">
<span>UK</span>
</div>
</div>
</div>
<div class="row">
<div class="row_in">
<div class="row_in_in">
<span>France</span>
</div>
</div>
</div>

How do I access all children and change the text one by one using for loop?

Consider this HTML code:
<div id="id1">
<div id="id2"></div><br>
<div id="id3"></div>
<br>
<div id="id2"></div><br>
<div id="id3"></div>
<br>
<div id="id2"></div><br>
<div id="id3"></div>
<br>
</div>
And this is my script:
for($olindex=0; $olindex<3; $olindex++){
$("#id1").children("#id3").eq($olindex).text(result2[$olindex]);
}
Now things are not working: There's nothing wrong with result2[$olindex] but still the text is not displayed in each element with id3. Maybe I've written wrong DOM code. How can I correct or change it to make it work?
Your selectors are incorrect. If you want to select elements by ID, use #:
var result2 = [0,1,2];
for(var $olindex=0; $olindex<3; $olindex++) {
$("#id1").children("#id3").eq($olindex).text(result2[$olindex]);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="id1">
<div id="id2"></div>
<div id="id3"></div>
<div id="id2"></div>
<div id="id3"></div>
<div id="id2"></div>
<div id="id3"></div>
</div>
That said, IDs must be unique. Use another approach, e.g. classes.
You've used several div elements with the same ID. ID should be unique per element, which is causing your issue.
You're better off using classes for your divs:
<div id="id1">
<div class="id2"></div><br>
<div class="id3"></div>
<br>
<div class="id2"></div><br>
<div class="id3"></div>
<br>
<div class="id2"></div><br>
<div class="id3"></div>
<br>
</div>
You can then use your JQuery Selector with a class instead:
$("#id1").children(".id3")
I think this is what you want to achieve:
'<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
</head>
<div id="id1">
<div id="id2"></div><br>
<div id="id3"></div>
<br>
<div id="id2"></div><br>
<div id="id3"></div>
<br>
<div id="id2"></div><br>
<div id="id3"></div>
<br>
</div>
<script>
for($olindex=0; $olindex<3; $olindex++){
$("#id1").children("#id3").eq($olindex).text(result2[$olindex]);
}
</script>'
If you are using IDs you need to use "#", not ".". "." is for classes.
Also, I don't recommend using the same ID for multiple elements.

Reveal Hidden Elements with Buttons

I have a row made of three buttons, and I need these three buttons to remain on the same row.
With that said, I am trying to make it so that each time one of these buttons is clicked, hidden content is displayed underneath them. Each button would show hidden content that is different from the other.
Is there anyway I can accomplish such a task using $(this) or must I assign a unique ID to each button and the relevant content it's supposed to show?
I have tried placing each button within a superclass called .items and the relevant content within this class as a child, called .description--so that I can access it using jQuery's .children() function--but this tends to mess up the row that my buttons are on (so that they are not all on the same row). Is there anyway to get around this?
What would be the simplest way to go about this?
Edit to show code:
<div class="displayers">
<div class="items">
<button type="button" class="btn btn-custom">Button 1</button>
<div class="row">
<div class="description">
<p> content here </p>
</div>
</div>
</div>
<div class="items">
<button type="button" class="btn btn-custom">Button 2</button>
<div class="row">
<div class="description">
<p> content here </p>
</div>
</div>
</div>
<div class="items">
<button type="button" class="btn btn-custom">Button 3</button>
<div class="row">
<div class="description">
<p> content here </p>
</div>
</div>
</div>
</div>
In order to make the buttons fit on the same row, I changed the ".items" class to have the property of "inline-block". The ".description" class is hidden, and I have some jQuery to reveal it.
var main = function() {
$('.items').click(function() {
$('.description').hide();
$(this).children('.description').show();
});
};
$(document).ready(main);
The problem with this is that my buttons are no longer on the same row.
I like to use data attributes and css selectors (easy to change later on), so I would use:
$('[data-show]').on('click', function(e) {
var toShow = $( $(this).data('show') );
toShow.siblings().hide();
toShow.show();
});
li {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>
<button data-show=".content > *:nth-child(1)">Open 1st</button>
<button data-show=".content > *:nth-child(2)">Open 2nd</button>
<button data-show=".content > *:nth-child(3)">Open 3rd</button></p>
<ul class="content">
<li>1st Container</li>
<li>2nd Container</li>
<li>3rd Container</li>
</ul>
Looks pretty simple to me, but does not mean others would agree. It really depends on your needs.
You can just toggle the elements which is next to your button with just class added to each element as below:
$('.btnshowdes').on('click',function(){
$(this).next('.desc').toggle();
});
.desc{
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="items">
<div class="internal">
<input type="button" class="btnshowdes" value="Toggle Description"/>
<div class="desc">Description 1</div>
</div>
<br/>
<div class="internal">
<input type="button" class="btnshowdes" value="Toggle Description"/>
<div class="desc">Description 2</div>
</div>
<br/>
<div class="internal">
<input type="button" class="btnshowdes" value="Toggle Description"/>
<div class="desc">Description 3</div>
</div>
<br/>
<div class="internal">
<input type="button" class="btnshowdes" value="Toggle Description"/>
<div class="desc">Description 4</div>
</div>
<br/>
</div>
FIDDLE DEMO
UPDATE
Based on your updated question to make it in the same row you just need to put an extra style to your .items as below:
.items{
display:inline-table; //helps to keep it in same row
padding:10px;//Just to make it feel good
}
Your js according to your html structure will be:
$('.btn-custom').on('click',function(){
$(this).next('.row').find('.description').toggle();
});
DEMO FIDDLE HERE
To solve your problem i would split my elements. Why don't you put each button in a different container (a div for instance), each container having his own id and his own content.
So when you click on a button you display the content inside of one div and the style of other buttons will not be affected.
Something like
<div class="container" id="1">
<button id="btn1"> Button one </button>
<!-- your content here linked to the script you use to display -->
</div>
<div class="container" id="2">
<button id="btn2"> Button two </button>
<!-- your content here linked to the script you use to display -->
</div>
<!-- etc... -->
So you don't have to worry and use complicated scripts, and each style will not be affected by the others modifications.

Dojo Button doesn't render inside ContentPane

I want to have a button inside a ContentPane but I can't get it rendering. I have the same code for display the button inside a ContentPane and outside everything, in the body. The first one doesn't get rendering and the second one does, so it doesn't display the correct way and it doesn't fire events. The code for the button is:
<button data-dojo-type="dijit/form/Button" data-dojo-props="iconClass:'dijitIconTask', onClick:function(){ console.debug('clicked simple') }">Simple</button>
And the code:
<body class="claro">
<button data-dojo-type="dijit/form/Button" data-dojo-props="iconClass:'dijitIconTask', onClick:function(){ console.debug('clicked simple') }">Simple</button>
<div data-dojo-type="dijit/MenuBar">
<div data-dojo-type="dijit/PopupMenuBarItem">
<span>SesiĆ³n</span>
<div data-dojo-type="dijit/DropDownMenu">
<div id="btnLogout" data-dojo-type="dijit/MenuItem" data-dojo-props="">Salir</div>
</div>
</div>
</div>
<div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'sidebar', gutters:true, liveSplitters:true" id="borderContainer">
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="splitter:true, region:'left'" style="width: 15%;" id="leftPane">
<div data-dojo-type="dijit/layout/ContentPane">
<input id="agentFilter">
</div>
<div data-dojo-type="dijit/layout/ContentPane" id="peopleTreePane" style="height: 90%">
</div>
</div>
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="splitter:true, region:'center'">
<div id="appCenterTabContainer" data-dojo-type="dijit/layout/TabContainer" data-dojo-props="splitter:true, region:'center'">
<div data-dojo-type="dojox/layout/ContentPane" title="Visitas" href="" id="visitasPanel">
<div>
<button data-dojo-type="dijit/form/Button"
data-dojo-props="iconClass:'dijitIconTask', onClick:function(){ console.debug('clicked simple') }">
Simple
</button>
</div>
</div>
<div data-dojo-type="dojox/layout/ContentPane" title="Logs" href="" id="logsPanel">
<div id="gridLogs" class="appGrid" style="height: 20em;"></div>
</div>
</div>
</div>
</div>
</body>
Thanks
It looks like the empty href attribute on your ContentPane is confusing Dojo's parser. You don't need that attribute unless you want the ContentPane to load its content from the server.
<div data-dojo-type="dojox/layout/ContentPane" title="Visitas" href="" id="visitasPanel">
<!-- ^ remove this -->
you are just missing height style property for borderContainer widget.
Cheers,
kiuma

jQuery UI draggable and rotatable parent

I'm trying to make a div with a bunch of childs rotatable with this plugin: https://github.com/trev/Rotatable
The element is draggable by the built in draggable function in jQuery UI. Here is my jQuery code.
$(document).on('mouseover', '.case .input', function(){
$(this).draggable({handle:'.drag'});
$(this).children('.resize.tl').parent().rotatable({ autoHide: false });
});
And here is my markup.
<div class="case">
<div class="case_background"></div>
<div class="case_model">
<!-- This is loaded by ajax -->
<div class="input" data-name="'+n+'">
<div class="drag">
<div class="icon"></div>
</div>
<div class="resize tl">
<div class="topleft"></div>
</div>
<input class="casetext opensans" type="text" name="textfield[]" size="25" value="The text">
<!-- End of ajax load -->
</div>
</div>
</div>
The only thing that is happening is the rotatable plugin does add divs with classes "rotatable-handle ui-draggable" every time you hover it.
How would you solve this? Do you see any problem?
I found out that the handle was what I should use.
$(document).on('mouseover', '.case .input, .case .image', function(){
var tc = $(this);
tc.rotatable({
handle:tc.children('.rotate.left, .rotate.right')
});
return true;
});
<div class="case">
<div class="case_background"></div>
<div class="case_model">
<!-- This is loaded by ajax -->
<div class="input" data-name="'+n+'">
<div class="drag">
<div class="icon"></div>
</div>
<div class="rotate left">
<div class="icon"></div>
</div>
<div class="rotate right">
<div class="icon"></div>
</div>
<input class="casetext opensans" type="text" name="textfield[]" size="25" value="The text">
<!-- End of ajax load -->
</div>
</div>
</div>

Categories

Resources