jQuery value selector - javascript

I have:
<button class="Delete" value="1">Delete</button>
<button class="Delete" value="2">Delete</button>
<button class="Delete" value="3">Delete</button>
Given variable X that contains a value (in this case either a 1, a 2 or a 3), then how do I hide the button corresponding to the value in X?
I want to say something like:
$('button').val(x).hide();
Meaning: "The button whose value is x, hide".

$('button[value="' + x + '"]').hide();

You can write your own custom selector (I just felt someone should mention it). Could look like:
(function($) {
$.extend($.expr[':'], {
val: function(elem, i, attr) {
return elem.value === attr[3];
}
});
}(jQuery));
$('button:val(2)').hide();

You'd do that inside of the actual selector:
$('button[value="foo"]').hide();

This would require concatenating x into an xpath, but i can't think of another way right now.
$(button[value='1']).hide();
EDIT: removed #, apparently deprecated, much like myself :)

You don't even have to manually assign values to buttons:
var i = 0; $('.Delete').attr('value', function() {i++; return ''+i;});
will do it fou you. Now you have your buttons values counted.
But nevermind, (you don't even need values!) You can hide 'THIS clicked button' by doing:
$(".Delete").click(function() {
$(this).html("DELETED!").delay(900).slideUp(600).hide();
});
I've added a bit of animation.
Or combine both!
CIAO :)

Related

JavaScript - querySelectorAll and lower/uppercase

I have a problem with querySelectorAll. I use it like this:
Array.prototype.forEach.call(buttons, (btn) => {
this.setItemActive(target);
});
setItemActive(item) {
_.addClass(document.querySelectorAll(`[title="${item}"]`)[0], this.activeClass);
}
And it works, if provided item is written exactly the same as the target value in the said element. But I use text-transform on my buttons and it is causing a problem. I tried adding toLowerCase() to both, but this didn't help. What can I do?
As for me - title is not very comfortable to use in such situations. Think about a kind of identificator.
Proposition:
in your HTML code, make additional attr, kind of :
<a title="WrIght As You Wish" data-title="strictlowercasetitle" >Your info with title</a>
and in your JS :
Array.prototype.forEach.call(buttons, (btn) => {
this.setItemActive(target);
});
setItemActive(item) {
// make item lower case
_.addClass(document.querySelectorAll(`[data-title="${item.toLowerCase()}"]`)[0], this.activeClass);
}
I tried to setItemActive function and wrote this below function.
Hope this will be helpful to you
function _setItem(item){
console.log(item)
var m = document.querySelectorAll('a[title='+item+']')[0];
console.log(m)
}
_setItem("WrIght");
Check this jsFiddle

Making part of an Id name into a variable

