Replacing fields with jQuery - javascript

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

Related

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!

How to get the values of html hidden wrapped by a div using jquery?

Im very new to javascript and jquery so please bear with me.
Here's my code: http://jsfiddle.net/94MnY/1/
Im trying to get the values of each hidden field inside the div.
I tried
$(document).ready(function() {
$('input#btnDispHidden').click(function() {
var totalHidden = 7;
for(var i=0; i<totalHidden; i++) {
alert($("#hiddenField hidden").html());
}
});
});
but the value Im getting is null.
I also wanna know how to get the total number of html elements inside a div. In my case how am I gonna get the total number hidden field inside the div. I assigned the value of totalHidden = 7 but what if I dont know total number of hidden fields.
Please help. Thanks in advance.
$('#hiddenField hidden') is attempting to access an actual <hidden> tag that is a child of #hiddenField
Try this instead. What you want to use is the input[type=hidden] selector syntax. You can then loop through each of the resulting input fields using the jQuery.each() method.
If you want to iterate over the <input> elements and alert each value try this:
$(document).ready(function() {
$('input#btnDispHidden').click(function() {
$('#hiddenField input').each(function() {
alert(this.value);
});
});
});
http://jsfiddle.net/94MnY/8/
Here it is.
Basically, you are looking for .each(). I removed a few input fields because so many alert messages are annoying. Also added in the selector the type hidden to avoid getting your last input field.
$(document).ready(function() {
$('input#btnDispHidden').click(function() {
$('input[type="hidden"]').each(function(i){
alert($(this).attr('value'))
})
});
});
To stick to what you already have - but with few modifications:
DEMO
$(document).ready(function() {
$('input#btnDispHidden').click(function() {
var totalHidden = $('#hiddenField input[type=hidden]').length; // get number of inputs
for(var i=0; i<totalHidden; i++) {
alert($("#hiddenField input[type=hidden]").eq(i).val());
}
});
});
You can actually just create an array of those hidden elements using query and loop through them and alert their values.
I have put a jsfiddle for you to see
http://jsfiddle.net/94MnY/4/
$(document).ready(function() {
$('input#btnDispHidden').click(function() {
$("#hiddenField input[type='hidden']").each(function(i, e){
alert($(this).val());
});
});
});
Try
$('#hiddenfield input[type=hidden]').each(function(){
alert(this.val());
});

jQuery - Is there a more efficient way to do this?

http://jsfiddle.net/bGDME/
Basically, I want to show only whatever is selected in the scope and hide the rest.
The way I did it seems so.. I don't know. Tedious.
I was hoping to get some ideas of making it better. A point in the right direction would be very much appreciated, too.
Thanks.
You can minimize the code by using toggle() instead of your if/else statements
Working Example: http://jsfiddle.net/hunter/bGDME/1/
$('#scope').change( function(){
var type = $('option:selected', this).val();
$('#grade').toggle(type == 2 || type == 3);
$('#class').toggle(type == 3);
});
.toggle(showOrHide)
showOrHide: A Boolean indicating whether to show or hide the elements.
This seems fine to me, unless you have lots of or dynamic controls. However u can use JQuery addClass / removeClass, switch statement, multiple Selector $('#grade, #class').show(); to minimize the code
you can also use a switch state: http://jsfiddle.net/bGDME/3/
Here's an approach using HTML5 data attributes to declaratively set "scope levels" on the select boxes: http://jsfiddle.net/bGDME/6/
And the updated JavaScript:
var $scopedSelects = $('#grade, #class').hide();
$('#scope').change( function(){
var scopeLevel = $(this).val();
$scopedSelects.each(function() {
var $this = $(this);
$this[$this.data('scope-level') <= scopeLevel ? 'show' : 'hide']();
});
});
The primary advantage this one might have is that the code stays the same regardless of how many "scoped selects" you have (assuming you update the initial selector, of course).
what about this??
$(document).ready( function() {
$('#grade, #class').hide();
$('#scope').change( function(){
var type = $('option:selected', this).text();
alert(type);
$('select').next().not('#'+type).hide();
$('#'+type).show();
});
});
DEMO
Its very simple,
$(document).ready( function() {
$("select[id!='scope'][id!='school']").hide();
$('#scope').change( function(){
$("select[id!='scope']").hide();
var ken=$(this).val();
$("#"+ken).show();
});
});
If you want to make it a bit more dynamic by not touching the javascript when you want to add more select elements, then you can do small changes to your javascript code and HTML and you will only need to edit the HTML
Javascript:
$(document).ready(function() {
$('#scope').change(function() {
var type = $(this).val().split(',');
$('.values select').hide();
for (x in type) {
$('.values').find('#'+type[x]).show();
}
});
});
HTML:
<select id='scope'>
<option value=''>Select</option>
<option value='school'>school</option>
<option value='school,grade'>grade</option>
<option value='school,grade,class'>class</option></select>
This will do what you're looking for: http://jsfiddle.net/bGDME/30/
You simply use the val() of the scope within the eq() method to determine which sibling select should remain shown. If 'school' is chosen from the first dropdown, then neither get shown:
$(document).ready( function() {
var additionalSelects = $('#grade, #class');
$('#scope').change(function(){
var selectedVal = $(this).val();
additionalSelects.hide();
if(selectedVal > 1){
additionalSelects.eq(selectedVal - 2).show();
}
});
});

