JQuery is(":focus") - javascript

It seems that for some reason, I cannot perform:
$(".exampleClass")[0].is(":focus");
It tells me - TypeError: undefined is not a function.
What I am trying to do is grab a few elements with jquery, scan through them, and find which one is focused (so that I can focus the next element in the array programmatically).
var fields = $(".textField");
var selected = false;
for(var j = 0; j < fields.length; j++){
var field = fields[j];
console.log(field);
if(selected){
field.focus();
}else if(field.is(':focus') && !selected ){
selected = true;
}
}
It all works fine until field.is(':focus') Why won't this work?

When you index into the jQuery object with the [ ] operator, you extract the underlying component of the list of matched elements. That component will be a DOM node, and it won't have a .is() method.
If you coded it like
$(".exampleClass").eq(0).is(":focus");
you'd be working with a jQuery object, and you wouldn't have the problem.

Related

.hide() is not a function error when executing from a loop

I want to be able to loop over a few different labels and hide their content based on if a radio button is check or not. This is the solution I came up with, but I keep getting an error in the console.
var hazardOptions = $(".js-hazardous-option");
var hazard = $("input[name=Hazardous]");
for (var i = 0, len = hazard.length; i < len; i++) {
if (hazard[i].id === "HazardousYes" && hazard[i].checked) {
for (var ii = 0, length = hazardOptions.length; ii < length; ii++) {
hazardOptions[ii].show();
}
} else if (hazard[i].id === "HazardousNo" && hazard[i].checked) {
for (var iii = 0, leng = hazardOptions.length; iii < leng; iii++) {
hazardOptions[iii].hide();
}
}
}
The error I get is:
hide() is not a function
Not sure what I'm missing, I've tried having a look online for a similar issue, but with no luck. I'm pretty sure that the problem is here: hazardOptions[iii].hide(); but not really sure why and/or how to fix it.
When you have a list of objects from a JQuery selector, if you try to access them via index you actually get the DOM element back and not the JQuery object. It's confusing for sure but it is in the documentation.
What you effectively need to do is turn it back into a JQuery object:
$(hazardOptions[iii]).hide();
Or you can use the eq() function with does provide the JQuery object ad thus still has the hide() function:
hazardOptions.eq(iii).hide();
Most probably you need to wrap it with $
$(hazardOptions[ii]).hide()
As you currently have it, if hazard.id === "HazardousYes", you are showing all hazardOptions, and if it is "HazardousNo"you are hiding all of them.
You can call .show() and .hide() on a jQuery collection and it will apply that to all elements in the collection. The below code will replicate the logic of your original code, however, the hazardOptions final show/hide state will be solely determined by the last hazard that is checked and has an id equal to "HazardousYes" and "HazardousNo". This may be what you want, but I would imagine it's not.
var hazardOptions = $(".js-hazardous-option");
var hazards = $("input[name=Hazardous]");
hazards.each(function (index, hazard) {
if (hazard.checked) {
if (hazard.id === "HazardousYes") {
hazardOptions.show();
} else if (hazard.id === "HazardousNo") {
hazardOptions.hide();
}
}
}
Edit - Come to think of it, if you don't have elements with duplicate IDs, You can make this really simple:
hazardOptions.show($("#HazardousYes").is(":checked"));
hazardOptions.hide($("#HazardousNo").is(":checked"));

Delete object by attribute in javascript

I have a few different tables on the same page but unfortunately they were not assigned any unique id's. I want to remove a table using a JS command, but since id cannot be used, is it possible to delete a table based on a certain attribute it has? For example, is there a command to delete all tables on the page that have the attribute: width="25%" ?
You can use querySelectorAll to do that.
var x = document.querySelectorAll("table[width='25%']");
for (var i=0; i<x.length; i++) { //returns array of elements that match the attribute selector
x[i].remove(); //call prototype method defined below
}
Removing is tricky, I found this code that makes a nice remove method
Element.prototype.remove = function() {
this.parentElement.removeChild(this);
}
NodeList.prototype.remove = HTMLCollection.prototype.remove = function() {
for(var i = 0, len = this.length; i < len; i++) {
if(this[i] && this[i].parentElement) {
this[i].parentElement.removeChild(this[i]);
}
}
}
This creates a prototype remove() function that iterates the node and deletes the children.
Please note that querySelectorAll will not work in IE8 or below, but the poster of the prototype method said that it should work in IE8 but not 7.
I know this already has some solutions, but I'll offer up one more alternative.
var tables = document.getElementsByTagName('table');
for(var i = 0; i < tables.length; i++){
if(tables[i].getAttribute('width') == "25%"){
tables[i].parentNode.removeChild(tables[i]);
}
}
Demo at http://codepen.io/michaelehead/pen/HfdKx.
Yes you can. The easiest way is to use JQuery.
In your javascript code you would just write:
$("[attribute=value]").remove()
So in your case it could be something like $("table[width='25%']").remove()

For cycle or for each with js objects

I got a problem to add a onclick event to object who can be many times in same page
I am trying to
var i;
for (i = 1; i<=10; i++) {
var tmpObj='lov_DgId_D_'+i;
var tmpObj2=tmpObj.getElementsByTagName('a')[0];
if (tmpObj2 != null) {
tmpObj2.onclick= DgIdOnClick;
}
}
But got a error TypeError:
Object lov_DgId_D_1 has no method 'getElementsByTagName' , but this is working
lov_DgId_D_2.getElementsByTagName('a')[0].onclick= DgIdOnClick;
This ibject lov_DgId_D_ can be from 1 like lov_DgId_D_1 or lov_DgId_D_99 u.t.c
What wil be the best solution to add onclick to all lov_DgId_D_* objects ?
As you use jquery, the simplest is
for (i = 1; i<=10; i++) {
$('#lov_DgId_D_'+ i+ ' a').click(DgIdOnClick);
}
If you want to bind your event handler to all a elements inside elements whose id starts with lov_DgId_D_, then it's as simple as
$('[id^="lov_DgId_D_"] a').click(DgIdOnClick);
The problem you have is a confusion between the id of an element and the actual element. Some code that should work for you is this one:
var i;
for (i = 1; i<=10; i++) {
var tmpObj=document.getElementById('lov_DgId_D_'+i); // <-- here
var tmpObj2=tmpObj.getElementsByTagName('a')[0];
if (tmpObj2 != null) {
tmpObj2.onclick= DgIdOnClick;
}
}
Slightly easier to read code:
for (var i=0; i<=10; i++) {
var anchor = document.querySelector('#lov_DgId_D_'+i + ' a');
if (anchor) anchor.onclick = DgIdOnClick;
}
A note: this code attaches a click event to the first anchor (a element) inside each element with the id lov_DgId_D_n, with n being 1->10. Your original code seems to want to do the same thing.
Another note: usually when you iterate over elements using their id's to identify them, you are better suited to add a class to those elements instead. It provides for more maintaintable code and probably easier to understand as well.

Javascript getElemtsByClass select [all]

I want to select all elements with the css class
.arrow-down
Sorry but i simply dont find the correct answer, for my problem!
I have an javascript code:
document.getElementsByClassName("arrow-down")[0].style.borderTopColor=""+blu+"";
so how do i select not the first but [all] or is there a way to [1;2;3;]??
getElementsByClassName("arrow-down")[all]
getElementsByClassName("arrow-down")[1;2...]
I tried many things but simply dont get it!
Greetings from germany!
You need to iterate over the list of returned results.
var elements = document.getElementsByClassName("arrow-down");
for (var i = 0, len = elements.length; i < len; i++){
elements[i].style.borderTopColor = blu;
}
If you want to only do a specific subset based on the index, then you can add a condition that checks the value of i. I'm also assuming that blu here is a variable you have defined somewhere?
for (var i = 0, len = elements.length; i < len; i++){
if (i === 1 || i === 2 || i === 3){
elements[i].style.borderTopColor = blu;
}
}
Unfortunately, JavaScript does not have a shorthand for accessing a specific subset of array values, or for applying changes to multiple elements at once. That is something that jQuery does automatically for you. For instance, with jQuery you could write this as:
$('.arrow-down').css('borderTopColor', blu);
document.getElementsByClassName("arrow-down") does select all of such elements.
These are returned in a node list (which can be treated as an array), which is why using [0] on that returns the first element.
Loop over the different elements that the expression returns and act on them:
var elements = document.getElementsByClassName("arrow-down");
var elementsNum = elements.length)
for(var i = 0; i < elementsNum; i++)
{
var anElement = elements[i];
// do something with anElement
}

