The situation is elementary and is often the case: Any tabular data - for example, the booking of an account - are using a Web application are maintained. Nevertheless, I have found after an initial screening no suitable software for this simplest use case [1].
Specifically, an application for table maintenance
the table data from the server operating
the user to view and care,
affect cell, delete entire rows or add new rows
and finally those changes secure can
which they are written back to the server.
How to design such an application? Sure once you need a physical picture of the table, the be deposited somewhere in the file system needs. On the other hand, it requires a presentation layer (GUI) to display the table to the user and offer him to change. For Web applications, the presentation layer is generally from HTML pages.
Between these two extremes - GUI and file system - are essentially two software components that work together in such an application: A Persistenzkomponente, which is responsible for ensuring that the data exists on the user's session also. And a change in administration, which logs the changes of the user and a user selected point on the Persistenzkomponente passes. inspired
to the jargon of the database programmer, the table is the application in two forms: as
Before Image
it represents the state of data before the user gets to see and manipulate (with the
Image
The maintenance screen meant, to which the user can change the data). The After-Image
therefore modeled the changes that the user has made to the data. From the comparison of
Before Image
the after-image is a series of
insert
-
update
-
and delete operations
derived that must be made to the table.
If the table comes from the server, it is the Before-Image dar. These data are presented, the client in a form that allows the user to change easily. Besides presenting the client manages the user-made changes. The client knows at any time, whether and what changes were made. can really only if changes were made, one needs to offer the user a
Save button, which he just made the changes, "commit" means continuing to write the persistence layer.
Here is my example implementation [2]:
http://www.ruediger-plantiko.net/konto
The application consists of a single HTML page. Client-side logic is shown with JavaScript. Communication with the server via Ajax, which is used as a structure for data exchange in both directions, the JavaScript data format JSON. The HTML page is dynamically manipulated using JavaScript. On the server side receives a Perl CGI program under the request, a query parameter names action tells the server what to do it. For example, shares the URL / cgi-bin/konto.pl action = get_all with the program
konto.pl
that all line items into it from the account file and send the client in JSON format should. In contrast, a second action shares called save
/ cgi-bin/konto.pl? Action = save with
the server that the belly of the HTTP request is a JSON hash of row data to be updated in the account file. He recognized these changes and then sends the client as
get_all
the updated image of the file (again in JSON format). Only these two
action
s are the way required.
The two layers communicate only through this interface and are otherwise completely independent. This means, for example: Instead of using CGI Perl on the request could be also deal with any other technology. In my implementation, the interface between the systems at the same time the interface between the two mentioned software components: The server manages the persistence, while management is the change to the client.
The special features of this implementation is that the data on the client bookings only in the dynamic table
are kept - which is exactly the table that the user sees. There is no picture of this extra data, such as a global array. Similarly with the change management: There is no global flag
data loss
. If the user makes changes to this for him visibly marked in the table as amended. There is no global flag, but a function
data loss ()
that looks easy, whether cells are marked as changed.
But let's start with the data format. I've thought of a simple CSV-like format. You can use comment lines and blank lines. They remain on updates and ignore the rest. Comment lines begin as Perl, with the pound sign (#
). Furthermore, should there be in addition to the entry lines, other lines in the file that could be inserted manually or by another program. For example, a cron job could periodically check the account balance and paste it as a real balance in the file. Our program is designed to reproduce all these lines, but ignore for their own processing.
This can be set up so that the first column in the CSV format, an ID representing the set. This ID for which alone can be taken into account line items have the prefix
book, while other lines have different prefixes. Balance lines for example, could have the prefix
net
initiated IDs. The file can be the following example:
# withdrawals buch1; 01/09/2010; 150.00, Norbert; Fee "Modern JavaScript" buch2, 09.10.2010, 605.00, Petra; Flight to Florence, rental car, accommodation buch3, 09.23.2010, 200.00; Norbert; Donate to Wikipedia
balance1; 09/30/2010; 15362.00
buch4, 10.03.2010, 350.00, Petra; New Smartphone
If, after the table maintenance application is called the Web, given the competent Perl class CsvTableMaintainer
the command to load all line items (
action = get_all ). The above example file is transformed into the following JSON object: { reservations: [ ["buch1", "01/09/2010", "150.00", "Norbert", "Course fee \\" Modern JavaScript \\ ""],
["buch2", "10/09/2010", "605.00", "Petra", "Flight Florence, car, night "],
[" buch3 "," 23/09/2010 "," 200.00 "," Norbert "," donation to Wikipedia "], [" buch4 "," 10/03/2010 "," 350.00 "," Petra "," New Smartphone "] ] user:" Petra, " msg:" "
This hash is now in the browser by the JavaScript function
update page () is received
this. first transmits the user under which the notification is made, in an intended field (unless it is to be displayed, you can set this field to invisible). For every other element of the hash is a function
\u0026lt;key> _update (\u0026lt; ; value>)
called with the key and
- \u0026lt;key>
- \u0026lt;value>
the value of this entry means - if a function exists with this name. If not, - \u0026lt;key>
is simply the ID of an element in the HTML DOM considered to replace its contents with - \u0026lt;value>
is. Finally, the hourglass-graph is set to invisible, which indicated the user the server activity: - / / --- After the return of an Ajax-Requests: side
update function update page (transport) { - / / transport parameters is The Ajax object (ultimately XMLHttpRequest)
var id, newCode;
/ / The user first upgrade
if (newCode.user) {
user_update (newCode.user);
delete newCode.user;}
for (id in newCode) {/ / either with a special method, if implemented ... if (typeof self [id + "_update"] == "function") { self [id + "_update"] (newCode [id]);} / / ... or simply by replacing the HTML content else {$ (id) update (newCode [id]);. reset}} / / Load state $ ("loading") hide ();. }
For the key
reservations there is a designated function buchungen_update ()
, which therefore is the array of line items called. It gets passed an array of arrays (AoA), so it can access any cell of each row. It passes through the cells to be displayed in a nested
each ()
loop and builds each
\u0026lt;tr> - and \u0026lt;td>
elements in the HTML table. The registration of users have also made reservations yet another cell that control cell
with Icons to modify, and delete rows. These must all be made more sensitive click by the doOnClick ()
registered for the event click
is. Finally, the button is hidden for safety: always go through when this feature is, the table contains the pure database state. A backup is therefore unnecessary: / / --- From the server as an array of array (AoA) sent line items / / to HTML take
buchungen_update function (rows) {var tbody = $ ("reservations"). down ("tbody");. var user = $ ("user") innerHTML; tbody.update ("");
was controlling cell code = control (cell);
rows.each (function (cell) { where ROWID = cells.shift (); each row = new Element ("tr", {id: ROWID}); cell . EACH (function (cell data, index) {row.appendChild (
new Element ("td", {className: "c" + (index +1)}) . update (cell data)); }); row.appendChild (
new Element ("td",
{className: "c5"}). update (
(cell [2] == user)? control cell code: ""));
tbody.appendChild (row) ; }); $ ("booking") show ();. / / All the pictures in the book table reservations click sensitive $$("# img ") each (function (img) {img.observe
(. "click", doOnClick);
}); / / database state - Backup is unnecessary
$ ("save") hide ();
} When the user "change" or "New Entry". click to open a form region to maintain a single table row. This form is really only for editing, it is never sent. For locking the user presses the button on the form region "Apply". Then closes the form, and the amended or new cell contents are entered in the table and receive a mark in the form of the CSS class
changed. This mark indicates to the user as well as the program that these fields are different from the database level.
Since the function data loss ()deleted or contains any cell with the CSS class
responsive now is available to back up the button. This is the function
check data loss ()
responsible, that is called after all operations, potentially leading to data changes. This in turn calls to the aforementioned function
data loss ()
to change the status by inspection of the table to determine. This can be formulated with the Prototype framework is very compact. The four terms of the function read like this: check to see if there is any real data line of the reservation table that holds either row-level, the CSS class
changed. Since the functions used any () and down () short-circuit, ie, stop the iteration after the first discovery, the implementation of the method
data loss ()
not only short but also efficient:data loss function () {return $
/ / - - Save button to offer only if data has changed
data loss function check () {$
("save") style.display. = Data loss ()? "Inline": "none";}
/ / --- Determine if data has changed
("booking") down ("tbody")..
select ("tr") any (function (row) {return row.hasClassName ("deleted") ID starts with the prefix new ) are treated the same as this modified line: The line data is added as part of the ID data in the hash. passed for deleted rows, the special keyword deleted as the data part. If the user Petra in the above example, the line buch2 deletes the amount of the line buch4 From 350.00 CHF to 400.00 CHF changes and inserts a new row to capture their Hanover hotel bill, sees the server to the passed hash follows from : { buch2 "deleted",
buch4: 03/10/2010; 400.00, Petra; new smartphone, "
new1: 10/09/2010; 100.00; night Hannover
}strict;
The server receives this JSON hash in the body of the HTTP request, together with the value
save for the URL parameter action
. It evaluates the hash and translates it into instructions to change the . data files also will be awarded for newly created lines of a final ID Finally, he gives -. returns the current state of the line items to the client [3]
The entry point for all internal, from the website - such as the command
get_all
. using Ajax remote requests is the CGI-Perl program
konto.pl
. It evaluates the URL parameter action
. How does it do that? The CGI mechanism is very simple: the query part of a URL is provided to the called program in the form of environment variables. The body of the request can be read from standard input and all output to standard output form the body of the HTTP response. The program
konto.pl
therefore extracted the value of
action from the query string of the URL and then calls dynamically to the sub-program of that name. ! Here's how:
# W: / perl / bin / perl.exe
# CGI Perl request handler that use the account maintenance page communicates
use warnings;
no strict 'refs'; use CsvTableMaintainer; # Table maintenance class use MiniJSON; # Required Perl JSON conversions # URL Query String my $ QueryString = $ ENV {"QUERY_STRING"} ... } sub save { ... }
As you can see,
konto.pl
is the dispatcher who receives the requests and calls the appropriate subroutines.
konto.pl
is narrow and has few subroutines - usually only the
action
s related programs. It is noteworthy that for simple tasks such as these no
use CGI:: \u0026lt;something>
is necessary: Read query parameters and access the payload of the incoming and outgoing HTTP message is in CGI so simple that no further Aid packages are necessary.
konto.pl
is of course also very narrow, because it delegates the actual tasks to the class
CsvTableMaintainer
and to a smaller part of the package
MiniJSON
. These program parts are - like all others, for this example required parts of the program - in my github
-Reposoritory
account. If you take the example application will therefore consider in more detail we refer to this repository.
[1] Perhaps I was not looking hard enough or was not satisfied with the found objects.
[2] In addition to the JavaScript framework Prototype by Sam Stephenso that supported me, read JavaScript to write, I use the Date Picker
by Hugo Ortega Fernandez. And - yes, I like the SAP icons!
avoided [3] To Codeduplizierung, he calls for the design of securing the action simply
get_all
on.
0 comments:
Post a Comment