jQuery buttonset refresh not working as I'd expected - javascript

OK - I have a function which I call to dynamically add a radio button as per this question. This is the full function:
// function used to create a new radio button
function createNewRadioButton(
selector,
newRadioBtnId,
newRadioBtnName,
newRadioBtnText){
// create a new radio button using supplied parameters
var newRadioBtn = $('<input />').attr({
type: "radio", id: newRadioBtnId, name: newRadioBtnName
});
// create a new label and append the new radio button
var newLabel = $('<label />').append(newRadioBtn).append(newRadioBtnText);
// add the new radio button and refresh the buttonset
$(selector).append(newLabel).append('<br />').buttonset("refresh");
}
So if I were to call the above function with the following code I would expect another radio button to be added underneath the radio buttons already contained in the div '#radioX' (assuming there is a div with id radioX containing radio buttons):
// create a new radio button using the info returned from server
createNewRadioButton(
'#radioX', // Radio button div id
product.Id, // Id
product.Id, // Name
product.Name // Label Text
);
Given that on document ready, I tell jQuery to create me a buttonset out of the radio buttons contained in #radioX like so: $( "#radioX" ).buttonset();, why doesn't the call to $("#radioX").buttonset("refresh") in the function createNewRadioButton refresh the list of radio buttons?
The result that I see after a call to createNewRadioButton is made is a new label with the desired text is added but no new radio button. So instead of a nice new jQuery radio button sitting underneath whatever was already there, I see just a new label with text equivelant to product.Name (in the given example).
I've also noticed this warning output in firebug after a call is made to createNewRadioButton - could this have anything to do with it?
reference to undefined property $(this).button("widget")[0]
EDIT
Here's a screenshot of what I expected to happen:
Here's a screenshot of what happens

My mistake. Actually the refresh method is taking good care of added radio elements at runtime.
The markup you are generating in createNewRadioButton() is I think not compatible with what the plugin expects.
You create:
<label><input /></label>
And the plugin expects:
<input /><label for=''></label>
Here is the modified function:
function createNewRadioButton(
selector,
newRadioBtnId,
newRadioBtnName,
newRadioBtnText){
// create a new radio button using supplied parameters
var newRadioBtn = $('<input />').attr({
type: "radio", id: newRadioBtnId, name: newRadioBtnName
});
// create a new label and append the new radio button
var newLabel = $('<label />').attr('for', newRadioBtnId).text(newRadioBtnText);
// add the input then the label (and forget about the <br/>
$(selector).append(newRadioBtn).append(newLabel).buttonset("refresh");
}
Don't forget to initiliaze the plugin, even if the container '#radioX' is empty:
$('#radioX').buttonset();
I have made a jsfiddle for you to see a working example.

It must be a bug. Change jQuery version from 1.7.1 to 1.8.3, choose UI in jsfiddle1 and you will see that it is now working as expected.
code here

Related

DOJO error Id is already registered

Hi I'm new bee to dojo and stuck into a simple problem. I'm getting an error
Tried to register widget with id==listGrid but that id is already registered. Let me share a piiece of my code with you
I have Three radio button and onclick on any of the radio button will result in grid. I'm using same div for all three radio button. First time the grid will come for first radio button but second time I get an above error. I'm calling this function on click of radio button
_showList:function()
{
var item = this.gc.getSelectedItem()
var id=item.id;
var cont = 'zone';
var action='getCityListById';
var controller='network';
this.cityGc = new GridViewControl({columns:
[
{action:action, controllerName:controller,parameters: {id:item.id, cont: cont}},
{name:"City Name", field:"name", width: "200px", editable: false}
], diff:220
},this.zoneListGrid);
}
zoneListGrid is a dojo attach point which is same for all three radio buttons. please suggest something through which I can work out. Thanks in advance
Since every click on a radio button will trigger this piece of code, dojo will try to create another grid component on the second click. Because there is already a widget present on that attach point, the error is thrown.
Either you re-use the grid that is already present (do a === null check on this.cityGc) or you destroy the existing grid first (this.cityGc.destroy()).

jQuery UI checkboxes misbehaving when cloned