jquery reset after()

is there a way to reset/update an after() element? Not add another after() text. Thank you
Maybe this will helpful.
(Controller function for Emptiness of Form to be sent Server Input parameter ID of Form Parent DIV, output is 1-true, 0 false)
function emptynessCntrl(elementosForControl){
var controlResult=1;
$(elementosForControl).find('input').each(function() {
if($(this).val().trim()===""){
controlResult=0;
console.log($(this).attr('id')+' Element is empty');
$(this).nextAll().remove();
$(this).after('<div class="err-label">'+$(this).attr('placeholder')+' is empty</div>');
return controlResult;
}
else{
$(this).nextAll().remove();
}
});
return controlResult;
}
Your question is not clear. I'll asume you want to modify an element added with .after()
Instead of doing this:
$("#elem1").after('<div id="after />");
You could do this (use insertAfter)
$('<div id="after" />').insertAfter("#elem1").attr("width", 200).html("hi") ...;
Hope this helps.
Cheers.
When you add the element, give it a name
var newElement = $('<span>Some new stuff</span>');
$('.whatever').after(newElement);
Then, when you want to change it, simply remove the previous one first
newElement.remove();
newElement = $('<div>And now for something completely different</div>');
$('.whatever').after(newElement);
You can write a function that uses .data() to remember the new element as such: (I would change the names a bit though)
$.fn.addUniqueSomething = function (content) {
var existing = this.data('something-that-was-already-added');
if (existing) {
existing.remove();
}
var something = $(content);
this.after(something);
this.data('something-that-was-already-added', something);
};
Then you can use
$('.whatever').addUniqueSomething('<span>Some new stuff</span>');
// and later...
$('.whatever').addUniqueSomething('<div>And now for something completely different</div>');
And the second one will replace the first

JQuery, a new Selection using the results

Is there a way to me do this?
<img id="example" src="anything.jpg" title="something" class="abc" />
$('.abc').each(function(){
//test if this result is something
if( $(this)...(???)...('[src^=anything]')) == 'anything.jpg'){
}
//another Jquery selector test for this one
if( $(this)...(???)...('#example').size() > 0){
}
});
This is just an example, what I need is pretty more complex.. But I would like to know if there is a way to make other jQuery selector test in the result of a first selector.. since "find" will find the children of $(this).. and .parent() get alot of brothers..
See what I mean?
Do you have any idea?
So sorry.. let me try again..
$('div').each();
get all "div", right?
But now in that function I need to make another "test" check if div class is "red" or "blue"..
See?
I need to test something else of the result based in Jquery selector..
I know I could do:
class = $(this).attr('class'); and then if(class=="blue"){} .. But I would like to do $('this[class=blue]').size()>0){}
The jQuery is() filter operates on a found set to detect if something is true or not.
The jQuery filter() method will further pare down a found set based on criteria.
var allDivs = $('div');
var greenOnes = allDivs.filter('.green');
var redOnes = allDivs.filter('.red' );
I think you need the is method:
$('.abc').each(function() {
$(this).is('[src^=anything]')
});
This is fairly simple though, but I can't really tell what you are trying to do by the description. Maybe this is enough to get you started though.
You can use the filter and is methods to filter/search within a jQuery object.
if( $(this).is('[src^="anything"]') ) {
}
elseif( $("#example").size() > 0) {
}
You could put $("#example") in a variable outside of the loop and then reference it inside the loop as well.
if(this.src.indexOf("anything") === 0) {
// source starts with 'anything'
}
if($("#example").length) {
// since there can be only one #example
// in a *valid* document
}
Based on your edit:
if($(this).hasClass("blue")) {
...
}
?

Categories