A bit of a random exercise but I want to take content from an existing table and create a new table based on the entries taken.
In the image above, the table on the left is what I have to work with already. The blue table on the right is what I want to create; using the data from the table on the left.
Can this be done with jQuery or some basic PHP?
If you're wondering why I'm doing this its because I don't have access to the SQL database and I want to use Google Charts API to display total number of user registrations for each month.
As always, your help is MUCH appreciated.
Using JQuery it can be done in this way
//initialize monthArray
var monthArr = [{month:'April', occ:0}, {month:'May', occ:0},{month:'June', occ:0}];
//read occurrences for MonthNames in your existing table
$.each(monthArr, function(n,i){
var _occ = $("td:contains('"+monthArr[n].month+"')").size();
monthArr[n].occ = _occ;
});
// create new table and show the values
$.each(monthArr, function(index, value) {
//alert(value.occ+ ': ' + value.month);
$('#inTable').append('<tr><td>'+value.month+'</td><td>'+value.occ+'</td></tr>');
});
Here is fiddle: http://jsfiddle.net/A3WeJ/38/
Note: Table look and feel formatting has not been done in this solution
The question of whether or not you wish to use jQuery or PHP depends on whether the content of these tables is likely to change after the page has loaded. If the page will not change, you should use PHP.
Assuming the table is produced using a while or foreach loop, you can simply set up counts for each option that you have in the table. Within the loop, if you check what is in this column and add to an appropriate arbitrary count, you can count how many are in each.
It would probably be good to check what the contents is, and if it's already in your array.
Hope that provides some initial help to the thinking behind this question!
You may try this (You didn't provide more information, so just may be an idea)
HTML The id maintable could be changed with another id/class or just table
<table id="maintable">
<thead><th>Name</th><th>Join Month</th><th>Join Year</th></thead>
<tbody>
<tr><td>Joe Blogs</td><td>April</td><td>2012</td></tr>
<tr><td>Mr. X</td><td>April</td><td>2012</td></tr>
<tr><td>Andrew Xmen</td><td>April</td><td>2012</td></tr>
<tr><td>Matt Bblogs</td><td>may</td><td>2012</td></tr>
<tr><td>Malcom McGuiness</td><td>June</td><td>2012</td></tr>
<tr><td>Friday Needavodka</td><td>June</td><td>2012</td></tr>
</tbody>
</table>
<div id="myTblDiv"></div>
JS
$(function(){
var rows={};
$('table#maintable tbody tr').each(function(){
var item=$('td:eq(1)', $(this));
if(rows.hasOwnProperty(item.text()))
rows[item.text()]=parseInt(rows[item.text()])+1;
else rows[item.text()]=1;
});
var myTable=$('<table />', {'id':'myNewtable', 'class':'table table-striped'});
var th=$('<thead><th>Total</th><th>Month</th></thead>');
var tbody=$('<tbody></tbody>');
myTable.append(th).append(tbody);
$.each(rows, function(k, v){
var row=$('<tr><td>'+v+'</td><td>'+k+'</td></tr>');
myTable.find('tbody').append(row);
});
$('div#myTblDiv').append(myTable);
});
DEMO or Different Style.
Notice, I've used an id (maintable) for the table generated by google, in this case you have to change the id or class (if it has any) or even you can just use table without any id or class name but make sure there is only one table when you are using only $('table'), also if you can wrap the table within a parent div then you can use $('div#parentDivId table').
Related
I want to emulate this booking form.
If pickup is not an airport in the drop down list, it swaps to a google maps autocomplete drop down list.
I have a database and can show the two drop down lists independently. What I want to achieve is that as you type - depending on the input content - hide one list and show the other one. (That is how I think it's done according to the website code).
If anyone could shed some light I would be very grateful.
I asked web admin but doesn't know because it has been done for him 😥
This could be the functions you could use
You may want to save the lengths and check if the length changes.
var dd1 = document.getElementById("dd1").value;
var dd2 = document.getElementById("dd2").value;
if(dd1.value.length >0 ){dd2.style.display = 'none'}
if(dd2.value.length >0 ){dd1.style.display = 'none'}
Or add an onkeypress event
dd1.onkeypress="checkkeystroke(1)"
dd1.addEventListener("keypress", function(){checkkeystroke(1);};
<input id="dd1" type="text onkeypress="checkkeystroke(1)" />;
<script>
var dropdown = [null,null,null];
const toggle = {1:[2],2:[1]};
dropdown[1] = document.getElementById("dd1");
dropdown[2] = document.getElementById("dd2");
function checkkeypress(id){
dropdown[id] = dropdown[toggle[id]].style.display = 'none';
}
</style>
That's just some basic possibilities. You would probably need to add some integrity checks. You do not want to hide both entry inputs
UPDATE
I want to show different drop downs depending on the text being
entered - and not in its length. If text written is not in the initial
drop down list, show a second drop down list
So instead of getting the length you have the "value" of the text which I needed to to get the length. You may want to get the length and segment your list of words by length. Maybe not.
Make and array of the wordlist
const wordlist = ['','','','','','',''];
if you have a different wordlist for each dropdown
then use an object instead of an array
const wordlist = {0:['','','','','','',''],1:['','','','','','',''],2:['','','','','','',''];
You need to use consecutivly numbered ids in your dropdowns
e.g.
<select id="dd0"><select id="dd1"><select id="dd2">
The following will search your wordlist and if it finds a word in teh text value it makes dropdown #3 disappear and dropdown #4 aapear.
<script>
wordlist['','','','','','',''];
var dd= [null,null,null];
for (var id in dd){
dd[id] = document.getElementById('dd' + id);
}
function keystroke(id){
for (for var key in wordlist){
if (dd[id].value.includes(wordlist[key])){
dd[3].style.display = 'none';
dd[4].style.display = 'block';
}
}
}
</script>
This should get you going if you understand my code. There are some things I'd like to explain but a client just called and I need to go back to work. I do not know your programming level. My code may be a little on the advanced side. It will be very fast and can handle a large word list so you may want to include common misspellings in your word list. If you have questions I'll be around later. There may be errors in my syntax I did not proof read the code. No time.
I'm sorry I haven't included "my attempt" as such with this one, I'm useless with jquery so need some advice!!
I would like to change the value of a second selctor based on the results of the first.
I have a database of builders and regions with the headers builder_name and builder_region. The list ends up looking like this ...
builder_1 region_1
builder_1 region_2
builder_2 region_1
builder_3 region_1
builder_3 region_2
builder_3 region_3
(You get the idea)
I'm using the following in the form I've built to get a list of the builders for the first select box ...
echo '<select class= "ml-select" name="gen_builder">';
echo '<option value=" ">Select Builder</option>';
while($row = mysql_fetch_array($rsBUILDER)) {
if($linebreak !== $row['builder_name']) {
echo '<option value="'.$row['builder_name'].'">'.$row['builder_name'].'</option>';
}
else {echo "";}
$linebreak = $row['builder_name'];
}
echo '</select>';
The $linebreak is to get rid of the duplicate builder names from the list, which works a treat.
What I would like to achieve is a second selector that selects the regions available, dependant upon the builder that has been selected in the first option. I hope this makes sense????
The second query needs to look at the builder selected in the first selector and filter out just the regions that are in rows with the builder name form selector one.
Please do say if you need further information, I'm not great at explaining myself.
As you said you don't have experience with jQuery or Ajax, I'll post my answer with as many comments as possible. I will assume that you have two select dropdowns in your page.
The first one contains the builders, so it will have id="builders".
The second one contains the regions, so it will have id="regions".
From what I understand, the first select will be exactly the one you posted in your question, generated server-side (by PHP). I only ask that you please make a slight change on it, making each option value be equal to the builder's database ID, and not its name (unless the builder's primary key is their name, and not an ID). This will make no difference for the final user but will be important for our jQuery solution. The second one will be empty, as the idea is to fill it dynamically with the regions related to the builder selected in the first dropdown.
Now let's get to the jQuery code:
//Everything that goes below this first line will be ready as soon as the page is fully loaded
$(document).ready(function() {
//The following code defines an event. More precisely, we are defining that the code inside it will run every time our select with id "builders" has its value changed
$('#builders').change(function() {
//$(this) is our builders select. $(this).val() contains the selected value, which is the ID of our selected builder
var currentValue = $(this).val();
//Now, this is our Ajax command that will invoke a script called get_regions.php, which will receive the builder's ID in $_GET['builder_id'] and you can use to query your database looking for all regions related to this builder. Make sure to create an array with the returned regions. Your get_regions.php's last line should be echo json_encode($regions);
$.get("get_regions.php", {'builder_id': currentValue}, function(data) {
//Inside this function is the code that will run when we receive the response from our PHP script. It contains a JSON encoded list of regions, so first of all we need to parse this JSON
var regions = $.parseJSON(data);
//Before filling our second select dropdown with the regions, let's remove all options it already contains, if any
$('#regions').empty();
//Now, all there is left is to loop over the regions, adding each as an option of the regions dropdown. I'll do it the universal way
for (var i = 0; i < regions.length; i++) {
var regionOption = '<option value="'+regions[i]['region_name']+'">';
regionOption += regions[i]['region_name'];
regionOption += '</option>';
$('#regions').append(regionOption);
}
});
});
});
Despite any syntax errors (can't test the code from here) this should do the trick. Hope the comments were clear enough for you to understand how things work in jQuery.
I'm working on a project that involves returning the id of the checkboxes chosen as well as the text in the corresponding textarea fields for those chosen checkboxes. The data is dynamically displayed and so far my jquery pull of both the checkboxes and textareas work:
var noteList = $("textarea[name='revokeNotes']").map(function(){
return this.value;
}).get().join();
var revokeList = $("input[name='revoke']:checked").map(function(){
return this.id;
}).get().join();
but I'm getting back all of the notes fields and I'm uncertain how to best iterate through them to find the proper notes as their ids aren't sequential but rather based on their id in the table they are being pulled from. The last version of the display code is below:
<td><textarea name=\"revokeNotes\" id=\"".$v["id"]."\" cols=\"30\"rows=\"3\">".$v["notes"]."</textarea></td>
<td><input type=\"checkbox\" id=\"".$v["id"]."\" name=\"revoke\" value=\"".$v["id"]."\" /></td>
Is there a way to reach my goal from this state or should I be using another jquery function, similar to .map()? I thought about using the id field from the checkboxes to iterate through the selected notes and pushing them into an array but I'm not sure 1) if that will work and 2) how to do that.
I need the data back in some form either an array or something I can explode on in php to create an array as I'm passing one value in ajax as there is no set maximum or minimum number of rows that will be displayed per user. Map was working until I threw some commas at it. Extra points for that.
var noteList = $.map(
$("textarea[name='revokeNotes']").filter(function() {
return $(this).closest('td')
.next('td')
.find('input[type="checkbox"]')
.is(':checked');
}), function(el) {
return el.value;
}).join();
adeneo's answer is great, I'd just propose the following improvements:
If possible use class selectors (like '.revoke-notes-area') since those are faster than DOM + attr selectors
Assuming this is a table and there is one textarea checkbox combo per row, you can traverse the tree to the closest <tr> a decouple the JS from depending that the checkbox comes after the text area in the DOM.
var filterMethod = function() {
$(this).closest('tr').find('.revoke-checkbox').is(':checked');
};
var mapMethod = function(el) {
return el.value;
};
var nodeList = $.map($('.revoke-notes-area').filter(filterMethod), mapMethod);
There's no reason you cannot or should not put the filter and map methods inline, I just split them out into variables so it's easier to read here.
You can check out my codepen here: http://codepen.io/aaron/pen/eIpby.
I have here a jQuery calculator script that allows me to calculate the values (of a specific css class) for input boxes in each row.
I have 8 rows total, with plans to allow users to dynamically add rows in the future.
My problem is not knowing how jquery library works in it's full potential. I'm not even sure if what I'm requesting is possible, but I tried looking around and couldn't find much,
$(function(){
$('specific-class').each(function() {
$(this).keyup(function(){
calculateTotal($(this));
});
});
});
function calculateTotal(src) {
var sum = 0;
var sumtable = src.closest('tr'); //only calculate the current row
sumtable.find('specific-class').each(function() {
if(!isNaN(this.value) && this.value.length!=0) {
sum += parseFloat(this.value);
}
});
sumtable.find(".qty").html(sum.toFixed(0)); //send to front
}
So with the above complete, I will be able to check each individual TD with the specific class and add the values together.
How do I go about storing the values of each row that gets calculated and then sending the stored variables as their own qty such as qty1,qty2,qty3 etc..?
Thank you SO Community you've been a huge help to my many questions.
The only way you can send data from jquery to PHP is using $.post or $.get.
You can post you data to the same file that called it, or some separate file which has the function to manage your data.
My preferred is the second one. Keeps you project modular.
I may just be searching Google using the wrong keywords but I am having very little luck finding information on creating expandable form fields. I have an input form where a user can list all of the inventory assigned to a server node, but would like for them to be able to add additional items if needed. Example being the form shows an option for (1) Disk to be added but they can click a + symbol and add more.
I already created 8 MYSQL rows for each type such as disk1, disk2, etc. to allow for a considerable amount to be stored. However, my concern is that this works out to be a LOT of options.
1) How can I use Javascript to create expandable forms? I only found one code example that didn't work.
2) Should I hard-code all of the options? Such as, right now my code has a Select box named "ram", "motherboard", etc. Could I generate these or should I go ahead and write it out for each field such as "ram1", "ram2", etc?
Cloning the field in JavaScript is easy. Say you have:
<select name="hdd"><!-- ...options here...--></select>
then once you get a reference to that existing element in the DOM (see below), you can do this:
var newSelect = existingSelect.cloneNode(true);
newSelect.selectedIndex = -1; // To clear any existing selection
existingSelect.parentNode.insertBefore(newSelect, existingSelect.nextSibling);
Getting the reference to the existing select can be done on any modern browser using a CSS selector and document.querySelector (to get the first match) or document.querySelectorAll (to get a list of all matches), for instance:
var list = document.querySelectorAll('select[name="hdd"]');
var existingSelect = list[list.length - 1]; // Get the last one
...which will give you the last one. Or more likely, you have a row of some kind (a tr, or a div) containing that which you want to copy. Not a problem, give that row a class (say, "hdd"), and clone the entire thing (here I'm cloning the last row and adding it to the end):
var list = document.querySelectorAll('.hdd');
var existingRow = list[list.length - 1]; // Get the last one
var newRow = existingRow.cloneNode(true); // Clone it
newRow.querySelector('select[name="hdd"]').selectedIndex = -1; // Clear selected value
existingRow.parentNode.insertBefore(newRow, existingRow.nextSibling);
On the MySQL side of things, it's best not to have columns like hdd1, hdd2, etc., because it makes queries on those fields complicated and does, of course, limit the maximum number you can have (granted you'll probably want to limit that anyway). (Having those columns in one row is called "denormalizing" the DB.)
The usual way to do that in DB design is to have a second table, listing HDDs, where a key in that second table (a "foreign key") links back to your main table. (See "database normalization" for more information.)
So your main table might have a record id, say SystemID. Your HDDs table would then have a SystemID column and an HDD column, where it could have many rows for the same SystemID.
Here's a complete example of the form bit: Live Copy | Live Source
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Add Form Field Example</title>
</head>
<body>
<div class="hdd">
<label>HDD: <select name="hdd">
<option>--choose--</option>
<option>80GB</option>
<option>500GB</option>
<option>1TB</option>
<option>2TB</option>
</select></label></div>
<input type="button" id="theButton" value="Add Row">
<script>
(function() {
document.getElementById("theButton").addEventListener("click", addRow, false);
function addRow() {
var list = document.querySelectorAll('.hdd');
var existingRow = list[list.length - 1]; // Get the last one
var newRow = existingRow.cloneNode(true); // Clone it
newRow.querySelector('select[name="hdd"]').selectedIndex = -1; // Clear selected value
existingRow.parentNode.insertBefore(newRow, existingRow.nextSibling);
}
})();
</script>
</body>
</html>
Some useful references:
Selectors Level 1
DOM3 Core
DOM2 HTML
HTML5 Specification
Try creating a generic DEVICE_DETAIL table, with columns for TYPE and DETAILS. Then you can hold an arbitrary number & add new types in the future.
create table DEVICE (
ID integer not null,
..
primary key (ID)
);
create table DEVICE_DETAIL (
ID integer not null,
FK_DEVICE integer not null,
"TYPE" varchar(24), -- type code; defined internally.
CONFIG varchar(200),
NOTES clob, -- if necessary?
.. more columns if useful
primary key (ID)
);
The benefit of this, is that you don't need separate tables for HDD, IP addresses, RAM, or a wide range of future possibilities. You just need a couple of columns which can hold the details -- and for most things, one line will suffice.
Add & show new fields in the UI, as the user fills out the previous ones.
The simplest way to do this is to register an "Add Field" click handler, and use that to create a new field in Javascript. I've put together a quick example to show you how to do this with input fields.
Here's the HTML:
<form id='form'>
<div>
<label for='input0'>Field 0</label>
<input name='input0' type='text'></input>
</div>
</form>
<a id='moreLink' href='#'>Add Field</a>
Here's the Javascript:
var inputIndex = 0;
document.getElementById('moreLink').addEventListener('click', function() {
var form = document.getElementById('form'),
newLabel = document.createElement('label'),
newInput = document.createElement('input'),
newDiv = document.createElement('div'),
inputId
;
inputIndex++;
inputId = 'input' + inputIndex;
newLabel.htmlFor = inputId;
newLabel.innerHTML = 'Field ' + inputIndex;
newInput.name = inputId;
newInput.type = 'text';
newDiv.appendChild(newLabel);
newDiv.appendChild(newInput);
form.appendChild(newDiv);
});
And here's a link to a JSFiddle so you can see it in action: http://jsfiddle.net/tpmet/
This is a pretty naive solution, but it'll perform fine and will work in any browser you throw at it, at least as far back as IE6.
If your markup gets more complicated, you should consider creating a template once at startup and cloning that template in the click handler. And if you plan to add entire forms or other large amounts of DOM, I'd recommend reading up on Document Fragments, which are more complicated but would perform better at that level of scale.
Hope this was helpful, please comment if my answer is unclear.