I have a bunch of divs with matching ids (#idA_1 and #idB_1, #idA_2 and #idB_2, etc). In jquery I wanted to assign click functions, so that when I click an #idA it will show and hide an #idB.
Basically I want to make this:
$(".idA_x").click(function(){
$("idB_x").toggleClass("hide")
});
X would be a variable to make #idA and #idB match. I could write each individually, but that would take too much code, is there a way to make the number in the id into a variable?
Sure, you can do:
var num = 13;
addButtonListener(num);
function addButtonListener(num){
$("#idA_"+num).click(function(){
$("#idB_"+num).toggleClass("hide")
});
}
Try JQuery solution :
var x = 1;
$(".idA_" + x ).click(function(){
$(".idB_" + x ).toggleClass("hide")
});
Hope this helps.
There are many ways to achieve that, but what you probably want is to create a shared CSS class, e.g. .ids, and bind the event listener to that one:
$('.ids').click(function () {
//...
});
Then you can handle your logic in a cleaner way within the function body.
In order to make it dynamic, and not have to repeat the code for each one of your numbers, I suggest doing as follows:
First, add a class to all the div's you want to be clickable .clickable, and then use the id of the clicked event, replacing A with B in order to select the element you what to toggle the class:
$(".clickable").click(function(){
var id = $(this).attr('id');
$("#" + id.replace('A', 'B')).toggleClass("hide");
});
Or, you can also select all divs and use the contains wildcard:
$("div[id*='idA_']").click(function(){
var id = $(this).attr('id');
$("#" + id.replace('A', 'B')).toggleClass("hide");
});
This solution won't have the need to add a class to all clickable divs.
You can use attribute selector begins with to target the id's you want that have corresponding elements.
https://api.jquery.com/attribute-starts-with-selector/
Then get the value after the understore using split on the id and applying Array.pop() to remove the 1st part of the array.
http://jsfiddle.net/up9h0903/
$("[id^='idA_']").click(function () {
var num = this.id.split("_").pop();
$("#idB_" + num).toggleClass("hide")
});
Using regex would be your other option to strip the number from the id.
http://jsfiddle.net/up9h0903/1/
$("[id^='idA_']").click(function () {
var num = this.id.match(/\d+/g);
$("#idB_" + num).toggleClass("hide")
});

Jquery: Replace a part of each attribute [duplicate]

Do someone know what is the best way to replace some string inside a onclick attribute ?
I need to get the current value and replace some text inside parameters.
Exemple, I have this link:
My link
And I want this:
My link
In other words, I want something like this:
$('a').attr('onclick', $(this).attr('onclick').replace('1', '2'));
And I know I can do this, but I need something dynamic retreiving the values of current element:
$("a").attr('onClick', "myfunction('parameter2a','parameter2b')");
Finally it working when I made a simple demo: http://jsfiddle.net/GkWhh/4/
Thank you for your solutions !
$('a[onclick]').attr('onclick', function(i, v){
return v.replace(/1/g, '2');
});
http://jsfiddle.net/cj9j7/
If you need something more dynamic do not use onclick attributes, changing onclick attributes is hackish, you can use click method instead.
var param = 1;
$('a').click(function(){
// ...
if ('wildguess') {
param = 1;
} else {
param++;
}
})
sounds like a really bad idea but anyway - you can access the string value of the onlick attribute using something like that:
$('a').each(function() { this.attributes.onclick.nodeValue = this.attributes.onclick.nodeValue.replace('1', '2'); })
You can do this: http://jsfiddle.net/SJP7k/
var atr = $('a').attr('onclick');
var str = atr.split('1');
var natr = str.join('2');
$('a').attr('onclick',natr);

Why select option value is not selected after clone it? [duplicate]

I didn't expect it but the following test fails on the cloned value check:
test("clone should retain values of select", function() {
var select = $("<select>").append($("<option>")
.val("1"))
.append($("<option>")
.val("2"));
$(select).val("2");
equals($(select).find("option:selected").val(), "2", "expect 2");
var clone = $(select).clone();
equals($(clone).find("option:selected").val(), "2", "expect 2");
});
Is this right?
After further research I found this ticket in the JQuery bug tracker system which explains the bug and provides a work around. Apparently, it is too expensive to clone the select values so they won't fix it.
https://bugs.jquery.com/ticket/1294
My use of the clone method was in a generic method where anything might be cloned so I'm not sure when or if there will be a select to set the value on. So I added the following:
var selects = $(cloneSourceId).find("select");
$(selects).each(function(i) {
var select = this;
$(clone).find("select").eq(i).val($(select).val());
});
Here's a fixed version of the clone method for jQuery:
https://github.com/spencertipping/jquery.fix.clone
// Textarea and select clone() bug workaround | Spencer Tipping
// Licensed under the terms of the MIT source code license
// Motivation.
// jQuery's clone() method works in most cases, but it fails to copy the value of textareas and select elements. This patch replaces jQuery's clone() method with a wrapper that fills in the
// values after the fact.
// An interesting error case submitted by Piotr PrzybyƂ: If two <select> options had the same value, the clone() method would select the wrong one in the cloned box. The fix, suggested by Piotr
// and implemented here, is to use the selectedIndex property on the <select> box itself rather than relying on jQuery's value-based val().
(function (original) {
jQuery.fn.clone = function () {
var result = original.apply(this, arguments),
my_textareas = this.find('textarea').add(this.filter('textarea')),
result_textareas = result.find('textarea').add(result.filter('textarea')),
my_selects = this.find('select').add(this.filter('select')),
result_selects = result.find('select').add(result.filter('select'));
for (var i = 0, l = my_textareas.length; i < l; ++i) $(result_textareas[i]).val($(my_textareas[i]).val());
for (var i = 0, l = my_selects.length; i < l; ++i) result_selects[i].selectedIndex = my_selects[i].selectedIndex;
return result;
};
}) (jQuery.fn.clone);
Made a plugin out of chief7's answer:
(function($,undefined) {
$.fn.cloneSelects = function(withDataAndEvents, deepWithDataAndEvents) {
var $clone = this.clone(withDataAndEvents, deepWithDataAndEvents);
var $origSelects = $('select', this);
var $clonedSelects = $('select', $clone);
$origSelects.each(function(i) {
$clonedSelects.eq(i).val($(this).val());
});
return $clone;
}
})(jQuery);
Only tested it briefly, but it seems to work.
My approach is a little different.
Instead of modifying selects during cloning, I'm just watching every select on page for change event, and then, if value is changed I add needed selected attribute to selected <option> so it becomes <option selected="selected">. As selection is now marked in <option>'s markup, it will be passed when you'll .clone() it.
The only code you need:
//when ANY select on page changes its value
$(document).on("change", "select", function(){
var val = $(this).val(); //get new value
//find selected option
$("option", this).removeAttr("selected").filter(function(){
return $(this).attr("value") == val;
}).first().attr("selected", "selected"); //add selected attribute to selected option
});
And now, you can copy select any way you want and it'll have it's value copied too.
$("#my-select").clone(); //will have selected value copied
I think this solution is less custom so you don't need to worry if your code will break if you'll modify something later.
If you don't want it to be applied to every select on page, you can change selector on the first line like:
$(document).on("change", "select.select-to-watch", function(){
Simplification of chief7's answer:
var cloned_form = original_form.clone()
original_form.find('select').each(function(i) {
cloned_form.find('select').eq(i).val($(this).val())
})
Again, here's the jQuery ticket: http://bugs.jquery.com/ticket/1294
Yes. This is because the 'selected' property of a 'select' DOM node differs from the 'selected' attribute of the options. jQuery does not modify the options' attributes in any way.
Try this instead:
$('option', select).get(1).setAttribute('selected', 'selected');
// starting from 0 ^
If you're really interested in how the val function works, you may want to examine
alert($.fn.val)
Cloning a <select> does not copy the value= property on <option>s. So Mark's plugin does not work in all cases.
To fix, do this before cloning the <select> values:
var $origOpts = $('option', this);
var $clonedOpts = $('option', $clone);
$origOpts.each(function(i) {
$clonedOpts.eq(i).val($(this).val());
});
A different way to clone which <select> option is selected, in jQuery 1.6.1+...
// instead of:
$clonedSelects.eq(i).val($(this).val());
// use this:
$clonedSelects.eq(i).prop('selectedIndex', $(this).prop('selectedIndex'));
The latter allows you to set the <option> values after setting the selectedIndex.
$(document).on("change", "select", function(){
original = $("#original");
clone = $(original.clone());
clone.find("select").val(original.find("select").val());
});
If you just need the value of the select, to serialize the form or something like it, this works for me:
$clonedForm.find('theselect').val($origForm.find('theselect').val());
After 1 hour of trying different solutions that didn't work, I did create this simple solution
$clonedItem.find('select option').removeAttr('selected');
$clonedItem.find('select option[value="' + $originaItem.find('select').val() + '"]').attr('selected', 'true');
#pie6k show an good idea.
It solved my problem. I change it a little small:
$(document).on("change", "select", function(){
var val = $(this).val();
$(this).find("option[value=" + val + "]").attr("selected",true);
});
just reporting back. For some godly unknown reason, and even though this was the first thing I tested, and I haven't changed my code whatsoever, now the
$("#selectTipoIntervencion1").val($("#selectTipoIntervencion0").val());
approach is working. I have no idea why or if it will stop working again as soon as I change something, but I'm gonna go with this for now. Thanks everybody for the help!

Replacing fields with jQuery

Why is line 10 returning null?
http://pastie.org/720484
it works with line 40
You do not seem to have a proper grasp of the siblings() operator. You also were not utilizing jQuery's val() function and were missing periods on some of your class names. To locate the address1 class you would need to do the following:
var $checkbox = jQuery(this);
$checkbox.parent().siblings('.formField').find('.address1');
Also, you would want the alert to be
alert($checkbox.parent().siblings('.formField').find('.address1').val());
to alert the value of the input box.
FIXED AND OPTIMIZED VERSION:
function update_address(eventObject) {
var $checkbox = jQuery(this);
var $siblings = $checkbox.parent().siblings('.formField');
if ($checkbox.attr('checked')) {
$siblings.find('.address1').val($('.hidden_address1').val());
$siblings.find('.address2').val($('.hidden_address2').val());
$siblings.find('.city').val($('.hidden_city').val());
$siblings.find('.state').val($('.hidden_state').val());
$siblings.find('.zip').val($('.hidden_zip').val());
$siblings.find('.province').val($('.hidden_province').val());
$siblings.find('.country').val($('.hidden_country').val());
} else {
$siblings.find('.address1').val('');
$siblings.find('.address2').val('');
$siblings.find('.city').val('');
$siblings.find('.state').val('');
$siblings.find('.zip').val('');
$siblings.find('.province').val('');
$siblings.find('.country').val('');
}
}
try fetching the input:text's .val() instead
On line 9, shouldn't it be var checkbox = $(this); instead? I've not seen the jQuery() function used like that.
Because <input class="address1"/> is not a sibling of <input id="parent_sameAsBefore"/>. I think you want:
checkbox.parent().parent().find('.address1');
Why not just go with finding the form fields using absolute path?
Unless your DOM is very convoluted (and you need relative paths), I would prefer this approach myself.
Also use .val() to get and set values.
function update_address(eventObject) {
if($(this).attr('checked')) {
$('#parent_address1').val($('hidden_address1').val());
$('#parent_address2').val($('hidden_address2').val());
$('#parent_city').val($('hidden_city').val());
$('#parent_state').val($('hidden_state').val());
$('#parent_zip').val($('hidden_zip').val());
$('#parent_province').val($('hidden_province').val());
$('#parent_country').val($('hidden_country').val());
}
else {
$('#parent_address1').val("");
$('#parent_address2').val("");
$('#parent_city').val("");
$('#parent_state').val("");
$('#parent_zip').val("");
$('#parent_province').val("");
$('#parent_country').val("");
}
}
Note, seems to be a bug in the original code in line 15:
checkbox.siblings('.tate').value = $('hidden_state').value;
Should be:
checkbox.siblings('.state').value = $('hidden_state').value;
alert(checkbox.siblings('.address1').html() ); // This should be
alert(checkbox.parent().siblings('.address1').html() );
//Checkbox does not have siblings
Line 10

Categories