So I have an accordion menu that I created with Jquery:
<script>
$(document).ready(function() {
/*Accordian Script for the Request New Appraisal Panel*/
$('.accordian_item').hide();
$('.accordian_item').first().slideDown();
$('.accordian_trigger').click(function(event) {
event.preventDefault();
$(this).parent().find('.accordian_item').slideToggle();
});
});
</script>
Now, I want to be able to dynamically append extra accordion items to the accordion box, which I have done like this:
<script>
$('#add_contact_btn').click(function(event) {
event.preventDefault();
var large = '<div class="accordian_container"><h4>Co-Borrower Information</h4><hr/><div class="accordian_item"><label> First Name</label><br/><input type="text"/><br/><label>Middle Name</label><br/><input type="text"/><br/><label>Last Name</label><br/><input type="text" /><br/><label>Home Number</label><br/><input type="text"/><br><label>Work Number</label><br/><input type="text"/><br><label>Cell Number</label><br/><input type="text"/><br></div></div>';
$('#accordion_container_box').append(large);
});
</script>
This works perfect, except the dynamically generated items don't collaps when you click on the collapse button. The existing accordion items still work. For some reason it seems like Jquery wont trigger for dynamically created links. Any ideas how I can correct this?
BTW, here is the basic HTML structure:
<div id="accordion_container_box">
<div class="accordian_container">
<h4>Borrower's Information</h4>
<hr/>
<div class="accordian_item">
<label> First Name</label><br/>
<input type="text"/><br/>
<label>Middle Name</label><br/>
<input type="text"/><br/>
<label>Last Name</label><br/>
<input type="text" /><br/>
<label>Home Number</label><br/>
<input type="text"/><br>
<label>Work Number</label><br/>
<input type="text"/><br>
<label>Cell Number</label><br/>
<input type="text"/><br>
</div>
</div>
<div class="accordian_container">
<h4>Co-Borrower's Information</h4>
<hr/>
<div class="accordian_item">
<label> First Name</label><br/>
<input type="text"/><br/>
<label>Middle Name</label><br/>
<input type="text"/><br/>
<label>Last Name</label><br/>
<input type="text" /><br/>
<label>Home Number</label><br/>
<input type="text"/><br>
<label>Work Number</label><br/>
<input type="text"/><br>
<label>Cell Number</label><br/>
<input type="text"/><br>
</div>
</div>
</div>
+ Additional Contact
You have to use .live('click'... on dynamically created content.
By default binding events to elements will only affect nodes that exist at the time that the bind runs. By using event delegation you can make use of the built in way that events bubble. jQuery < 1.7 did this with the delegate and live methods, jQuery 1.7 added the on method to consolidate all the event handlers in a single API.
For example you could use the following to handle all clicks on nodes with a class of accordian_trigger regardless of when they were created.
$(document).on('click', '.accordian_trigger', function() {
//whatever you need to do
});
What this will do is attach an onclick event handler to the document itself. When any click occurs in the DOM it will bubble up from the node that the event occurred on to its parent and its parent until it reaches the document. jQuery will then check whether the event occurred on a node that matches the selector passed in as the second parameter of on, in this case it will check whether the node has a class of accordian_trigger. If it does it will run the function passed in as the third parameter.
For efficiency's sake you'll likely want to replace document with a parent node that you know will contain all accordian_trigger nodes. Otherwise all clicks bubble all the way up to the document and check whether the node that was clicked on has the accordian_trigger class, which is potentially expensive, especially if you have a large DOM.
Related
I have a div element with several children. I need to disable tabbing in all of them. I have been using tabindex but is there any way to disable them all by setting a value in the parent.
I don't want to touch the child divs.
I have no idea what your code looks like but you could grab the parent element and add the tabindex attribute to its children that are inputs using attr() as follows:
$(".wrapper").children("input").attr("tabindex", "-1");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="wrapper">
<input type="text" name="1">
<input type="text" name="2">
<input type="text" name="3">
<input type="text" name="4">
</div>
NOTE: when you say "I don't want to touch the child divs" I'm assuming you mean you don't want to manually go through every instance and add tabindex as it would be time consuming?
More info: http://api.jquery.com/attr/
Background:
I've got a set of input elements form invoice item details. I want a user to be able to add rows of input fields for each additional item.
Input Markup
<div class="input-row">
<div class="form-group">
<label for="item_name">Item:</label>
<div>
<input type="text" name="item_name[]" placeholder="Name">
</div>
<div>
<input type="text" name="item_qty[]" placeholder="Quantity">
</div>
<div>
<input type="text" name="item_price[]" placeholder="Price">
</div>
<div>
<input type="text" name="item_total[]" placeholder="Total">
</div>
</div>
</div>
And a button to add an additional item
Button Markup
<div class="col-lg-2">
<a id="add-item" href="#">Add Item</a>
</div>
Button Javascript
$('#add-item').click(function(){
$('.input-row:first').clone().appendTo('.input-row:last');
})
Problem:
When I click the add button the first time, it works fine and adds a row of input fields after the first one, however if I click it again it adds 2 rows and then click it again it adds 4 rows. I realise this may be because the cloned .input-row div is being included in the clone, but I'm trying to only copy the first div element using the :first selector. Any ideas how to resolve this?
Question
How can I ensure only one div is appended to the markup.
The best solution I've seen so far is the following jQuery Library:
http://www.andresvidal.com/labs/relcopy.html
Solution
The jQuery appendTo method adds the element into the existing div, meaning when you clone it the second time the div contains two rows of input fields and then the third time will contain 4 rows of input fields.
To overcome this use the insertAfter() method
Button Javascript
$('#add-item').click(function(){
$('.input-row:first').clone().insertAfter('.input-row:last');
})
I'm need to create the following form structure:
<div class="lg-pnl" id="logP">
<form id="form">
<div class="fields" id="fields1">
<div class="txt">
<label for="user" class="ent-u"></label>
<input id="user" type="text" name="user" class="validate[required] text-input" placeholder="user"/>
</div>
<div class="txt">
<label for="pw" class="ent-l"></label>
<input id="pw" type="password" name="password" class="validate[required] pw-input" placeholder="pwd"/>
</div>
<div class="btn">
<input type="submit" value="GO" id="subGO"/>
</div>
</div>
</form>
</div>
And for archieve this I'm using the very very very ugly code bellow:
$("#logP").append('<form id="form">');
$("#logP form").append('<div class="fields"></div>');
$("#logP form .fields").append('<div class="txt"></div>');
$("#logP form .fields .txt").append('<label for="user" class="ent-u"/>');
$("#logP form .fields .txt").append('<input id="user" type="text" name="user" class="validate[required] text-input" placeholder="user"/>');
$("#logP form .fields .txt").append('<label for="pw" class="ent-l"/>');
$("#logP form .fields .txt").append('<input id="pw" type="password" name="password" class="validate[required] pw-input" placeholder="pwd"/>');
$("#logP form .fields").append('<div class="btn"></div>');
$("#logP form .fields .buttons").append('<input type="submit" value="GO" id="subGO"/>');
I really need to preserve this DOM tree because the CSS style works on it.
But the styles isn't work properly neither the js events bind with form and input elements,
I have lost all behaviour for these functions, for example the piece of code bellow doesn't work anymore.
div.lg-pnl div.txt input[type="text"],
div.lg-pnl div.txt input[type="password"]
$('.subGO').click(function() {
$('#form').validation('validate');
});
$(function() {
$('input').keyup(function() {
this.value = this.value.toUpperCase();
});
});
So I'm trying to find out some better way to create this entire form and its own elements
dynamically without losing the styles and the id/class references in the javascript already
defined.
I'll really appreciate your suggestions
Thanks.
Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the event binding call.
You need to use Event Delegation. You have to use .on() using delegated-events approach.
Use
$(document).on('click', '.subGO',function() {
$('#form').validation('validate');
});
Replace document with nearest static container. i.e. "#logP"
Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time.
I am attempting to put together a fairly complex form using dojo and dijit widgets. The form has multiple 'sections' which allow the user to attach an existing object (via select tag) or create an entirely new object inline in the form.
My inputs are rendered conditionally based radio buttons and manipulated via javascript. What I am having problems doing, is conditionally making dijit widgets required based on whether the inputs are rendered or not (which itself depends on which radio button is selected.
My html (actually jsp)
<div>
<input id="useExisting" type="radio" name="radio" checked value="useExisting" onclick="renderExistingInput()" /> <label for="useExisting">Use Existing</label>
<input id="new" type="radio" name="radio" value="new" onclick="renderNewInputs()"/> <label for="new">Create New</label>
</div>
<br>
<div id="newInputs">
<div class="row">
<label class="label" for="newName">Name </label>
<span class="formInput"><input type="text" id="newName" name="newName" required="true" dojoType="dijit.form.ValidationTextBox"/></span>
</div>
<!-- More inputs with required="true"-->
<br>
</div>
<div id="existingInput>
<div class="row">
<label class="label" for="existingSelect">Existing Object </label>
<span class="formInput">
<select name="existingSelect" id="existingSelect" dojoType="dijit.form.Select">
<!--JSTL tags for compiling list of options -->
</select>
</span>
</div>
</div>
Accompanying javascript functions:
function renderExistingInput() {
dojo.fx.wipeOut(getWipeArguments('newInputs')).play();
dojo.fx.wipeIn(getWipeArguments('existingInput')).play();
}
function renderNewInputs() {
dojo.fx.wipeOut(getWipeArguments('existingInput')).play();
dojo.fx.wipeIn(getWipeArguments('newInputs')).play();
}
function getWipeArguments(id) {
var wipeArgs = {
node : id
};
return wipeArgs;
}
The basic 'flow' of user interactions is User clicks a radio button, the correct div renders as a result of that. What I want then are inputs that are not rendered to not be considered required. I'm not entirely sure how to do this. Is it possible to manipulate that particular attribute directly via dojo? Or is there a better way to do this entirely?
Seem's like My answer was staring me right in the face. I simply needed to pull together the different parts I had come across. My final function for changed the 'required' attribute looks like:
function setWidgetRequiredAttributes(baseDomNodeId, requiredValue){
foundWidgets = dijit.findWidgets(dojo.byId(baseDomNodeId));
console.log(foundWidgets);
foundWidgets.forEach(function(widget){
widget.required=requiredValue;
});
}
I have a table that contains in each row an input and a "save" image.
<td>
<div id="acp_1" style="margin-left:100px;display: inline">
<input size="10" type="text" value="11:00" name="acpr_1" id="acpr_1" />
<span class="modify-listener" id="ml_1">
<img id="save_1" src="/images/skin/database_save.png" alt="modify"/>
</span>
</div>
</td>
<td>
<div id="acp_2" style="margin-left:100px;display: inline">
<input size="10" type="text" value="11:00" name="acpr_2" id="acpr_2" />
<span class="modify-listener" id="ml_2">
<img id="save_2" src="/images/skin/database_save.png" alt="modify"/>
</span>
</div>
</td>
The __number pattern is used to differentiate one row's element from another.
I need to capture the click event on the image, so I can save the input's value in the backend. Something like:
Event.observe('modify-listener', 'click', function(){
....
How can I detect which row's image was clicked so I can call an Ajax function with the right values?
Thanks.
The technique you are searching for is called event delegation. It basically means that you handle an event on a higher lever of the tree so as to have only one event handler instead of many.
What you need to do is to find the container element that includes all the images (like the table that they are in), and use it as the base for event handling, and give its id to Event.observe. Then you can find out which img was clicked by using the Event.findElement method.
Event.observe('target', 'click', function(event) {
alert( Event.findElement(event, 'IMG').id ); // e.g.: save_1
});
assuming that your table has an id #target
You can find a working demo here.