How do I order by node depth and then by tabindex? - javascript

I've got an HTML form that's built dynamically using templates at runtime - dictated by user action.
I need to set the tab index across the form based on the tabindexing specified within each of the pieces of the form.
Given this, is there a way in jQuery to order items within a set? For instance something that follows this pseudo structure would be awesome, but I can't figure out how to achieve it:
<div name="firstTemplate" templateIndex="0">
<input type="text" name="field0" tabIndex="1" />
<input type="text" name="field1" tabIndex="2" />
<input type="text" name="field2" tabIndex="3" />
</div>
<div name="firstTemplateRpt" templateIndex="1">
<input type="text" name="field0" tabIndex="1" />
<input type="text" name="field1" tabIndex="2" />
<input type="text" name="field2" tabIndex="3" />
</div>
<div name="secondTemplate" templateIndex="2">
<input type="text" name="field0" tabIndex="1" />
<input type="text" name="field1" tabIndex="2" />
<input type="text" name="field2" tabIndex="3" />
</div>
I could then use some variation of the following concept:
$("input, textarea, select, input:checkbox, input:radio").orderBy("templateIndex, tabIndex");
Where templateIndex would be the index of the template within the form and the tabindex would be the tabindex of the control within the template. A template could be added to the form multiple times at runtime, which is causing havoc on manually specified tabindexes.
When another template is added to the form, it would be assigned the templateIndex="3" with its manually set tabIndexes starting again at 1.

Collect the divs with a templateIndex attribute into an array, then sort them like:
divArray.sort(function(a, b) {
return a.getAttribute('templateIndex') - b.getAttribute('templateIndex');
});
Then iterate over those and sort the inputs inside the array using a very similar function:
inpArray.sort(function(a, b) {
return a.tabIndex - b.tabIndex;
});
Then move the elements in the required order in the document using something like node.parentNode.insertBefore(node, firstChild).

Related

How to get text-box counts in javascript