remove element from array when checkbox unchecked

I add an element to an array when the checkbox is checked and I need to remove it when it is unchecked. I use splice to remove an element. I just can't seem to call an event when it's unchecked. I tried using this:
if ($('input[name="'+category+'"]:checked'))
item_id[category] = $(this).attr("id");
else
item_id.splice(category, 1);
It adds the needed element ok, when the checkbox is checked, but it doesn't seem to remove it when it's unchecked. Variable category is a loop variable and is correct.
If someone can work this out, it would be greatly appreciated.
jQuery selectors always return an object whether an element is matched or not.
What you've effectively got is:
if (new Object())
item_id[category] = $(this).attr("id");
else
item_id.splice(category, 1);
Objects are always truthy (no matter if it's an empty object, or an object John Resig initialized), so this if statement will never execute the else.
What you're probably after is:
if ($('input[name="'+category+'"]:checked').length)
item_id[category] = $(this).attr("id");
else
item_id.splice(category, 1);
Which checks the length property instead.
This still won't work however, as splice() will shift all elements in your array; making the category wrong.
If your binding the event on a number of checkbox elements, it will be unwise to use .bind() (and it's counterparts .click()), as this method will bind an event for each checkbox. Instead, use .live(), or .delegate(); this will bind one event to an ancestor of all checkbox elements, and listen for event (using JavaScripts event bubbling), which is much more efficient.
Taking both of these points into consideration, you might fancy something like this.
$(yourJquerySelector).live('change', function () {
var category = '?' // (this.value ?)
item_id[category] = this.checked ? this.id : undefined;
});
Not entirely sure what you are after to be honest, but here is my solution to this,hope it works for you in some way
Javascript Array - indexOf Method:
http://www.tutorialspoint.com/javascript/array_indexof.htm
<script>
if (!Array.prototype.indexOf)
{
Array.prototype.indexOf = function(elt /*, from*/)
{
var len = this.length;
var from = Number(arguments[1]) || 0;
from = (from < 0)
? Math.ceil(from)
: Math.floor(from);
if (from < 0)
from += len;
for (; from < len; from++)
{
if (from in this &&
this[from] === elt)
return from;
}
return -1;
};
}
$(function() {
var checkedItems = new Array();
$(":checkbox").change(function () {
if($(this).attr('checked'))
{
checkedItems.push($(this).attr("id"));
}
else
{
var index = checkedItems.indexOf($(this).attr("id"));
checkedItems.splice(index,1);
}
});
});
</script>
HTML
<input type="checkbox" id="c1" value="1">
<input type="checkbox" id="c2" value="2">
<input type="checkbox" id="c3" value="3">
The splice function is meant to return what's removed, so start debugging by displaying its return value.
Change your if condition to:
$('input[name="'+category+'"]').is(':checked')
As mentioned by Matt, your current if condition is a selector that returns a list of jQuery elements. Testing the number of elements returned (using the length property) would also do the trick.

Categories