I have a table of rows and columns on an HTML-based entry form that allows the user to edit multiple records. Each row corresponds to a database record and each column to a database field.
When the user submits the form, the server needs to figure out which request parameter belongs to which row. The method I've been using for years is to prefix or suffix each HTML input element's name to indicate the row it belongs to. For example, all input elements would have the suffix "row1" so that the server would know that request parameters whose names end with "row1" are field values for the first row.
While this works, one caveat of the suffix/prefix approach is that you're adding a constraint that you can't name any other elements with a particular suffix/prefix. So I wonder if there's a better, more elegant approach. I'm using JSP for the presentation layer, by the way.
Thanks.
I don't know JSP very well, but in PHP you would define your input fields' names with an array syntax.
<input name='person[]'>
<input name='person[]'>
<input name='person[]'>
When PHP receives a form like that, it gives you an array (within the standard $_POST array), thus:
$_POST['person']=array('alice','bob','charlie');
Which makes it very easy to deal with having as many sets of fields as you want.
You can also explicitly name the array elements:
<input name='person[teamleader]'>
<input name='person[developer1]'>
would give you an array with those keys. If your current prefixes are meaningful beyond simply numbering the records, this would solve that problem.
I don't know whether the identical syntax would work for JSP, but I imagine it would allow something very similar.
Hope that helps.
Current user agents send back the values in the order of the fields as presented to the user.
This means that you could (theoretically) drop the prefix/suffix altogether and sort it out based on the ordering of the values. You'd get something like
/?name=Tom&gender=M&name=Jane&gender=F&name=Roger&gender=M
I don't know how your framework returns that, but many return it as lists of each value
name = [Tom, Jane, Roger]
gender = [M, F, M]
If you pop an element off of each list, you should get a related set that you can work with.
The downside to this is that it relies on a standard behavior which is not actually required by the specification. Still... it's a convenient solution with a behavior that won't be problematic in practice.
When browsers POST that information back to the server, it is just a list of parameters:
?name_row1=Jeff&browser_row1=Chrome&name_row2=Mark&browser_row2=IE8
So really, I think you can answer a simpler question: how do you relate keys in a key-value list?
Alternatively, you can go to a more structured delivery method (JSON or XML), which will automatically give you a structured data format. Of course, this means you'll need to build this value on the browser first, then send it via AJAX (or via the value of a hidden input field) and then unpack/deserialize it in the server code.
XML:
<rows>
<row><id>1</id><name>Jeff</name><browser>Chrome</browser></row>
<row>...</row>
</rows>
or JSON:
[{ "name":"Jeff", "browser":"Chrome"}, { "name":"Mark", "browser":"IE8" }]
There are many resources/tutorials on how to do this... Google it. Or go with the ostensible StackOverflow consensus and try jQuery.
Related
I have a database X, inside i have plenty of similar documents with a field called "order number" which come with sequential numbers. My question is, i am trying to make a view to show all the order numbers so i make something like
function(doc){ emit(doc.number, doc.order number);}"
But this gives error, so how to access in javascript the field "order number"(with a space in between the two names.
ps. using couchdb 1.6.1
Managed to find the answer
In JSON if you need to access a field where the keys has a space you need to do it through [].
e.g.
doc['order number']
i got the tip from this answer
Accessing JSON object keys having spaces
I have a multidimensional array that is something like this
[0]string
[1]-->[0]string,[1]string,[2]string
[2]string
[3]string
[4]-->[0]string,[1]string,[2]string[3]string,[4]string,[5]INFO
(I hope that makes sense)
where [1] and [4] are themselves arrays which I could access INFO like myArray[4][5].
The length of the nested arrays ([1] and [4]) can varry.
I use this method to store, calculate, and distribute data across a pretty complicated form.
Not all the data thats storred in the array makes it to an input field so its not all sent to the next page when the form's post method is called.
I would like to access the array the same way on the next page as I do on the first.
Thoughts:
Method 1:
I figure I could load all the data into hidden fields, post everything, then get those values on the second page and load themm all back into an array but that would require over a hundred hidden fields.
Method 2:
I suppose I could also use .join() to concatenate the whole array into one string, load that into one input, post it , and use .split(",") to break it back up. But If I do that im not sure how to handel the multidimensional asspect of it so that I still would be able to access INFO like myArray[4][5] on page 2.
I will be accessing the arrary with Javascript, the values that DO make it to inputs on page 1 will be accessed using php on page 2.
My question is is there a better way to acomplish what I need or how can I set up the Method 2 metioned above?
This solved my problem:
var str = JSON.stringify(fullInfoArray);
sessionStorage.fullInfoArray = str;
var newArr = JSON.parse(sessionStorage.fullInfoArray);
alert(newArr[0][2][1]);
If possible, you can use sessionStorage to store the string representation of your objects using JSON.stringify():
// store value
sessionStorage.setItem('myvalue', JSON.stringify(myObject));
// retrieve value
var myObject = JSON.parse(sessionStorage.getItem('myvalue'));
Note that sessionStorage has an upper limit to how much can be stored; I believe it's about 2.5MB, so you shouldn't hit it easily.
Keep the data in your PHP Session and whenever you submit forms update the data in session.
Every page you generate can be generated using this data.
OR
If uou are using a modern browser, make use of HTML5 localStorage.
OR
You can do continue with what you are doing :)
Below is a snipet of code that I am having trouble with. The purpose is to check duplicate entries in the database and return "h" with a boolean if true or false. For testing purposes I am returning a true boolean for "h" but by the time the alert(duplicate_count); line gets executed the duplicate_count is still 0. Even though the alert for a +1 gets executed.
To me it seems like the function updateUserFields is taking longer to execute so it's taking longer to finish before getting to the alert.
Any ideas or suggestions? Thanks!
var duplicate_count = 0
for (var i = 0; i < skill_id.length; i++) {
function updateUserFields(h) {
if(h) {
duplicate_count++;
alert("count +1");
} else {
alert("none found");
}
}
var g = new cfc_mentoring_find_mentor();
g.setCallbackHandler(updateUserFields);
g.is_relationship_duplicate(resource_id, mentee_id, section_id[i], skill_id[i], active_ind,table);
};
alert(duplicate_count);
There is no reason whatsoever to use client-side JavaScript/jQuery to remove duplicates from your database. Security concerns aside (and there are a lot of those), there is a much easier way to make sure the entries in your database are unique: use SQL.
SQL is capable of expressing the requirement that there be no duplicates in a table column, and the database engine will enforce that for you, never letting you insert a duplicate entry in the first place. The syntax varies very slightly by database engine, but whenever you create the table you can specify that a column must be unique.
Let's use SQLite as our example database engine. The relevant part of your problem is right now probably expressed with tables something like this:
CREATE TABLE Person(
id INTEGER PRIMARY KEY ASC,
-- Other fields here
);
CREATE TABLE MentorRelationship(
id INTEGER PRIMARY KEY ASC,
mentorID INTEGER,
menteeID INTEGER,
FOREIGN KEY (mentorID) REFERENCES Person(id),
FOREIGN KEY (menteeID) REFERENCES Person(id)
);
However, you can make enforce uniqueness i.e. require that any (mentorID, menteeID) pair is unique, by changing the pair (mentorID, menteeID) to be the primary key. This works because you are only allowed one copy of each primary key. Then, the MentorRelationship table becomes
CREATE TABLE MentorRelationship(
mentorID INTEGER,
menteeID INTEGER,
PRIMARY KEY (mentorID, menteeID),
FOREIGN KEY (mentorID) REFERENCES Person(id),
FOREIGN KEY (menteeID) REFERENCES Person(id)
);
EDIT: As per the comment, alerting the user to duplicates but not actually removing them
This is still much better with SQL than with JavaScript. When you do this in JavaScript, you read one database row at a time, send it over the network, wait for it to come to your page, process it, throw it away, and then request the next one. With SQL, all the hard work is done by the database engine, and you don't lose time by transferring unnecessary data over the network. Using the first set of table definitions above, you could write
SELECT mentorID, menteeID
FROM MentorRelationship
GROUP BY mentorID, menteeID
HAVING COUNT(*) > 1;
which will return all the (mentorID, menteeID) pairs that occur more than once.
Once you have a query like this working on the server (and are also pulling out all the information you want to show to the user, which is presumably more than just a pair of IDs), you need to send this over the network to the user's web browser. Essentially, on the server side you map a URL to return this information in some convenient form (JSON, XML, etc.), and on the client side you read this information by contacting that URL with an AJAX call (see jQuery's website for some code examples), and then display that information to the user. No need to write in JavaScript what a database engine will execute orders of magnitude faster.
EDIT 2: As per the second comment, checking whether an item is already in the database
Almost everything I said in the first edit applies, except for two changes: the schema and the query. The schema should become the second of the two schemas I posted, since you don't want the database engine to allow duplicates. Also, the query should be simply
SELECT COUNT(*) > 0
FROM MentorRelationship
WHERE mentorID = #mentorID AND menteeID = #menteeID;
where #mentorID and #menteeID are the items that the user selected, and are inserted into the query by a query builder library and not by string concatenation. Then, the server will get a true value if the item is already in the database, and a false value otherwise. The server can send that back to the client via AJAX as before, and the client (that's your JavaScript page) can alert the user if the item is already in the database.
I have a long array with multiple items per object and I have to start to exclude items depending on what someone selects as a check box, you can see a basic idea working here
http://jsfiddle.net/caseybecking/QwtFY/
My question is how do I start to narrow the list without having to do a check on how man y items they have checked, also this doesn't work if they check multiple items per "Fit" or "Wash"
To elaborate further my objectives. I need to store object(s) that only contain the specific item(s) the user wants to FILTER down to. All this is is a ginat filter of multiple pieces of a long array.
Sounds like you want something like .serialize() or .serializeArray() -- then you can send this data to your server or use the serialized array to filter the json object. You'll need to make sure each input element has a name attribute. In the below fiddle I've removed the hideous boxChecked function as haven't a clue what your trying to achieve in that. Anyway:
Fiddle: http://jsfiddle.net/zZtyy/
I have an ajax function which call a servlet to get list of products from various webservices, the number of products can go up to 100,000. I need to show this list in a html table.
I am trying to provide users an interface to filter this list based on several criteria. Currently I am using a simple jQuery plugin to achieve this, but I found it to hog memory and time.
The Javascript that I use basically uses regex to search and filter rows matching the filtering criteria.
I was thinking of an alternate solution wherein I filter the JSON array returned by my servlet and bind the html table to it. Is there a way to achieve this, if there is, then is it more efficient than the regex approach.
Going through up to 100,000 items and checking if they meet your criteria is going to take a while, especially if the criteria might be complex (must be CONDO with 2 OR 3 bedrooms NOT in zip code 12345 and FIREPLACE but not JACUZZI).
Perhaps your servlet could cache the data for the 100,000 items and it could do the filtering, based on criteria posted by the user's browser. It could return, say, "items 1-50 of 12,456 selected from 100,000" and let the user page forward to the next 50 or so, and even select how many items to get back (25, 50, all).
If they select "all" before narrowing down the number very far, then a halfway observant user will expect it to take a while to load.
In other words, don't even TRY to manage the 100,000 items in the browser, let the server do it.
User enters filter and hits
search.
Ajax call to database, database has indexes on appropriate
columns and the database does the filtering.
Database returns result
Show result in table. (Probably want it to be paged to
only show 100-1000 rows at a time
because 100,000 rows in a table can
really slow down your browser.
Edit: Since you don't have a database, the best you're going to be able to do is run the regex over the JSON dataset and add results that match to the table. You'll want to save the JSON dataset in a variable in case they change the search. (I'm assuming that right now you're adding everything to the table and then using the jquery table plugin to filter it)
I'm assuming that by filtering you mean only displaying a subset of the data; and not sorting.
As you are populating the data into the table add classes to each row for everything in that row you want to filter by. e.g.:
<tr class="filter1 filter2 filter3">....
<tr class="filter1 filter3">....
<tr class="filter2">....
<tr class="filter3">....
Then when you want to apply a filter you can do something like:
$('TR:not(.filter1)').hide();
I agree with Berry that 100000 rows in the browser is bit of a stretch, but if there's anything that comes close to handling something of that magnitude then it's jOrder. http://github.com/danstocker/jorder
Create a jOrder table based on your JSON, and add the most necessary indexes. I mean the ones that you must at all cost filter by.
E.g. you have a "Name" field with people's names.
var table = jOrder(json)
.index('name', ['Name'], { sorted: true, ordered: true });
Then, for instance, this is how you select the records where the Name field starts with "John":
var filtered = table.where([{ Name: 'John' }], { mode: jOrder.startof, renumber: true });
Later, if you need paging in your table, just feed the table builder a filtered.slice(...).
If you're getting back xml, you could just use jQuery selection
$('.class', context) where context is your xml response.
From this selection, you could just write the xml to the page and use CSS to style it. That's where I'd start at first, at least. I'm doing something similar in one of my applications, but my dataset is smaller.
I don't know what you mean by "bind"? You can parse JSON and then use for loop (or $.each()) to populate ether straight HTML or by using grid plugin's insert/add