Cloning a div but it is not formatted like main div - javascript

Here is my main div
<div id="question-con">
<label for="ques-code">Question Setter:</label>
<input type="checkbox" id="ques-code" name="ques-code"/>
<div id="question-toggle" style="display:none;">
<div id="question-div" style="background-color:#A6A6A6;width: 350px;border: 1px solid greenyellow;margin-bottom: 10px;">
<label>Credit</label>
<input type="text" name="credit" class="credit" id="credit_0">
<label>No of Setter</label>
<input type="text" name="setter">
<label>Type</label>
<input type="text" name="type" id="type">
<label for="in-ex">Internal/External</label>
<input type="text" name="in-ex" id="">
<p class="remove" style="color:red;float: right;font-weight: bold;cursor: pointer;" >Remove</p>
</div>
</div>
<button id="btn-question" style="margin-top: 20px;margin-right: 5px; display: none;">Add</button>
</div>
In each button click, below function is triggered.I cloned the main div here, but the format of the cloned div is not like the main div.
$("#btn-question").click(function (e) {
e.preventDefault();
++question_count;
var question_clone = $('#question-div').clone();
question_clone.attr('id', question_count);
//question_clone.children().attr('id', "question_" + question_count);
question_clone.children(".credit").attr('id', "credit_" + question_count);
$('#question-toggle').append(question_clone);
$("#" + question_count + " input").val("");
});
Click here to see the image
What can i do?

You need to pass true as parameters to the clone to get its formatting too:
$('#question-div').clone(true,true);
See the .clone( [withDataAndEvents ] [, deepWithDataAndEvents ] ):
withDataAndEvents
A Boolean indicating whether event handlers and data should be copied along with the elements. The default value is false.
deepWithDataAndEvents
A Boolean indicating whether event handlers and data for all children of the cloned element should be copied. By default its value matches the first argument's value (which defaults to false).
This will only copy formatting of common classes or inline-styles that are applied to the elements but not to specific rules such as if you have #someid > a declared then copying the a element somewhere else such as #otherid a then it will not work. You need to explicitly define the css rules for them.

Related

Set .focus on second last input, not first or last

