How to identify the chosen selector in jQuery? - javascript

$('#select_id1, #select_id2, #select_id3').change(function() {
// If '#select_id1' has changed, 'str' should be equal to 'select_id1'.
// If '#select_id2' has changed, 'str' should be equal to 'select_id2'.
// If '#select_id3' has changed, 'str' should be equal to 'select_id3'.
str = <what should be here ?>
});

You can get the id of the element that invoked the change by this.id.
$('#select_id1, #select_id2, #select_id3').change(function() {
str = this.id;
});

Or (less efficiently):
$('#select_id1, #select_id2, #select_id3').change(function() {
str = $(this).attr("id");
});
But basically this is set to the element on which the event took place.

For the more general case, where not only IDs are used, as suggested by #Anurag, you can do the following:
// Save the selector
var selector = ".someClass, #someId, tr.someTrClass";
$(selector).change(function () {
var selectors = selector.split(","),
matching = []; // Remember that each element can
// match more than one selector
for (var i = 0, s; s = selectors[i]; i++) {
if ($(this).is(s)) matching.push(s);
}
str = matching.join(","); // Your list of all matching selectors
});

You can either look at this.id directly or indirectly via a passed in event object:
$('#select_id1, #select_id2, #select_id3').change(function (e) {
alert(e.target.id + ' == ' + this.id + ' ... ' + (e.target.id == this.id));
});
Most people just look at this but there are times when you might be interested in more than just the target of your event.

Related

iterate over array in jquery

I'm trying to do some validation on a user selecting items from a list. I want to make sure an item is not added twice by checking if the <li> is already in the array. This is what I'm trying and its not working.
$(".List").on("click", "li", function () {
var i = 0;
var checkArr = [];
var div = $("#AddedItems");
var parent = $(this).closest("ul");
var itemtoadd = parent.find("[data-id]").attr("data-id");
var name = parent.find("[data-name]").attr("data-name");
alert(itemtoadd + name);//checking
var itemtoadd = ("<li id = " + itemtoadd + " class = \"itemAdd\">" + name + "</li>");
checkArr.push(itemtoadd); //put one in to check against?
checkArr.forEach(item)
{
if (item == itemtoadd)
alert("this item has already been added");
else {
checkArr.push(itemtoadd);
alert(itemtoadd);
$(itemtoadd).appendTo(div);
}
}
// div.html(itemtoadd);
});
You have at least three problems here:
You aren't using Array.forEach correctly -- it takes a function that takes an item.
Immediately before you do your check, you're adding the item you're looking for. You will always hit the alert case.
You're using checkArr as a local variable -- you're getting an empty array each time you enter the function.
That all being said, you can accomplish your goal without keeping an array at all. I believe you can replace everything from your first alert down with this:
if ($('#' + itemtoadd, div).length == 0) {
itemtoadd = ("<li id = " + itemtoadd + " class = \"itemAdd\">" + name + "</li>");
div.append(itemtoadd);
}
else {
alert("this item has already been added");
}

How to make an array of CSS classes

