jQuery next() selector when divs are not neighboring - jquery-selectors

Ive been using the following to change the width of the div.my-div that appears after the one you've clicked:
$(".my-div").click(function () {
$(this).next().css({'width':'500px'});
});
As my divs were neighboring, this worked fine:
<div class="my-div">stuff</div>
<div class="my-div">stuff</div>
<div class="my-div">stuff</div>
However now the structure has changed so they are no longer neighboring:
<div>
<div class="my-div">stuff</div>
</div>
<div>
<div>
<div class="my-div">stuff</div>
</div>
</div>
<div class="my-div">stuff</div>
Whats the simplest way to select the next element of the same class?
Thanks

jQuery will return elements in order of their appearance in the DOM.
As such, you could cache all the .my-div elements, use the index()[docs] method to get the index of the one that received the event, increment it and use the eq()[docs] method to get the next one.
var divs = $(".my-div"); // cache all of them
divs.click(function () {
var idx = divs.index( this ); // get the index in the set of the current one
divs.eq( idx + 1 ).css({'width':'500px'}); // get the one at the next index
});
This saves you from doing a bunch of unnecessary DOM selection and traversing.
Example: http://jsfiddle.net/VrATm/1/
EDIT: Posted wrong example link. Fixed.

You can traverse the tree hierarchy. That is, you can first jump to parent, then to next, then to children, like this:
$(this).parent().next().find(' > div').css({'width':'500px'});

Related

jQuery.on() for children with no particular selector

I have HTML structure like this:
<div class="parent">
<div class="child">
<div class="something">...</div>
</div>
<div class="child">
<div class="something-else">...</div>
</div>
<div class="child">
...
</div>
...
</div>
I catch events (like click) on .child elements like this:
$('.parent').on('click', '.child', function() { ... });
However, I would like to get rid of explicit class specification and base on the fact of direct ancestry itself.
I want to write the code which would not require any particular classes for children elements. Closest thing to this is:
$('.parent').on('click', '*', function() { ... });
But obviously such handler will spread on deeper descendants (.something, .something-else etc.), not only on the first level.
Is there a way to acheive what I look for, being it using something instead of * or some other way?
P.S. I don't want to use direct binding - $('.parent').children().click(function() {...}); - as it is slower and will not work in case of children being dynamically added.
The selector sought for is > *:
$('.parent').on('click', '> *', function() { ... });
(The actual solution was suggested by Josh Crozier in the comments, I just reposted it as an answer.)

getElementsByClassName('class') for ONLY the element that is clicked on

