How to store multiple related values in javascript? - javascript

I have a set of checkboxes in a page and each checkbox is associated with a textbox.
What I need to do is to disable the textbox if the checkbox is unchecked and put a default value inside it(each textbox has a different default value).
Right now I have written a function which accepts checkboxId, textboxId and the default value which is called onClick of the checkbox.
Is there a way to store this information(checkBoxId,textBoxId,defaultValue) statically(like a map or something) in javascript so that my function does not require any arguments and can be called onLoad of the page?

This is something I did before:
<input type="checkbox" id="sample">
<input data-requires="sample" data-default="Default">
function applyControls(){
$("input[data-requires]").each(function(){
var target = $(this);
$("#" + target.data("requires")).click(function(){
if(this.checked){
target.prop("disabled", false);
}else{
target.prop("disabled", true).val(target.data("default"));
}
});
});
}
applyControls();
Note: This code is written with jQuery. You can easily convert this to native code by substituting jQuery methods with native methods.
Demo: http://jsfiddle.net/DerekL/VnHAc/
Now this way you don't have to create any map or Object to store these relations (you don't even need ids for individual textboxes!) By using data-* attributes, you do not have to modify a "map" every single time you add connections. In fact, this is the preferred way1 of doing it in HTML5.
1 https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes

Related

How to grab ID of element which ID has been dynamically given?

