jQuery - Find next select element - javascript

What I am trying to do is populate data in a select element. I'm using the following code, where a user selects a SubjectCategory from one drop down, which then should populate the next select element's html. The handler itself is working just fine, it returns the correct html I need to place inside the select element.
Also, keep in mind that I eventually clone both of these select elements and will need to populate them accordingly.
The problem is that $elem is always returning null.
I'm guessing that it's a problem with this line of code, however not quite sure (keeping in mind that I'm also cloning these two select elements):
var $elem = $this.closest('div').prev().find('select');
$(".SubjectCategory").live("click", function () {
var $this = $(this);
var $elem = $this.closest('div').next().find('select');
var a = $this.val();
$.get("/userControls/BookSubjectHandler.ashx?category=" + a, {}, function (data) {
$elem.html(data);
});
});
<div class="singleField subjectField">
<label id="Category" class="fieldSml">Subject Matter</label>
<div class="bookDetails ddl"><select id="ddlSubjectMatter" class="fieldSml SubjectCategory"></select></div>
<label id="Subjects" class="fieldSml">Category</label>
<div class="bookDetails ddl" id="subjectMatter"><select id="ddlSubjects" class="fieldSml Subjects"></select></div>
</div>

You're searching inside the <label>, not the next <div> as you want. next only gets one element after the current one.
Try this: It searches for the first div next to your parent element.
var $elem = $this.closest('div').nextAll('div').first().find('select');

Given that the source element has an id of ddlSubjectMatter and the target select element has an id of subjectMatter, it may be a lot simpler to capitalise the first letter of the second id (i.e. make SubjectMatter) then you get the second element by:
var elem = document.getElementById(this.id.replace(/^ddl/,''));
It makes the element relationship independent of the document layout.
Incidentally, it is invalid HTML to have select elements with no options, not that it is a big issue.

Why are you creating an extraneous $this variable? Unless you've omitted code that requires it for a different scope, just call $(this). That might be causing the problem, too.

Related

.appendChild() an HTML element on click

I wanted to copy an entire row including its' siblings and contents on button click. When I click the button the element, it appears in the console but doesn't append to the page. This is my code:
It doesn't show any error messages. I've tried innerHTML/outerHTML or append() it doesn't work.
$(document).ready(function() {
$('#addSubFBtn').on('click', function() {
var itm = document.getElementById("trFb");
var wrapper = document.createElement('div');
var el = wrapper.appendChild(itm);
document.getElementById("tbFb").append(el);
console.log(el);
});
});
Seems like what you're trying to do is clone the item after you get it from your document. W3schools website explains how to accomplish this. Check out the link: https://www.w3schools.com/jsref/met_node_clonenode.asp
Once you clone the node, [appendchild] should work as intended
Not sure (as said without seeing related HTML) but i see flaw in your logic:
var itm = document.getElementById("trFb");
still exist on the document(so in the page) so you've to retrieve it before you want to add/move it to another place.
using .removeElement will return you removed element(or null if no element matche the selector) so correct script should be:
var itm=document.getElementById("trFb").parentNode.removeChild(document.getElementById("trFb"));
as shown here to remove element you've to use method on to parent element.
So you can add it to any other element existing.
For more specific use or element created in global JS variable (such an createElement not yet appended) you can see :document.createDocumentFragment(); as explained here https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment

Grab the element with d3js

I'm trying to learn d3js library. Faced with the problem of the capture table's TD element by clicking. I usually use this way
window.addEventListener("load", function(){
document.getElementById("table_id").addEventListener("click",function(e){
var elem = e.target || e.srcElement;
if(elem.nodeName != "TD") return;
...
}
...
So i need to do something like that in d3js. But I don't know how to substitute .target and .srcElement methods.
What I do have
d3.select(#table_id).on('click',function(){
var elem = ???
In this i have my table. In d3.event such information click clientX=327, clientY=129. The d is undefined
Please, help me to grab TD element in var.
D3js is very flexible and you don't need to use d3.event.target every time.
As you asked, some details missed in your code:
1. Selection
There are two selection functions in d3 :
d3.select() it gets or finds specific tag or element or class or tag id, for example:
d3.select('div') returns first div or d3.select('.active') find tag have class named active. In your case you should used3.select('#table_id') you missed single quotation in select function.
The next d3 selection function is d3.selectAll() that act like d3.select() but the difference is this function select all the parameters, for example :
d3.selectAll('p') return all the p tags or all Id or classes get as parameter.
2. different between this and d
this is an argument that use to select specific tag you try to select or do some stuff on it and is more usable in selectAll function because you don't know which tag selected.
d is an object or DOM that contain all the properties and events.
So I changed your code and hope it's help you to learn d3 better.
d3.select("#table_id").on("click",function(){
var elem=d3.select(this);
if(elem.attr("name")!=="TD")
return;
});
more information here.

Looking to get index of first matched element within array

I'm looking to get index position of matched element within repeater and would like to know how I can find.
List of books below
element.all(by.repeater('books'))
within those rows, some rows will have below element
element(by.css('[ng-click="download"]')
and I want to do following
find element of download button (more than 1)
get index position of first download button (so I can do other stuffs later with .get(3) for specific row)
So here what I have tried.
element.all(by.css('some-css')).first().element(by.tagName('tag-within-css')).get(index);
element.all(by.css('some-css')).get(index).element(by.tagName('tag-within-css'));
Finding Sub-Elements - Protractor locators guide
some error such as index not defined or no method of 'get'.
Thanks.
I think you don't need to operate using element positions/indexes inside the repeater. Instead, find download buttons and operate with the current row using context/element specific element searches by chaining element and element.all:
var books = element.all(by.repeater('books'));
var downloadButtons = books.all(by.css('[ng-click="download"]'));
var firstDownloadButton = downloadButtons.first();
// here is how you can, for example, get the next div element to the download button
var nextElement = firstDownloadButton.element(by.xpath('following-sibling::div'));

What javascript method to target descendants?

I'm using a javascript function to set the value of a text field, based on the option chosen from a select field.
The javascript contains a lot of other stuff, but only the following is relevant to this question.
$(function (){
$('.source').live("change", function(e) {
var target = $(this).next('.target')[0];
----other stuff----
});
});
I originally had my form set up as follows, and everything worked fine.
<select class="source"></select>
<input class="target"></input>
I've subsequently added some styling, which has required extra divs.
<select class="source"></select>
<div class="level1">
<div class="level2">
<input class="target"></input>
</div>
</div>
Now the javascript function does not work, because the next method only targets siblings and not descendants.
So my question is, what method should I be using to target a specific descendant?
An important fact: this markup is part of a nested form, and is repeated several times on the same page. It is important that the function targets the correct .target field, i.e. immediately subsequent and descendant.
I've tried obvious candidates – .find(), .children() — but these don't seem to work. Would appreciate any ideas or pointers.
Thanks!
Now that in the new markup structure .target input is wrapped in a div with class level1 you can find that div first using next() and then use find() method to get to the .target input.
$(function (){
$('.source').live("change", function(e) {
var target = $(this).next('.level1').find('.target')[0];
----other stuff----
});
});
Note: Even if you don't pass any selector to next() also it will work fine because it only selects the immediate next sibling optionally filtered by the selector which we pass.
In your case this would work:
$(function (){
$('.source').live("change", function(e) {
var target = $(this).next().find('.target')[0];
----other stuff----
});
})
;
It's a descendant of the sibling, so this should do the trick:
var target = $(this).next('.level1').find('.target')[0];

jQuery $.data(): Possible misuse?

Perhaps I'm using $.data incorrectly.
Assigning the data:
var course_li = sprintf('<li class="draggable course">%s</li>', course["fields"]["name"]);
$(course_li).data('pk', course['pk']);
alert(course['pk']); // shows a correct value
alert($(course_li).data('pk')); // shows null. curious...
course_li is later appended to the DOM.
Moving the li to a different ul:
function moveToTerm(item, term) {
item.fadeOut(function() {
item.appendTo(term).fadeIn();
});
}
Trying to access the data later:
$.each($(term).children(".course"), function(index, course) {
var pk = $(course).data('pk');
// pk is undefined
courses.push(pk);
});
What am I doing wrong? I have confirmed that the course li on which I am setting the data is the same as the one on which I am looking for it. (Unless I'm messing that up by calling appendTo() on it?)
When you store the data:
$(course_li).data('pk', course['pk']);
you're creating an element but not saving it, so it's lost. Your alert test test the wrong value; it should be:
$(course_li).data('pk', course['pk']);
alert($(course_li).data('pk'));
which is null. Consider:
$(course_li);
$(course_li);
This creates two different elements with source equal to course_li, which are then promptly lost. What you need to do is create the element first, then work with that single element (i.e. don't call $(course_li) more than once). For example,
var course_li = $(sprintf('<li class="draggable course">%s</li>',
course["fields"]["name"]));
course_li.data('pk', course['pk']);
parent.append(course_li);
Note that course_li now holds an element, rather than a string.
try checking to see if the element being created by this call:
$(course_li)
is a single 'li' element, or a div. From the doco:
When the HTML is more complex than a single tag without attributes, as it is in the above example... snip ...Specifically, jQuery creates a new <div> element and sets the innerHTML property of the element to the HTML snippet that was passed in
So it's probably creating a div that you are assigning the data to, so when you select the 'li' itself, you are getting a child of the actual element that you set the data on.

Categories