I have dynamically created inputs via a button, two get created at a time and I'd like the focus to be on the first of the two each time a set is added, so theoretically it'll always be the second last input
I currently use $('input:text:visible:first').focus(); but is there a way to do this but get the second last?
Input1.1
Input1.2
Input2.1
Input2.2
# user creates new input set via button
Input3.1 <---Focus on this one
Input3.2
One solution is to use eq(-2).focus(); (eq() documentation). From there you can read that the argument can be a negative number that represent the next:
indexFromEnd / Type: Integer / An integer indicating the position of the element, counting backwards from the last element in the set.
I have made a simple example to demostrate his use:
$("#myBtn").click(function()
{
$('<input value="new">').appendTo(".wrapper");
$('<input value="new">').appendTo(".wrapper");
$(".wrapper input").eq(-2).focus();
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<input type="text" value="input1">
<input type="text" value="input2">
<input type="text" value="input3">
<input type="text" value="input4">
</div>
<button id="myBtn">ADD</button>
You can use input:nth-last-child(n) where n is any number
function createInput() {
let str = `<div class ='ipCon'>
<input type='text'>
<input type='text'>
<input type='text'>
</div>`;
document.getElementById('con').innerHTML = str;
document.getElementsByClassName('ipCon')[0].querySelector('input:nth-last-child(2)').focus()
}
input:focus {
background-color: yellow;
}
<div id='con'>
</div>
<button type='button' onclick='createInput()'> Create Inputs</button>

DataTables export for complex HTML (python deform)

I'm using DataTables jquery for nice-looking tables and python's deform for generating my form elements easily from schema. DataTables exporting functionality doesn't play nice with the form elements generated.
Because of that, I need to use DataTables' export function to properly generate my exports. There's actually four types of cells I can think of in my application (arranged in order of increasing complexity), and the function would need to handle all of them.
Firstly, a standard <input>. Expected output here would just be with some brand
<input name="brand" value="with some brand" id="deformField1168" class=" form-control " type="text">
Secondly, a textarea (this is actually the only one DataTables handles correctly by default, as it strips away HTML to get 'only text contents'). Expected output here would be a short description
<textarea id="deformField1169" name="description" rows="2" class=" form-control ">a short description</textarea>
Third, a stack of divs which I use to place a trash/delete icon on one side of a cell, otherwise this is the same as the first case. If this is the only case which cannot be solved, I don't mind moving the icon to it's own cell, it's just uglier that way. Expected output here would be a_test_item
<div style="float: left; width: 85%; text-align: left">
<input name="item_number" value="a_test_item" id="deformField1167" class=" form-control " type="text">
</div>
<div style="float: right; width: 15%; text-align: right">
<form class="form" action="" method="post" accept-charset="utf-8" enctype="multipart/form-data">
<input name="id" value="1" type="hidden">
<button type="submit" class="btn btn-default" name="delete">
<span class="glyphicon glyphicon-trash">
</span></button>
</form>
</div>
Fourth and last, this set of hidden inputs + javascript which brings up a datepicker. Expected output here would be 2017-03-07
<input name="__start__" value="delivery_date:mapping" type="hidden">
<input name="date" value="2017-03-07" id="deformField1171" class=" form-control hasDatepicker" type="date">
<input name="__end__" value="delivery_date:mapping" type="hidden">
<script type="text/javascript">
deform.addCallback(
'deformField1171',
function deform_cb(oid) {
if (!Modernizr.inputtypes['date'] ||"date" != "date" || window.forceDateTimePolyfill){
$('#' + oid).pickadate({"format": "yyyy-mm-dd", "selectMonths": true, "selectYears": true, "formatSubmit": "yyyy-mm-dd"});
}
}
);
</script>
My current exportOption function looks like this:-
exportOptions: {
format: {
body: function ( data, row, column, node ) {
console.log(data)
return data
}
}
}
I've never used javascript to process strings before (only to getElementByID etc.), and it doesn't seem like string processing is the way to go anyway. Could I create a JS 'page' using these cells and use standard HTML access (all the getElement* functions)?
And as usual the very act of typing out the question provides me with insight which helps. Based on the accepted answer here about creating a DOM from a HTML string, as well as the observation that all visible inputs have the class form-control, here's the (embarrassingly simple) function I've written.
exportOptions: {
format: {
body: function ( data, row, column, node ) {
var div = document.createElement('div')
div.innerHTML = data
var value = div.getElementsByClassName('form-control')[0].value
return value
}
}
}

How do I detect a change in value of a RadioNodeList?

With a form my_form with a set of radio buttons with name=my_radio I can get a RadioNodeList object with my_form.elements.my_radio. I can get the value of the currently selected button with that object's value property, and if I assign a string to the value property the selected option changes as appropriate.
I expected to be able to do my_form.elements.my_radio.addEventListener('change', ..., to listen for the value changing (via the user selecting a different option) but it has no such method.
How can I detect the value changing?
Is the only way to set up event listeners on each individual radio button object?
var my_form = document.querySelector('#my_form');
var my_radio = my_form.elements.my_radio;
// This fails since RadioNodeList has no addEventListener function
/*
my_radio.addEventListener('change', function () {
console.log("Value changed; new value is " + my_radio.value);
});
*/
// The following works, but is there a better way, such as with a single event listener?
for (var i = 0, l = my_radio.length; i < l; i++) {
my_radio[i].addEventListener('change', function () {
console.log("Value changed; new value is " + my_radio.value);
});
}
<form id=my_form>
<div>
<label>
<input type=radio name=my_radio value=value_1>
Value 1
</label>
</div>
<div>
<label>
<input type=radio name=my_radio value=value_2>
Value 2
</label>
</div>
<div>
<label>
<input type=radio name=my_radio value=value_3>
Value 3
</label>
</div>
<div>
<label>
Some other field where I don't need to detect changes
<input name=some_other_field>
</label>
</div>
</form>
In your markup, wrap just the radio buttons in a fieldset. Then attach the event-listener to that instead of the form, so it won't fire for changes to other <input> fields.
Here is the modified code:
var my_form = document.querySelector('#my_form');
var my_radio = my_form.elements.my_radio;
var my_radio_group = document.querySelector('#my_radio_group');
// Attach the eventListener to the fieldset instead of the form
my_radio_group.addEventListener('change', function() {
// You actually don't even need the other global variables; this also works:
// let my_radio = this.form.elements.my_radio);
console.log("Value changed; new value is " + my_radio.value);
});
/* If you don't want any border around the radio group */
#my_radio_group {
border: none;
}
<form id="my_form">
<fieldset id="my_radio_group">
<div>
<label>
<input type="radio" name="my_radio" value="value_1">
Value 1
</label>
</div>
<div>
<label>
<input type="radio" name="my_radio" value="value_2">
Value 2
</label>
</div>
<div>
<label>
<input type="radio" name="my_radio" value="value_3">
Value 3
</label>
</div>
</fieldset>
<div>
<label>
Some other field where I don't need to detect changes
<input name="some_other_field">
</label>
</div>
</form>
Why OP's first approach fails
A RadioNodeList, being a kind of NodeList, is a collection of Nodes (radio elements in this case). As such, it is much like a JS Array (you can do my_radio[i]). In JS, Events can be received only by objects that inherit the EventTarget interface, like Nodes and HTML Elements, and not by collections like arrays and NodeLists.
To attach a single event handler for multiple elements, you have to attach it to a close parent and use Event Delegation. Which is what I did in my solution, using the <fieldset> element. Any wrapper element e.g. <div> would have sufficed; only that the <fieldset> is semantically more accurate here.
you can try this:
my_form.addEventListener('change', function () {
console.log("Value changed; new value is " + my_radio.value);
});
document.formName.radioButtons[thisOne].click()

Javascript Add Row to HTML Table & Increment ID

This is my first post on this site so hopefully you will go easy on me. I'm trying to create an HTML / PHP form and use a small piece of Javascript to add additional rows to a table when a button is clicked and increment the ID for the two fields.
The button works in adding the rows however it doesn't seem to increment the ID, just use the same ID as the previous row. Hopefully someone could help?
$(window).load(function(){
var table = $('#productanddates')[0];
var newIDSuffix = 2;
$(table).delegate('#button2', 'click', function () {
var thisRow = $(this).closest('tr')[0];
var cloned = $(thisRow).clone();
cloned.find('input, select').each(function () {
var id = $(this).attr('id');
id = id.substring(0, id.length - 1) + newIDSuffix;
$(this).attr('id', id);
});
cloned.insertAfter(thisRow).find('input:date').val('');
newIDSuffix++;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="blue-bar ta-l">
<div class="container">
<h1>Submit Your Insurance Renewal Date(s)</h1>
</div>
</div>
<div class="grey-bar">
<div class="container">
<div class="rounded-box">
<div>
<label for="name">Name</label>
<input type="text" id="name" name="name" autocomplete="off" required />
</div>
<div>
<label for="name">Renewal Dates</label>
</div>
<table width="100%" border="0" cellspacing="0" cellpadding="5" id="productanddates" class="border">
<tr>
<td>
<select name="insurance_type1" id="insurance_type1">
<option></option>
<option>Car</option>
<option>Home</option>
<option>Van</option>
<option>Business</option>
<option>GAP</option>
<option>Travel</option>
</select>
</td>
<td>
<input type="date" name="renewal_date1" id="renewal_date1" />
</td>
<td>
<input type="button" name="button2" id="button2" value="+" />
</td>
</tr>
</table>
<div>
<label for="telephone_number">Contact Number</label>
<input type="tel" id="telephone_number" name="telephone_number" pattern="\d{11}" autocomplete="off" required />
</div>
<div>
<label for="email">Email Address</label>
<input type="email" id="email" name="email" autocomplete="off" required />
</div>
<div>
<input name="submit" type="submit" value="Submit" class="btn">
</div>
</div>
cloned.insertAfter(thisRow).find('input:date').val('');
This line isn't correct. It will throw an invalid selector error.
You need to change it to:
cloned.insertAfter(thisRow).find('input[type="date"]').val('');
jQuery actually does support the :INPUT-TYPE format in selectors, but not the new HTML5 input types (yet): so using input[type="date"] here is the correct way for now to select an element with an HTML5 type. Please notice the quotes around the value. If you want to select an attribute with a certain value.
A selector overview of css selectors here: W3schools.
Because this line is throwing an error your newIDSuffix never gets updated, because the script halts at the line before that because of the script error.
#Charlietfl raises a valid point about learning more about classes and DOM traversal. However that will not fix this code. Or explain why your code isn't working. Nevertheless it's a good tip.
I've gone ahead an taken a stab at a cleaner version of what I think that you are trying to accomplish. I'll walk through the major updates:
Updated the button id and name from "button2" to "button1" - I assumed that you would want to keep the indices in sync across the inputs in each row.
Changing $(window).load(function() { to $("document").ready(function() { - While either will work, the former will wait until all images have finished loading, while the latter while fire once the DOM has completed building. Unless you REALLY want the images to load first, I'd recommend $("document").ready(), for faster triggering of the code.
Removing the [0] references - the primary reason to use [0] after a jQuery selector collection is to reference the DOM version of the selected jQuery element, in order to us a "vanilla" JavaScript method on it. In all cases, you were re-rwapping the variables in $(...), which just converted the DOM element back into a jQuery object, so that extra step was not needed.
Changed the .delegate() method to .on() - as Howard Renollet noted, that is the correct method to use for modern versions of jQuery. Note that the "event" and "target" parameters have swapped places in on, from where they were in delegate.
Changed the event target from #button2 to :button - this will make sure that all of the buttons in the new rows will also allow you to add additional rows, not just the first one.
Switched the clone target from the clicked row to the last row in the table - this will help keep your row numbering consistant and in ascending order. The cloned row will always be the last one, regardless of which one was clicked, and the new row will always be placed at the end, after it.
Changed the indexing to use the last row's index as the base for the new row and use a regular expression to determine it - with the table being ordered now, you can always count on the last row to have the highest index. By using the regular expression /^(.+)(\d+)$/i, you can split up the index value into "everything before the index" and "the index (i.e., on or more numbers, at the end of the value)". Then, you simply increment the index by 1 and reattach it, for the new value. Using the regex approach also allows you to easily adapt, it there ever get to be more than 9 rows (i.e., double-digit indices).
Updated both the id and name attributes for each input - I assumed that you would want the id and name attributes to be the same for each individual element, based on the initial row, and, you were only updating the id in your code, which would have caused problems when sending the data.
Changed $("input:date") to $("input[type='date']) - as Mouser pointed out, this was really the core reason why your code was failing, initially. All of the other changes will help you avoid additional issues in the future or were simply "code quality"-related changes.
So . . . those were the major updates. :) Let me know if I misunderstood what you were trying to do or if you have any questions.
$("document").ready(function() {
$('#productanddates').on('click', ':button', function () {
var lastRow = $(this).closest('table').find("tr:last-child");
var cloned = lastRow.clone();
cloned.find('input, select').each(function () {
var id = $(this).attr('id');
var regIdMatch = /^(.+)(\d+)$/;
var aIdParts = id.match(regIdMatch);
var newId = aIdParts[1] + (parseInt(aIdParts[2], 10) + 1);
$(this).attr('id', newId);
$(this).attr('name', newId);
});
cloned.find("input[type='date']").val('');
cloned.insertAfter(lastRow);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="blue-bar ta-l">
<div class="container">
<h1>Submit Your Insurance Renewal Date(s)</h1>
</div>
</div>
<div class="grey-bar">
<div class="container">
<div class="rounded-box">
<div>
<label for="name">Name</label>
<input type="text" id="name" name="name" autocomplete="off" required />
</div>
<div>
<label for="name">Renewal Dates</label>
</div>
<table width="100%" border="0" cellspacing="0" cellpadding="5" id="productanddates" class="border">
<tr>
<td>
<select name="insurance_type1" id="insurance_type1">
<option></option>
<option>Car</option>
<option>Home</option>
<option>Van</option>
<option>Business</option>
<option>GAP</option>
<option>Travel</option>
</select>
</td>
<td>
<input type="date" name="renewal_date1" id="renewal_date1" />
</td>
<td>
<input type="button" name="button1" id="button1" value="+" />
</td>
</tr>
</table>
<div>
<label for="telephone_number">Contact Number</label>
<input type="tel" id="telephone_number" name="telephone_number" pattern="\d{11}" autocomplete="off" required />
</div>
<div>
<label for="email">Email Address</label>
<input type="email" id="email" name="email" autocomplete="off" required />
</div>
<div>
<input name="submit" type="submit" value="Submit" class="btn">
</div>
</div>
cloned.insertAfter(thisRow).find('input[type="date"]').val('');

How get specific elememt that have data-bind attribute and call now (using now-active now)?

<div class="container">
<div class="well" data-id="myApp">
// Data-Bind is Here
<input type="text" value="" class="form-control input-sm"
data-bind="value:name,valueUpdate:'afterkeyup'" />
// Data-Bind is Here
<p class="info" data-bind="text:name"></p>
<button class="btn btn-success" data-bind="click:showName">Show</button>
</div>
</div>
I want to get html element that have "data-bind" attribute for example I want to Get something like this :
<input type="text" value="" class="form-control input-sm"
data-bind="value:name,valueUpdate:'afterkeyup'" />
if I change above code like this :
<div class="container">
// Data-Bind is HERE Now
<div class="well" data-id="myApp" data-bind="value:name,valueUpdate:'afterkeyup'">
// Data-Bind is HERE Now
<input type="text" value="" class="form-control input-sm" />
<p class="info" data-bind="text:name"></p>
<button class="btn btn-success" data-bind="click:showName">Show</button>
</div>
</div>
now I want to get element like this :
<div class="well" data-id="myApp" data-bind="value:name,valueUpdate:'afterkeyup'">
How can I have function for get active element that set data-bind for it , when data-bind read I can get correspondingly element of it
I need general way not for specific event or ...
If you are using JQuery then you can use "has attribute" selector. For example:
$("[data-bind]")
You can get all elements with a data-bind attribute with the jquery attribute selector.
$("*[data-bind]")
Next you can refine the selector in various ways, e.g. to consider only certain tags or choosing only a slice of the result,or by employing jquery filters:
$("div[data-bind], input[data-bind], p.data-carrier[data-bind]"); // consider only div, input, or p elements, the latter only when having class data-carrier
$("*[data-bind]:first"); // use the first match only
$("*[data-bind]")[1]; // use the second match only
$("*[data-bind]").filter(":even"); // use only matches with an even index in the list of matches
$("*[data-bind]").each ( function ( idx, element ) { /* your code */ } ); // the most general approach: iterate through the results and decide upon each element what to do next
Are you looking for this in jquery:
var elem = $('.container').find('[data-bind]');
Use $("*[data-bind]")[0].outerHTML
It will you the outerHTML of the element.
Working Fiddle

Categories

Resources