I have a series of divs with classes. I want to select the text within the div that is clicked on by the user.
In the example code below, if user clicks on the first div, the text consoled out should be: "Sample text ONE"
If the user clicks on the 2nd div, it should be "Sample text TWO"
I can accomplish what I want with divs that have Id's and getElementById('id').innerHTML
but I am forced to accomplish it with classes, which does not work.
Digging further:
I am understanding that getElementsByClassName returns an array like object, and document.getElementsByClassName(".sample_div")[0].innerHTML will kind of work, but it only returns the first element. Perhaps there is a way to replace the 0 with the index of the div that is clicked on?
Any way to do this with classes will be great. Thank you.
<!DOCTYPE html> <html>
<div class='sample_div'>Sample text ONE</div>
<div class='sample_div'>Sample text TWO</div>
</html>
<script type="text/javascript">
const divs = document.querySelectorAll('.sample_div');
divs.forEach(divSelect => divSelect.addEventListener('click', notice));
function notice() {
let text = document.getElementsByClassName('.sample_div').innerHTML;
console.log(text);
}
this will contain the clicked element
With jquery, you can create an event listener that listens to all .sample_div and reference it with this variable.
$(".sample_div").click(function(){
console.log(this.innerHTML)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='sample_div'>Sample text ONE</div>
<div class='sample_div'>Sample text TWO</div>
Without JQuery it should be like this:
//Get all the elements with the class "sample_div"
var sampleDivs = document.getElementsByClassName("sample_div")
//Iterate over the sampleDivs node array
for(var x=0, sampleDivsLength = sampleDivs.length; x<sampleDivsLength;x++){
//Add an event listener for each DOM element
sampleDivs[x].addEventListener("click",function(){
console.log(this.innerHTML)
})
}
<div class='sample_div'>Sample text ONE</div>
<div class='sample_div'>Sample text TWO</div>

Using Protractor to select elements with by.repeater()

Using the following Protractor element and by.repeater() API methods below:
var targetRowText = 'Sales';
var targetGridName = 'myGrid';
var sel = 'grid-directive[grid-name="' + targetGridName + '"] .col-freeze .grid-wrapper';
var gridRows = element(by.css(sel).all(by.repeater('row in vm.sourceData.data'));
var result = gridRows.all(by.cssContainingText('span', targetRowText)).first();
I am able to select the following row element from a grid which I have labeled, myGrid:
<div id="rowId_21" ng-class-odd="'row-2'" ng-class-even="'row-3'" ng-class="vm.hideRow(row)" class="row-3 height-auto">
<div ng-repeat="column in vm.sourceData.columns" >
<div ng-if="!column.subCols" class="ng-scope">
<div ng-if="row[column.field].length !== 0" class="ng-scope highlight21">
<span ng-bind-html="row[column.field] | changeNegToPrenFormat" vm.highlightedrow="" class="ng-binding">
Sales
</span>
</div>
</div>
</div>
</div>
Please note that I have used by.cssContainingText() to look up the "Sales" span element.
MY PROBLEM:
That that I have located this row in var result, how can I retrieve the id attribute of that outer-most div ?
In other words, I need to selected <div id="rowId_21" so that I can reuse id="rowId_21" in a subsequent Protractor selector.
In jQuery, for example, I could use brute force to get that outer div id as follows :
var el = $('grid-directive[grid-name="Sales"] .col-freeze .grid-wrapper #rowId_21 span')
el.parentElement.parentElement.parentElement.parentElement;
Here's a high-level outlines of what I mean. The grid actually separates the left-most column from the actual data rows, so there are two distinct divs that accomplish this:
<div grid-directive grid-name="myGrid">
<div class="col-freeze" >
<!-- CONTAINS LEFT-MOST "CATEGORIES" COLUMN -->
</div>
<div class="min-width-grid-wrapper">
<!-- CONTAINS THE DATA ROWS-->
</div>
However, I'm struggling to do this in Protractor.
Advice is appreciated...
Bob
A straight-forward option would be to get to the desired parent element using the ancestor axis:
element(by.xpath("./ancestor::div[starts-with(#id, 'rowId')]")).getAttribute("id").then(function (parentId) {
// use parentId here
});
Though, I think that this going down and then up the tree should be considered as a sign that you are not approaching the problem in an easy and correct way.

Swipe.js callback function

I'm using swipejs (https://github.com/bradbirdsall/Swipe) and want to add a class to certain DOM elements if the slide being slided to has a data attribute.
In this case a slide may have the attribute of data-colour="orange". When sliding to that slide I want to addClass '.orange' to any DOM element that hasClass '.colour'
HTML:
<!-- Slide 1 -->
<div class="slide" data-colour="orange">
<h1 class="center">we know sport</h1>
</div>
<!-- Slide 2 -->
<div class="slide" data-colour="blue">
<h1 class="center">we really know football</h1>
</div>
jQuery:
$(document).ready(function(){
var elem = document.getElementById('mySwipe');
window.mySwipe = Swipe(elem, {
callback: function(){
colour.addClass($('.slide').data('colour'));
}
});
});
This performs the desired action, but will only apply the data attribute of the current slide when sliding to the next slide, whereas I would like to work out the data attribute of the next slide, and when sliding to it add that as a class to other DOM elements.
Any help would be greatly appreciated.
Swipe 2.0 adds attribute data-index, so you could write:
$('#mySwipe [data-index='+(mySwipe.getPos()+1)+']').data('colour')

How to use "this" and not "this" selectors in jQuery

I have 4 divs with content like below:
<div class="prodNav-Info-Panel">content</div>
<div class="prodNav-Usage-Panel">content</div>
<div class="prodNav-Guarantee-Panel">content</div>
<div class="prodNav-FAQ-Panel">content</div>
And a navigation list like this:
<div id="nav">
<ul id="navigation">
<li><a class="prodNav-Info" ></a></li>
<li><a class="prodNav-Usage" ></a></li>
<li><a class="prodNav-Guarantee"></a></li>
<li><a class="prodNav-FAQ" ></a></li>
</ul>
</div>
When the page is first displayed I show all the content by executing this:
$('div.prodNav-Usage-Panel').fadeIn('slow');
$('div.prodNav-Guarantee-Panel').fadeIn('slow');
$('div.prodNav-FAQ-Panel').fadeIn('slow');
$('div.prodNav-Info-Panel').fadeIn('slow');
Now, when you click the navigation list item it reveals the clicked content and hides the others, like this:
$('.prodNav-Info').click( function() {
$('div.prodNav-Info-Panel').fadeIn('slow');
$('div.prodNav-Usage-Panel').fadeOut('slow');
$('div.prodNav-Guarantee-Panel').fadeOut('slow');
$('div.prodNav-FAQ-Panel').fadeOut('slow');
});
So what I have is 4 separate functions because I do not know which content is currently displayed. I know this is inefficient and can be done with a couple of lines of code. It seems like there is a way of saying: when this is clicked, hide the rest.
Can I do this with something like $(this) and $(not this)?
Thanks,
Erik
In your particular case you maybe able to use the .sibilings() method something like this:
$(this).fadeIn().sibilings().fadeOut()
Otherwise, lets say that you have a set of elements stored somewhere that points to all of your elements:
// contains 5 elements:
var $hiders = $(".prodNavPanel");
// somewhere later:
$hiders.not("#someElement").fadeOut();
$("#someElement").fadeIn();
Also, I would suggest changing the classes for your <div> and <a> to something more like:
<div class="prodNavPanel" id="panel-Info">content</div>
....
<a class="prodNavLink" href="#panel-Info">info</a>
This gives you a few advantages over your HTML. First: the links will have useful hrefs. Second: You can easily select all your <div>/<a> tags. Then you can do this with jQuery:
$(function() {
var $panels = $(".prodNavPanel");
$(".prodNavLink").click(function() {
var m = this.href.match(/(#panel.*)$/);
if (m) {
var panelId = m[1];
$panels.not(panelId).fadeOut();
$(panelId).fadeIn();
return false; // prevents browser from "moving" the page
}
});
});