I'm trying to create a table of inputs that automatically adds a new row when you enter text in one of the inputs on the bottom line. For the most part, it works fine. However, I'm having some trouble with jQuery UI checkbox buttons.
The checkbox buttons are supposed to change their icon when clicked. This works fine for the original buttons, but the cloned button that appears when you add a new row doesn't work properly.
You can see it in jsfiddle here. To replicate the issue, put some text in the third input down. You'll see that a fourth row appears. If you press the fourth checkbox, you'll see the third checkbox is the one whose icon changes. The wrong button also gets ui-state-focus but doesn't actually get focus, which really baffles me, though the correct button does get ui-state-active and seems, as far as I can tell, to evaluate as having been checked properly.
To be clear, the two checkboxes do not have the same ID, and their labels are for the right checkbox - the createNewRow() function takes care of that. If you comment out the line that turns the checkboxes into jQuery UI checkboxes, you'll see everything works fine. If you console.log the value of $(this).attr('id') in the buttonSwitchCheck function, you'll see that it has the right ID there too - if you click the fourth button, it'll tell you that the id of $(this) is "test4", but it's "test3" (the third button) that gets the icon change.
I'm going mad staring at this and I'd appreciate any help people can give. Here's the code:
// Turns on and off an icon as the checkbox changes from checked to unchecked.
function buttonSwitchCheck() {
if ($(this).prop('checked') === true) {
$(this).button("option", "icons", {
primary: "ui-icon-circle-check"
});
} else {
$(this).button("option", "icons", {
primary: "ui-icon-circle-close"
});
}
}
// Add a new row at the bottom once the user starts filling out the bottom blank row.
function createNewRow() {
// Identify the row and clone it, including the bound events.
var row = $(this).closest("tr");
var table = row.closest("table");
var newRow = row.clone(true);
// Set all values (except for buttons) to blank for the new row.
newRow.find('.ssheet').not('.button').val('');
// Find elements that require an ID (mostly elements with labels like checkboxes) and increment the ID.
newRow.find('.ssheetRowId').each(function () {
var idArr = $(this).attr('id').match(/^(.*?)([0-9]*)$/);
var idNum = idArr[2] - 0 + 1;
var newId = idArr[1] + idNum;
$(this).attr('id', newId);
$(this).siblings('label.ssheetGetRowId').attr('for', newId);
});
// Add the row to the table.
newRow.appendTo(table);
// Remove the old row's ability to create a new row.
row.removeClass('ssheetNewRow');
row.find(".ssheet").unbind('change', createNewRow);
}
$(document).ready(function () {
// Activate jQuery UI checkboxes.
$(".checkButton").button().bind('change', buttonSwitchCheck).each(buttonSwitchCheck);
// When text is entered on the bottom row, add a new row.
$(".ssheetNewRow").find(".ssheet").not('.checkButton').bind('change', createNewRow);
});
EDIT: I was able to find a solution, which I'll share with the ages. Thanks to "Funky Dude" below, who inspired me to start thinking along the right track.
The trick is to destroy the jQuery UI button in the original row before the clone, then reinitializing it immediately afterwards for both the original row and the copy. You don't need to unbind and rebind the change event - it's just the jQuery UI buttons which have trouble. In the createNewRow function:
row.find('.checkButton').button('destroy');
var newRow = row.clone(true);
row.find('.checkButton').add(newRow.find('.checkButton')).button().each(buttonSwitchCheck);
Try using the newer method .on, that allows for delegation, which should help with the dynamic changes to your DOM:
$(".checkButton").button().each(buttonSwitchCheck);
$("table").on("change", ".checkButton", buttonSwitchCheck);
I'm not sure, but it might help with not having to worry about binding events to specific elements.
Also, you could use it for the textbox change event:
$("table").on("change", ".ssheetNewRow .ssheet:not(.checkButton)", createNewRow);
Here's your fiddle with my changes: http://jsfiddle.net/Cugb6/3/
It doesn't function any different, but to me, it's a little cleaner. I thought it would've fixed your problem, but obviously hasn't, due to problems with the button widget.
And funny enough, it doesn't seem they "support" cloning: http://bugs.jqueryui.com/ticket/7959
i think you are using deep clone, which also clones the event handler. in your create new row function, try unbinding the change event then rebind on the clone.

Why radio button click event behaves differently