How do I make an array of CSS classes, not the CSS class names? I need the "." and everything.
I need users to be able to click on certain buttons, and add the classes the button belongs to into an array.
I used this before:
var myPicks[];
$('.button').click( function() {
var hello = " " + $(this).attr('class').split(' ')[0];
myPicks.push(hello);
}
But that seems to add the name of the classes, not the classes themselves. It's possible I'm wrong and there's something wrong with another part of my JQuery code.
Try
var myPicks = [];
$('.button').click( function() {
Array.prototype.push.apply(myPicks, $.map($(this).attr('class').split(' '), function(value, idx){
return '.' + value
}))
console.log('myPicks', myPicks)
});
if you want only unique classes
var myPicks = [];
$('.button').click( function() {
$.each($(this).attr('class').split(' '), function(idx, value){
var selector = '.' + value;
if($.inArray(selector, myPicks) == -1){
myPicks.push(selector)
}
})
console.log('myPicks', myPicks)
});
Demo: Fiddle
I will not recommend save the name of the class with the dot included into that array(), It will be useless if you need it later for something else.
(Or your goint to need to split it again)
Instead, I suggest to save it like you have now and then and only when you needed, add the dot to that value
like:
var myPicks = new Array();
myPicks[0] = "something";
// original value:
var newValue = myPicks[0]; // newValue == 'something'
//used as ID:
var newValue = '#' + myPicks[0]; // newValue == '#something'
// used as a class:
var newValue = '.' + myPicks[0]; // newValue == '.something'
BUT, of course if you need that way... just replace the PUSH function and add the dot to it:
var newHello = '.' + hello;
myPicks.push(newHello);

How to change the id of deep nested elements with jQuery

I have this recursive code that transverses the DOM and adds a prefix to the id for all input tags.
I would like to change this to a more elegant jQuery, but I'm not sure how to structure the selectors or if the selectors need to be recursive..
cheers,
function set_inputs(obj, prefix){
for (var s=0;s< obj.childNodes.length; s++){
var node = obj.childNodes[s];
if(node.tagName == "INPUT"){
node.id= prefix +'_' + node.id;
node.name= prefix +'_' + node.name;
}
else{
set_inputs(node,prefix);
}
}
}
For the entire DOM.
It would be as simple as:
var prefix;
$("input").each(function(i,elem)
{
$(elem).attr("id", prefix + "_" + $(elem).attr("id"));
});
You could change the selector : $("input") - which selects all the doms inputs, to any other selector to target different elements.
If you wanted it separately in a function then:
function() set_inputs(col, prefix) {
col.each(function(i,elem)
{
$(elem).attr("id", prefix + "_" + $(elem).attr("id"));
});
}
You would then use it like this:
set_inputs($("input"), "abc");//prefix ALL the DOM's inputs with abc
set_inputs($("input.btn"), "abc");//prefix inputs with the css-class btn
No particular need to use jQuery for this either. It could be done in plain javascript without recursion using getElementsByTagName() like this:
function set_inputs(obj, prefix) {
var nodes = obj.getElementsByTagName("input");
for (var i = 0, len = nodes.length; i < len; i++) {
if (nodes[i].id) {
nodes[i].id = prefix + '_' + nodes[i].id;
}
if (nodes[i].name) {
nodes[i].name = prefix + '_' + nodes[i].name;
}
}
}
P.S. I added protection in the code that your code did not have in case input tags exist without an id or a name attribute so the code won't error out if it encounters that. If you didn't want that protection, the code would be shorter like this:
function set_inputs(obj, prefix) {
var nodes = obj.getElementsByTagName("input");
for (var i = 0, len = nodes.length; i < len; i++) {
nodes[i].id = prefix + '_' + nodes[i].id;
nodes[i].name = prefix + '_' + nodes[i].name;
}
}
You call this function by passing it two arguments, the DOM object that represents the top of the part of the DOM tree you want to search for input tags in and the prefix you want to add to the IDs. If you do something like this: set_inputs(document.body, "test") it will search the entire document. If you do something like this: set_inputs(document.getElementById("top"), "test"), it will only search a portion of the DOM tree (the part under the id=top element). You can pass it any arbitrary DOM object and it will only search the nodes in that hierarchy.
Just want to suggest a small change
$('input').each(function(){
this.id = prefix + this.id;
});
To pull the deep nested inputs, use jquery find(). This solution is much simpler code than recursive javascript. I did leave out the steps verifying the existence of id and name attributes which should be done for production code.
$(obj).find("input").each(function(){
$(this).attr('id',prefix + "_" + $(this).attr('id'));
$(this).attr('name',prefix + "_" + $(this).attr('name'));
});

PrototypeJS loop won't run

I have a loop which won't run using Prototype + Scriptaculous. It runs once for the first object in my array then stops.
var myMessages = new Object();
myMessages = ['success','info','warning','error']; // define the messages types
function hideAllMessages()
{
var messagesHeights = new Array(); // this array will store height for each
enter code here
// This one runs just once for the first item in the array
var i = 0;
myMessages.each(function(element) {
alert(element);
messagesHeights[i] = $('.' + element).getHeight();
i++;
$$('.' + element + ' message').invoke('hide');
});
//This won't run at all===============================
for (var index = 0; index < myMessages.length; index++)
{
messagesHeights[index] = $('.' + myMessages[index]).getHeight();
$('x').hide();
//$('.' + myMessages[i]).css('top', -messagesHeights[i]); //move element outside viewport
}
}
I'm not a prototype user, but here's what I see so far:
$ is for IDs. I believe you need $$ here:
$$('.' + element)
This returns an Array, so I think you need invoke() like this:
$$('.' + element).invoke('getHeight');
Also, .each() passes the index as the second argument to the callback, so you don't need to maintain your own i.
myMessages.each(function(element, i) {
Also, this:
$$('.' + element + ' message')
...would seem to be looking for elements with the tag named message. I assume you want a class instead.
$$('.' + element + ' .message').invoke('hide');

Unique NAME to clone() elements

How do I give an unique NAME or other ATTR to a element that is cloned?
Thank you in advance.
Use Math.random:
$('.some_element').each(function() {
var id = (Math.floor(Math.random()*10000000000000000));
$(this).clone().attr('id', id);
});
Or, if you'd like a "handle" on the original element, you could create a new id in this format:
ORIGINAL_ELEMENT_ID + SEPARATOR + RANDOM_NUMBER
E.g.,
$('.some_element').each(function() {
var id = [
this.id,
(Math.floor(Math.random()*10000000000000000))
].join('-');
$(this).clone().attr('id', id);
});
A hack-ish way to do this would be to use a global counter and keep incrementing it by One before adding the value to the name of the cloned element.
ex.
var count =1;
func some_func() {
var cloneElement = $(form).clone();
cloneElement.attr('name', cloneElement.attr('name') + count++);
}
$('.some_element').clone().attr('id','some_unique_id');

Categories