Saturday, October 9, 2010

Birthday Cakes Of Bicycles

table maintenance as a web application written

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].
  • Here I show an implementation for the maintenance interface using JavaScript, which takes over the entire change management on the client. The application consists of a single Web page, the left nor is reloaded. It communicates internally via Ajax requests to the server that has delivered the data and changes to perpetuate. can read
    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;
    newCode transport.responseText.evalJSON = ();

    / / 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 () 
    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
    deleted or contains any cell with 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: 


    / / - - 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
    data loss function () {return $
    ("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
    } 


    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
    strict;
    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