H i have a button "Add text" when on-click it creates the text-boxes,now How can i get the count of text-boxes in JavaScript i create text-boxes like
<input type="text" name="my_textbox[1]" id="my_textbox1" />
<input type="text" name="my_textbox[2]" id="my_textbox2" />
<input type="text" name="my_textbox[3]" id="my_textbox3" />
<input type="text" name="my_textbox[4]" id="my_textbox4" />
the reason why i need to count is ,i am fetching values from ajax and creating new text-box appending new text-box like :
<input type="text" name="my_textbox[5]" id="my_textbox5" value="seomthing"/>
Now I would like to know the number of text-boxes present. It would be best if I can get the count through JavaScript .
Thanks in advance.
Give your inputs a classname so you can identify them as a group:
<input class="myInputs" type="text" name="my_textbox[1]" id="my_textbox1" />
Then in your javascript select them with querySelectorAll() and look at the length of the returned collection:
var inputs = document.querySelectorAll('.myInputs')
var number_of_inputs = inputs.length
Use document.querySelectorAll() to get all the elements matching substring of id (https://www.w3.org/TR/selectors/#attribute-substrings). This '[id^="my_textbox"]' syntax means you are selecting all elements with id starting with "my_textbox" string. The just take the length of queried collection and you are done. Please see snippet below:
var textboxCount = document.querySelectorAll('[id^="my_textbox"]').length;
console.log(textboxCount);
<input type="text" name="my_textbox[1]" id="my_textbox1" />
<input type="text" name="my_textbox[2]" id="my_textbox2" />
<input type="text" name="my_textbox[3]" id="my_textbox3" />
<input type="text" name="my_textbox[4]" id="my_textbox4" />

Update Div Hidden Field on jQuery Sortable Drag and Drop Update

I am using an HTML5 jQuery Sortable library. Not jQuery UI Sortable but this one here http://farhadi.ir/projects/html5sortable/
I have used it on many projects in the past and generally I use AJAX to save the sort order as a string of ID's into a database field.
On my current project, I need to do things completely different though. I am not using AJAX to save the order this time.
Basically I have the Sortable library running on a Form edit screen which will have a list of DIV's, inside these div's will be form fields. At the bottom of the page is a save button that submits the form to save all the data on the page. So I would like to instead store the sort order of each DIV into a hidden form field for each item.
I have set up a demo to work with on CodePen.io here http://codepen.io/jasondavis/pen/ztirw?editors=101
I could use some help to update a Form filed under each Div to update the fields with the Sort order each time a Drop occurs. So instead of saving a string of ID's in the correct sorted order, I would instead like to update every record on a Drop event into a Form filed with the current sort position.
Any help please?
The demo HTML structure looks like this...
<div id="project_tasks" class="tasks_block sortable">
<div id="task_13" class="task_row">
<span class="handle"></span>
<input name="taskid_13" id="taskid_13" size="15" type="text" value="taskID 1">
<input name="projectid_13" id="projectid_13" size="15" type="text" value="917fdb60-96d7-346f-10b3-54175c9a2f34">
Sort Order: <input name="sort_order_19" id="sort_order_19" size="15" type="text" value="1">
<br style="clear:both;">
</div>
<div id="task_14" class="task_row">
<span class="handle"></span>
<input name="taskid_14" id="taskid_14" size="15" type="text" value="taskID 2">
<input name="projectid_14" id="projectid_14" size="15" type="text" value="917fdb60-96d7-346f-10b3-54175c9a2f34">
Sort Order: <input name="sort_order_19" id="sort_order_19" size="15" type="text" value="2">
<br style="clear:both;">
</div>
<div id="task_15" class="task_row">
<span class="handle"></span>
<input name="taskid_15" id="taskid_15" size="15" type="text" value="taskID 3">
<input name="projectid_15" id="projectid_15" size="15" type="text" value="917fdb60-96d7-346f-10b3-54175c9a2f34">
Sort Order: <input name="sort_order_19" id="sort_order_19" size="15" type="text" value="3">
<br style="clear:both;">
</div>
<div id="task_15" class="task_row taskheading">
<span class="handle"></span>
<h2>List Heading 1</h2>
Sort Order: <input name="sort_order_19" id="sort_order_19" size="15" type="text" value="4">
<br style="clear:both;">
</div>
<div id="task_16" class="task_row">
<span class="handle"></span>
<input name="taskid_16" id="taskid_16" size="15" type="text" value="taskID 4">
<input name="projectid_16" id="projectid_16" size="15" type="text" value="917fdb60-96d7-346f-10b3-54175c9a2f34">
Sort Order: <input name="sort_order_19" id="sort_order_19" size="15" type="text" value="5">
<br style="clear:both;">
</div>
</div>
A little JavaScript to start things off...
$( document ).ready(function() {
$('#project_tasks').sortable({
handle: '.handle',
onStartDrag: function() {},
onEndDrag: function() {},
onChangeOrder: function() {}
}).bind('sortupdate', function() {
$('.sortable div').each(function() {
// Update a HIDDEN Field under each DIV with the current sort order
// So when my Form is submitted/saved, it can save the sort order for
// each record into the database.
});
});
});
Ok - here you go:
http://codepen.io/anon/pen/IEKvA
$('.sortable div').each(function(idx) {
var inputField = $(this).find("[id^='sort_order']");
$(inputField).val(idx);
});
The idea is to everytime and item is dropped you run thru your divs, find all the input fields that start with the id sort_order and set the index accordingly.

What is the most efficient way of submitting a form whose inputs are not direct children of the form element itself using native JavaScript?

I am currently creating a form for my employer which tracks individual employee statistics throughout a typical day, such as number of calls, revenue, items sold, etc. I would like to asynchronously update a database using a simple html form without necessarily having to use the entire jQuery library since all I would be using is the $.ajax method, which I do know is effective.
The trouble I'm running into is in finding a way to serialize a form using the form's <input type="submit"> button. My form's input fields are spatially organized using <div></div> tags between the <form> element itself and its <input /> fields themselves, as seen below:
<form name="tour_1" id="tour_1">
<div class="num_calls_cell">
<input type="text" value="3" name="total_calls" autocomplete="off" />
</div>
<div class="acw_cell">
<input type="text" value="24.35" name="acw" autocomplete="off" />
</div>
<div class="rev_cell">
<input type="text" value="125.34" name="revenue" autocomplete="off" />
</div>
<div class="env_cell">
<input type="text" value="0" name="envelopes" autocomplete="off" />
</div>
<div class="pen_cell">
<input type="text" value="1" name="pens" autocomplete="off" />
</div>
<div class="cal_cell">
<input type="text" value="0" name="other" autocomplete="off" />
</div>
<div class="comment_cell">
<input type="text" value="comment" name="comments" autocomplete="off" />
</div>
<div class="submit_cell">
<input type="submit" class="submit_tour" value="Submit Tour" />
</div>
</form>
There are a total of four of these forms that I have in one "day" (you may view the actual project here (http://ryanvold.com/prototype/prototype.php).
How could I most effectively transfer my form data into a PHP file that can easily update a MySQL database using my <input type="submit"> buttons?
You can serialize form like this:
document.getElementById('tour_1').addEventListener('submit', function(e) {
e.preventDefault();
var params = [];
for (var i = 0; i < this.elements.length; i++) {
params.push(this.elements[i].name + '=' + encodeURIComponent(this.elements[i].value));
}
params = params.join('&');
alert(params);
}, false);
This will give you params as follows:
total_calls=3&acw=24.35&revenue=125.34&envelopes=0&pens=1&other=0&comments=comment&=Submit%20Tour
Having constructed params string like this you can use it as ajax request POST parameters:
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(params);
This is just an example, remember to take care of IE if you need to support it (attachEvent).
Demo: http://jsfiddle.net/LnLaT/

jquery find logical operator inside selector

How can I search (jquery find) elements without using comma seperator. JSFiddle here.
Example:
<div id="inputs">
<input name="n1" value="v1" type="text" />
<input name="n2" value="v2" type="checkbox" />
<input name="n3" value="v3" type="button" />
<input name="n4" value="v4" type="hidden" />
<input name="n5" value="v5" type="text" />
<input name="n6" value="v6" type="text" />
<input name="n7" value="v7" type="text" />
<input name="n8" value="v8" type="text" />
<input name="n9" value="v9" type="text" />
<input name="n10" value="v10" type="text" />
</div>
1- I can do this with following code:
$('#inputs')
.find('input[type="text"][name="n7"], input[type="text"][name="n8"]')
.val("found");
2- But how I want to use this is like:
$('#inputs')
.find('input[type="text"][name="n7" || "n8"])
.val("found");
Reason: Just curious and think there might be a performance difference (second is faster).
How can I search elements without using comma seperator.
You cannot, the comma between multiple selectors is the only OR-operator available.
However, you can chain the searches and use the comma operator on a single level only:
$('#inputs input[type="text"]').filter('[name="n7"], [name="n8"]')
This is indeed more concise (no repetition) and should be more efficient as well. If you really want to match multiple values against a single attribute expression, use a custom filter function:
$('#inputs input:text').filter(function() {
var name = this.name;
return name=="n7" || name=="n8"; // or
return ~["n7","n8"].indexOf(this.name); // or
return /^n[78]$/.test(this.name); // or whatever
});

Serialize multiple select boxes for Ajax POST

I'll use a toy example to illustrate my problem:
I have a form which gets some details about a user:
<form action="#" method="post" id="myform">
<input type="text" name="fname" />
<input type="text" name="sname" />
<input type="text" name="birthdate" />
<select name="hobbies">
<option>Programming</option>
<option>Eating cats</option>
<option>Explaining string theory to my grandmother</option>
</select>
</form>
and I'm going to send it to my server with an ajax call so I can give some kind of response without a page refresh:
$.post("myserverscript.php", $('#myform').serialize(), function(){...callback...});
This works fine.
Now, I need to take the same information about multiple users on the same page. No problem, I just add [] to my input names:
<form action="#" method="post" id="myform">
<input type="text" name="fname[]" />
<input type="text" name="sname[]" />
<input type="text" name="birthdate[]" />
<select name="hobbies[]">
<option>Programming</option>
<option>Eating cats</option>
<option>Explaining string theory to my grandmother</option>
</select>
</form>
And again, all is well with the world.
Now, I want to allow the user to pick more than one hobby each:
<form action="#" method="post" id="myform">
<input type="text" name="fname[]" />
<input type="text" name="sname[]" />
<input type="text" name="birthdate[]" />
<select name="hobbies[]" multiple>
<option>Programming</option>
<option>Eating cats</option>
<option>Explaining string theory to my grandmother</option>
</select>
</form>
and this is where things start going a little pear-shaped. When I call serialize() now, all the hobbies are put into one array - so I'm unable to say which user has which hobbies.
I've tried using [][] instead of [] but that just puts each individual item into it's own array within the hobbies array so I still lose the user->hobby link.
The only way that I can see of doing this is writing my own serialize() which groups things as I need them.
Is there a better, simpler or more elegant way of doing this?
My standard approach is to append the UserID to the input name, with an underscore between them.
So, instead of this:
<input type="text" name="fname[]" />
it would be:
<input type="text" name="fname_23423" />
Then, server-side, you split the input names on _. The first element is the input name, the second is the UserID, and you're all set.
I've had a similar problem but the way I did it was to assign each user a specific array
for example this fiddle
<form action="#" method="post" id="myform">
<input type="text" name="user1[fname]" />
<input type="text" name="user1[sname]" />
<input type="text" name="user1[birthdate]" />
<select name="user1[hobbies]" multiple>
<option>Programming</option>
<option>Eating cats</option>
<option>Explaining string theory to my grandmother</option>
</select>
Submit
</form>

Categories