I’m trying to make a simple show when checkbox is checked kind of section but am unable to get a hold of the element because the IDs of the element are assigned dynamically by PHP.
The element will be inside a foreach loop so there will be multiple instances of it with dynamically given IDs.
example:
//Laravel blade template
<element id="attrb{{ $elem->id }}> "></element>
//Javascript
if ($("#attrb*ID").is(":checked")) {
$("#attrbs-container").show();
} else {
$("#attrbs-container").hide();
}
With Jquery
$('input[id^="attrb"]').change(function(e){
if($(this).is(':checked')) console.log($(this).prop('id'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" id="attrb1" value="1" />
Run, and check the box. You can replace console.log with your .show or whatever.
The selector input[id^="attrb"] means an input with an id that ^= starts with attrb. You could also use input[type="checkbox"] if these are the only checkboxes you have, but it's less specific.
Change vs Click
change fires when the data (state) of the element changes. click will trigger anytime you click. In this case it probably doesn't matter too much which you use. A better example of change vs click is using radio buttons, and clicking an already checked radio. Checkboxes un-click when checked, radio buttons not so much. I'm just in a habit of using change over click for state changes.
$('input[id^="attrb"]').click(function(e){
if($(this).is(':checked')) console.log($(this).prop('id'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="radio" id="attrb1" value="1" />
Run and click the radio 2x. It fires 2 times.
$('input[id^="attrb"]').change(function(e){
if($(this).is(':checked')) console.log($(this).prop('id'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="radio" id="attrb1" value="1" />
Do the same thing here, but with change. That's the difference.
DYNAMIC vs Dynamic
What I mean here is DYNAMIC is something that changes at run time on the client, Dynamic is static HTML where the ID changes on the server side only. For DYNAMIC you want to use on like this
$(someparent).on('change', 'input[id^="attrb"]', function(e){ ... });
Where someparent is a static element that doesn't change at runtime. This will use event delegation and "bubbling" to find the content that was changed on the client side.
I don't think you meant DYNAMIC but I included it just in case.
Cheers!
you could create a function with a callback if you're assigning the id with javascript (after an ajax request)
function addID(add, callback)
Then use the funciton:
addId(function(){
//dynamically add ID
}, function(){
// callback function
if ($(“#attrb*ID”).is(":checked")) {
$(“#attrbs-container").show();
} else {
$(“#attrbs-container").hide();
}
})

Smarty / Dojo checkbox onCheck uncheck other checkbox

I am using Dojo labels and checkboxes in one of my app inside smarty file. I want to add a certain behavior to uncheck a checkbox, if any other checkbox is checked. I also check if that checkbox is originally checked, it will uncheck the same. (I do not want to use radio button)
Here is my code for one CheckBox:
<input id="form.cs"
data-dojo-type='dijit.form.CheckBox'
type="checkbox"
data-dojo-props="value:'true', type:'checkbox', name:'cs', style:'vertical-align: top'"
onChange="if(dijit.byId('form.cs"').checked)
dijit.byId('form.cs"').set('checked', false);
else
dijit.byId(' form.nl"').set('checked', false);"
/>
The problem with code is when i add curly braces, this is not rendered by smarty engine and throws error.
For example :
onChange="if(dijit.byId('form.cs"').checked) {
dijit.byId('form.cs"').set('checked', false); }
else {
dijit.byId(' form.nl"').set('checked', false);"}
The above code snippet will create a breakdown in the smarty.
I recommend writing your event handler in JavaScript. If you're going to write all your event handlers as attributes you're going to have a lot of problems like code validation, ... .
You could write a loop that actually loops over all checkboxes, setting the value to the opposite of the changed value (so if one checkbox becomes true, the other ones must become false).
To do this you could write a simple function like this:
var toggleCheckboxes = function(myNode, value) {
query("input[type=checkbox]").forEach(function(node) {
if (node !== myNode) {
registry.getEnclosingWidget(node).set("value", !value, false);
}
});
};
The dojo/query module allows you to get a list of all nodes matching the given selector. With the dijit/registry module you can retrieve the actual widget behind the DOM node and then you just set the value using:
registry.getEnclosingWidget(node).set("value", !value, false);
The third parameter (set to false) is actually very important. This parameter will prevent further event invocations. If you don't put that parameter there it will actually trigger another onChange, causing an infinite loop.
Now the only thing you need to do is bind an onChange event handler to each checkbox that calls this function, you can also to that with the dojo/query and dijit/registry module, for example:
query("input[type=checkbox]").forEach(function(node) {
registry.getEnclosingWidget(node).on("change", function(value) {
toggleCheckboxes(node, value);
});
});
A complete example can be found on JSFiddle.
But I still recommend using a radiobutton. I think you can actually say this is a bad UI design, a checkbox and a radiobutton have different goals, use them for what they're meant to.

How to get values from dynamically added (using javascript) elements?

On my aspx page I dynamically create html controls on client side using javascript. For example, after page load you can click button in a browser, by clicking button html input and select elements appear. You may click once again, and this elements (input and select) will added again. So, you can create so many inputs and selects as you want (all this using javascript, no postbacks)
After user created some inputs and selects and entered some information in it, he posted form. I want on server side to find all this dynamically added elements and perform some actions depends on values in this controls.
How can I find dynamically added elements, and what is the best and elegant way to achieve this?
Thanks in advance.
In the Javascript that creates the new elements, increment a counter each time an element is created. Add the value of the counter to the name of the input element so each element has a unique name.
Add the final value of the counter to a hidden form field when the form is posted.
In your server side code, create a loop that starts at zero and continues until you have reached the value of the counter. Within the loop, fetch the posted value of the corresponding form field.
When you add the elements, assign unique IDs to them, and then retrieve their values using Request.Form["UniqueIdHere"] (C#) or Request.Form("UniqueIdHere") (VB.NET).
Create a loop that loops through each input and select object, that grabs the name/id of the current object and its corresponding value. Then add those items to an array and once the loop is completed, pass those values to your aspx file.
You can view an example with this approach at: http://jsfiddle.net/euHeX/. It currently just alerts the values, but you could easily modify it to pass the values as a parameter via ajax to your handler aspx file. The code will add new inputs or select boxes based off of the input provided. This would of course be modified to reflect your current setup.
HTML:
<div id="dynamic"></div>
<input type="button" id="submit-form" value="Submit>>">
JavaScript (using jQuery):
function createInput(type){
for(var i=0; i<5; i++){
if(type==0){
var obj = '<input type="text" id="'+i+'" class="dynamicContent">';
}else if(type==1){
var obj = '<select id="'+i+'" class="dynamicContent"><option>--Select--</option></select>';
}
$("#dynamic").append(obj);
}
}
function getContent(){
var inputArray = [];
$(".dynamicContent").each(function(k,v){
var o = $(this);
var oType;
if(o.is("input")){ oType = "input"; }
if(o.is("select")){ oType = "select"; }
var oID = oType+o.attr("id");
var oValue = o.val();
inputArray.push(oID+'='+oValue);
});
alert(inputArray);
}
$("#submit-form").click(function(){
getContent();
});
// Set type to 0 for input or 1 for select
var type = '1';
createInput(type);
If you're using jQuery you can use .live() to achive this like a peace of cake!
http://api.jquery.com/live/
I don't know if your controls will survive the postback the way you're creating them, but a good technique for accessing dynamically generated controls (assuming that you've figured out how to persist them) is to do something like the following:
Add a panel to your page. Add your dynamically created controls to this panel.
In the OnClick event handler (or other method), do something like the following:
foreach (DropDownList ddl in Panel1.Controls.OfType<DropDownList>())
{
//put code here
}
foreach (TextBox txt in Panel1.Controls.OfType<TextBox>())
{
//put code here
}

Jquery checkboxes within containing table selector question

My current code:
<script type="text/javascript">
function checkAll(checked) {
$("input[type='checkbox']:not([disabled='disabled'])").attr('checked', checked);
}
</script>
<input type="checkbox" id="cbxSelectAll" onclick="checkAll(this.checked);" />
The short version:
How do I modify the function call and method above to check all checkboxes inside a table containing the checxbox form element.
The long version:
I am creating a WebUserControl containing a grid view in asp.net that is going to have a delete option. I would like the delete to be a series of checkboxes with one a box in the header to select all of them. What this amounts to for non ASP.NET people is a table with a header row that has a checkbox and every row also has a checxbox.
I have used the above code to check all boxes on the entire page. That won't work here though because I want to have multiple of these on the page at once each working independently. I know I could use a selector to select all the boxes if I ID'd the table but that would require some coding to name the table uniquely and then put that name in the script block.
Really what I would like is to modify the script above to check all checkboxes in the containing table of the "select all" box. The table containing the checkbox could be nested within others but I don't see any being nested within it, or if there are and the nested table also contains checxboxes I don't care if they also get selected.
Thanks for your help.
First, don't mix your HTML and your Javascript. Use event handler binding instead.
Second, use closest to get the nearest ancestor element of a particular type:
$(document).ready(function(){
$('#cbxSelectAll').click(function() {
$(this)
.closest('table') // get the parent table element
.find("input:checkbox:enabled") // find children that match the selector
.attr('checked', this.checked); // set their checked value
});
});
Change your inline attribute to this:
<input type="checkbox" id="cbxSelectAll" onclick="checkAll.call(this);" />
And your checkAll() to this:
function checkAll() {
$(this).closest('table').find("input:checkbox:enabled").attr('checked', this.checked);
}
Using .call(), it is called from the context of the element clicked.
Then the jQuery gets the closest()(docs) <table> and finds the inputs using the checkbox-selector(docs) and the enabled-selector(docs) .
Then when using the attr()(docs) method, you can use this.checked to set the checkboxes to the current state of the one checked.
You can find the table containing the select all using .closest
function checkAll(checked) {
var $table = $(this).closest('table');
$table.find("input[type='checkbox']:not([disabled='disabled'])")
.attr('checked', checked);
}
If there might be several nested tables it's often easiest to specify the one you want with a class, e.g. $(this).closest('table.tableOfCheckboxes'); where you add class tableOfCheckboxes to the table you want to find.

JavaScript\JQuery - identifying if radio button value changed by click

I have a page that displays a list of records. The user can select the record status using radio buttons, e.g.:
<div id="record_653">
<label><input type="radio" name="status_653" value="new" checked/>new</label>
<label><input type="radio" name="status_653" value="skipped" />skipped</label>
<label><input type="radio" name="status_653" value="downloaded" />downloaded</label>
</div>
I am using JQuery to send the changes made by the user back to the server, where I use them to update the database. This is a simplified version of what I do:
$("#record_653").click(
function(event) {
var url = ...,
params = ...;
post(url,params);
});
The problem is that this code will create requests even if the user clicks the same button that was previously checked. What I actually want is the "on change" event, except its behavior in Internet Explorer is not very useful (e.g. here).
So I figure I somehow have to identify if the click event changed the value.
Is the old value stored somewhere (in the DOM? in the event?) so I could compare against it?
If not, how should I store the old value?
The old value is not stored someplace where you can query it, no. You will need to store the value yourself. You could use a javascript variable, a hidden input element, or jQuery's data() function.
EDIT
The jQuery data function provides access to a key-value-pair data structure as a way to store arbitrary data for a given element. The api looks like:
// store original value for an element
$(selector).data('key', value);
// retrieve original value for an element
var value = $(selector).data('key');
A more developed thought:
$(document).ready(function() {
// store original values on document ready
$(selector).each(function() {
var value = $(this).val();
$(this).data('original-value', value);
})
// later on, you might attach a click handler to the the option
// and want to determine if the value has actually changed or not.
$(selector).click(function() {
var currentValue = $(this).val();
var originalValue = $(this).data('original-value');
if (currentValue != originalValue) {
// do stuff.
// you might want to update the original value so future changes
// can be detected:
$(this).data('original-value', currentValue);
}
});
});
$('#record_653 input:radio').each(function() {
$(this).data('isChecked', $(this).is(':checked'));
$(this).click(function() {
if ( $(this).is(':checked') !== $(this).data('isChecked') ) {
// do changed action
} else {
$(this).data('isChecked', !$(this).data('isChecked') );
}
})
});
This was complicated to do in my head but I think you want something like this.
As was suggested by meder and Ken Browning, I ended up using JQuery's data() to store the previous value and check against it on every click.
Storing an "is checked" boolean for each input radio is one solution. However you need to maintain this value. So in the click event handler, in addition to changing the "is checked" of the current input, you need to find the input that was previously checked and change its "is checked" data to false.
What I chose to do instead was to store, in the parent element, the currently checked object. So my code looks something like:
$(document).ready(
function() {
// find the checked input and store it as "currChecked" for the record
$("#record_653").data("currChecked",
$(this).find("input:radio:checked")[0]);
// add the click event
$("#record_653").click( function(event) {
if ($(event.target).is("input:radio") &&
event.target !== $(this).data("currChecked"))
{
$(this).data("currChecked", event.target);
handleChangeEvent(event);
}
});
});
}
);
Thanks
I had the same problem, but with FF I managed to deal with it using the onchange event rather than the onclick.
This is exactly what I was looking for to deal with IE7. Works like a charm!
Thanks for the detailed solution!

Categories

Resources