Example on JS FIddle.
The question is:
If the first click is on the radio button, it behaves normally; But if the first click is on span text (i.e. aaaa), it can not get the checked radio.
Please tell me why and how I can make it the same.
This code, which happens when the radio button is clicked:
var obj = $(e.target||e.srcElement).parent();
score = obj.find('input:checked').val();
Puts the parent in the obj variable, which is the containing DIV. This contains both of the radio buttons. It then finds the FIRST checked input element in that DIV, which is always the one with the 'first' value after it is checked.
You should just get the value of the item which was clicked:
score = $(e.target||e.srcElement).val();
This can be rewritten as
score = $(this).val();
Here's a working example: http://jsfiddle.net/RPSwD/10/
See new fiddle.
The problem is this line:
score = obj.find('input:checked').val();
Change it to:
score = $(this).val();
The reason for this is that you're looking for the selected item in the div but on the first click, the item has yet to become selected. Given that the event is targeted at the radio button, you can assume that radio is the selected one.
Note also that you don't need to use e.target||e.srcElement. jQuery takes care of this for you. Use $(this) instead.
Additionally, you need to set a name on the radio buttons to stop both from becoming selected. Alternatively, if having both selected is desired behaviour, use check boxes instead.
You don't need to use any of the event properties:
var score = $(this).val(); // in your '.x' click handler
$('.y').click(function(e) {
$(this).prev('.x').click();
});
just wrap your radio button inside label tag like this
<label for="radio1">
<input type=radio class="x" id="radio1" value="First"/>
<span class="y">aaaa</span>
</label>
No need for extra jquery or javascript
check the demo here

Adding an item to an editable menulist when it is typed in by the user

I am creating a menulist popup list dynamically. I the editable and open attributes to true. What I would like to be able to do is to be able to add a new menulist item when the user types in an item that is not already present. Is this possible? If so, how?
I am creating the list like so:
var ml = document.createElement("menulist");
ml.setAttribute("editable","true");
ml.setAttribute("open","true");
ml.setAttribute("oncommand","alert(this.value)");
var mp = document.createElement("menupopup");
var mi = document.createElement("menuitem");
mi.setAttribute("label","item1");
mi.setAttribute("value","1");
mp.appendChild(mi);
//add as many items as i feel
ml.appendChild(mp);
When the value is changed, the alert function is fired when the item is changed but when I type in anything, it is not fired. Basically, I want to eventually pass the value to a funcntion I call from here to add the item to the list.
First of all, you should seriously consider using addEventListener instead of changing attributes like oncommand:
ml.addEventListener("command", function(event) {
alert(this.value);
}, false);
If you want to be notified about changes in the text field then you should add an event listener to the text field:
ml.appendChild(mp);
ml.inputField.addEventListener("input", function(event)
{
alert("Text field value changed");
}, false);
Note that this has to be done after the element is added to the document, before that the inputField property will not be defined (corresponding XBL binding didn't apply yet).
For reference: menulist.inputField, input event

Dynamically added a field in different forms using Jquery

I'd like to have a field that doesn't show at first, but if the user decided to input to it, then it will appear in the form.
I can use Jquery and do something like
$('input[example]')
.bind('click', function() {
$('#clickfield')
.append('<input id="new_field" name="MODEL[new_field]" size="30" type="text">');
However, I'd like to add this field in several different forms for different models.
Since the model name is in the field, how would I write the Jquery script to be modular so I can use the same script for all my forms?
One solution is to make a function with the names you want as input parameters:
addInput(form, id, modelName) {
$(form).append(
'<input id="'+id+'" name="'+modelName+'['+id+']" size="30" type="text">'
);
}
Where form would be the selector of the field ('#clickfield' in the example case), id would be the id of the new input field, and modelName would be the name of the model you mentioned.
Other solution, assuming 'input[example]' selects some button or clickable area that triggers the event of showing the field; and '#clickfield' is some div or span or some area where you will show your field, is to load these hidden fields from the server, styled as display:none, with a mnemonic class, so you could do something like define a function:
showField(clickable, class) {
$(clickable).click(
function(){
$(class).show();
}
);
}
and then:
$(document).ready(
showField('input[example1]', '.class1');
showField('input[example2]', '.class2');
showField('input[example3]', '.class3');
// .
// .
// .
// One line for every clickable area that triggers
// the event of showing a field, and the class of the
// field to show
);
this way you could add some user friendly features like fading the field in with the fadeIn() Jquery function (instead of show()), or any other animation on appearing.
Hope you could use it! good luck!

Categories

Resources