www.webOShelp.net

Get the latest on:webOS Developers' RSS FeedwebOS Facebook page webOS Twitter Feed

Home Getting Started with webOS webOS HTML5 Database Storage Tutorial - Prototyping in webOS

webOS HTML5 Database Storage Tutorial - Prototyping in webOS

Article Index
webOS HTML5 Database Storage Tutorial
The Constructor Function
Prototyping in webOS
Finishing up
All Pages

Prototyping

Here's the full prototype function. Have a look at it in its entirety, then we'll break it down.

Note.prototype = {

    get id()
    {
        if (!("_id" in this))
            this._id = 0;
        return this._id;
    },

    set id(x)
    {
        this._id = x;
    },

    get text()
    {
        return this.editField.innerHTML;
    },

    set text(x)
    {
        this.editField.innerHTML = x;
    },

    get timestamp()
    {
        if (!("_timestamp" in this))
            this._timestamp = 0;
        return this._timestamp;
    },

    set timestamp(x)
    {
        if (this._timestamp == x)
            return;

        this._timestamp = x;
        var date = new Date();
        date.setTime(parseFloat(x));
        this.lastModified.textContent = modifiedString(date);
    },

    get left()
    {
        return this.note.style.left;
    },

    set left(x)
    {
        this.note.style.left = x;
    },

    get top()
    {
        return this.note.style.top;
    },

    set top(x)
    {
        this.note.style.top = x;
    },

    get zIndex()
    {
        return this.note.style.zIndex;
    },

    set zIndex(x)
    {
        this.note.style.zIndex = x;
    },

    close: function(event)
    {
        this.cancelPendingSave();

        var note = this;
        db.transaction(function(tx)
        {
            tx.executeSql("DELETE FROM WebKitStickyNotes WHERE id = ?", [note.id]);
        });
        
        var duration = event.shiftKey ? 2 : .25;
        this.note.style.webkitTransition = '-webkit-transform ' + duration + 's ease-in, opacity ' + duration + 's ease-in';
        this.note.offsetTop; // Force style recalc
        this.note.style.webkitTransformOrigin = "0 0";
        this.note.style.webkitTransform = 'skew(30deg, 0deg) scale(0)';
        this.note.style.opacity = '0';

        var self = this;
        setTimeout(function() { document.body.removeChild(self.note) }, duration * 1000);
    },

    saveSoon: function()
    {
        this.cancelPendingSave();
        var self = this;
        this._saveTimer = setTimeout(function() { self.save() }, 200);
    },

    cancelPendingSave: function()
    {
        if (!("_saveTimer" in this))
            return;
        clearTimeout(this._saveTimer);
        delete this._saveTimer;
    },

    save: function()
    {
        this.cancelPendingSave();

        if ("dirty" in this) {
            this.timestamp = new Date().getTime();
            delete this.dirty;
        }

        var note = this;
        db.transaction(function (tx)
        {
            tx.executeSql("UPDATE WebKitStickyNotes SET note = ?, timestamp = ?, left = ?, top = ?, zindex = ? WHERE id = ?", [note.text, note.timestamp, note.left, note.top, note.zIndex, note.id]);
        });
    },

    saveAsNew: function()
    {
        this.timestamp = new Date().getTime();
        
        var note = this;
        db.transaction(function (tx) 
        {
            tx.executeSql("INSERT INTO WebKitStickyNotes (id, note, timestamp, left, top, zindex) VALUES (?, ?, ?, ?, ?, ?)", [note.id, note.text, note.timestamp, note.left, note.top, note.zIndex]);
        }); 
    },

    onMouseDown: function(e)
    {
        captured = this;
        this.startX = e.clientX - this.note.offsetLeft;
        this.startY = e.clientY - this.note.offsetTop;
        this.zIndex = ++highestZ;

        var self = this;
        if (!("mouseMoveHandler" in this)) {
            this.mouseMoveHandler = function(e) { return self.onMouseMove(e) }
            this.mouseUpHandler = function(e) { return self.onMouseUp(e) }
        }

        document.addEventListener('mousemove', this.mouseMoveHandler, true);
        document.addEventListener('mouseup', this.mouseUpHandler, true);

        return false;
    },

    onMouseMove: function(e)
    {
        if (this != captured)
            return true;

        this.left = e.clientX - this.startX + 'px';
        this.top = e.clientY - this.startY + 'px';
        return false;
    },

    onMouseUp: function(e)
    {
        document.removeEventListener('mousemove', this.mouseMoveHandler, true);
        document.removeEventListener('mouseup', this.mouseUpHandler, true);

        this.save();
        return false;
    },

    onNoteClick: function(e)
    {
        this.editField.focus();
        getSelection().collapseToEnd();
    },

    onKeyUp: function()
    {
        this.dirty = true;
        this.saveSoon();
    },
}

Well, that was a handful.  Let's start from the very beginning:

Note.prototype = {

This line declares that we're going to be attaching methods to the Note object that we defined earlier.

    get id()
    {
        if (!("_id" in this))
            this._id = 0;
        return this._id;
    },

    set id(x)
    {
        this._id = x;
    },

    get text()
    {
        return this.editField.innerHTML;
    },

    set text(x)
    {
        this.editField.innerHTML = x;
    },

    get timestamp()
    {
        if (!("_timestamp" in this))
            this._timestamp = 0;
        return this._timestamp;
    },

    set timestamp(x)
    {
        if (this._timestamp == x)
            return;

        this._timestamp = x;
        var date = new Date();
        date.setTime(parseFloat(x));
        this.lastModified.textContent = modifiedString(date);
    },

    get left()
    {
        return this.note.style.left;
    },

    set left(x)
    {
        this.note.style.left = x;
    },

    get top()
    {
        return this.note.style.top;
    },

    set top(x)
    {
        this.note.style.top = x;
    },

    get zIndex()
    {
        return this.note.style.zIndex;
    },

    set zIndex(x)
    {
        this.note.style.zIndex = x;
    },

These are called "getter" and "setter" methods. Here we're defining methods for id, text, timestamp, left, top, and zIndex.  These functions allow us to externally access and write to a Note's internal data by using commands like note.left, note.text, etc.  Some of these are visible properties of the Note, such as left and top.  Getting the left value of a note returns the x-coordinate of its left edge in the browser window.  Setting the left value will actually move the note to the specified x-coordinate.  Similarly, the setting the text value changes the text that is displayed in the note, while getting the text value retrieves the text that the user has typed into the note.

close: function(event)
    {
        this.cancelPendingSave();

        var note = this;
        db.transaction(function(tx)
        {
            tx.executeSql("DELETE FROM WebKitStickyNotes WHERE id = ?", [note.id]);
        });
        
        var duration = event.shiftKey ? 2 : .25;
        this.note.style.webkitTransition = '-webkit-transform ' + duration + 's ease-in, opacity ' + duration + 's ease-in';
        this.note.offsetTop; // Force style recalc
        this.note.style.webkitTransformOrigin = "0 0";
        this.note.style.webkitTransform = 'skew(30deg, 0deg) scale(0)';
        this.note.style.opacity = '0';

        var self = this;
        setTimeout(function() { document.body.removeChild(self.note) }, duration * 1000);
    },

This function is called when a user closes a note.  Here we've got a database transaction:

        db.transaction(function(tx)
        {
            tx.executeSql("DELETE FROM WebKitStickyNotes WHERE id = ?", [note.id]);
        });

Here we're defining an anonymous function, and passing this function in to the db.transaction method.  The db.transaction method will then use the function we've passed in as it manages and executes the database transaction.  The function defines a simple sql statement that deletes a note from the WebKitStickyNotes table in the database.  "What? Where did that table come from?".  This table actually gets created in the loaded() function we'll take a look at later. :)

 

    saveSoon: function()
    {
        this.cancelPendingSave();
        var self = this;
        this._saveTimer = setTimeout(function() { self.save() }, 200);
    },
    cancelPendingSave: function()
    {
        if (!("_saveTimer" in this))
            return;
        clearTimeout(this._saveTimer);
        delete this._saveTimer;
    },

These two functions manage the saving of the notes.  The first function gets called every time the user types a character into a note.  The cancelPendingSave() function (which is also called every time a user types a character) resets a 200 millisecond timer on the save action. The net function of these two methods is to call the save() function to save the note to the database if the user hasn't pressed a key within the last 200 milliseconds.

 

    save: function()
    {
        this.cancelPendingSave();

        if ("dirty" in this) {
            this.timestamp = new Date().getTime();
            delete this.dirty;
        }

        var note = this;
        db.transaction(function (tx)
        {
            tx.executeSql("UPDATE WebKitStickyNotes SET note = ?, timestamp = ?, left = ?, top = ?, zindex = ? WHERE id = ?", [note.text, note.timestamp, note.left, note.top, note.zIndex, note.id]);
        });
    },

This function saves a note's contents to the database.  If dirty exists, the timestamp of the note gets updated before the save.  The db function then UPDATEs the note's record in the database.  The next function creates a record for new notes. 

saveAsNew: function()
    {
        this.timestamp = new Date().getTime();
        
        var note = this;
        db.transaction(function (tx) 
        {
            tx.executeSql("INSERT INTO WebKitStickyNotes (id, note, timestamp, left, top, zindex) VALUES (?, ?, ?, ?, ?, ?)", [note.id, note.text, note.timestamp, note.left, note.top, note.zIndex]);
        }); 
    },

 

This function creates a new note record in the table WebKitStickyNotes and is executed whenever the "New Note" button is clicked.  This means that any note you interact with already has a record in the database, so when the save() function is called, the record only needs to be updated.

 

    onMouseDown: function(e)
    {
        captured = this;
        this.startX = e.clientX - this.note.offsetLeft;
        this.startY = e.clientY - this.note.offsetTop;
        this.zIndex = ++highestZ;

        var self = this;
        if (!("mouseMoveHandler" in this)) {
            this.mouseMoveHandler = function(e) { return self.onMouseMove(e) }
            this.mouseUpHandler = function(e) { return self.onMouseUp(e) }
        }

        document.addEventListener('mousemove', this.mouseMoveHandler, true);
        document.addEventListener('mouseup', this.mouseUpHandler, true);

        return false;
    },

    onMouseMove: function(e)
    {
        if (this != captured)
            return true;

        this.left = e.clientX - this.startX + 'px';
        this.top = e.clientY - this.startY + 'px';
        return false;
    },

    onMouseUp: function(e)
    {
        document.removeEventListener('mousemove', this.mouseMoveHandler, true);
        document.removeEventListener('mouseup', this.mouseUpHandler, true);

        this.save();
        return false;
    },

 

These functions manage the dragging of a note around on the screen.  Whether the drag and drop interaction in webOS works the same way remains to be seen, but webOS does support dragging and dropping.

 

    onNoteClick: function(e)
    {
        this.editField.focus();
        getSelection().collapseToEnd();
    },

 

This function is executed whenever a user clicks a note.  It brings the clicked note into focus and places the cursor at the end of the text.

 

    onKeyUp: function()
    {
        this.dirty = true;
        this.saveSoon();
    },

 

This function is executed every time a user presses a key.

That covers the Note prototype.  In the next section, we'll go through the remaining functions.



 

18 Comments

Feed
  1. Really bad tutorial, the subject, the HTML 5 databse, is drowning in a load of unrelated code. Any code not strictly related to the topic should be keept to a minimum.
  2. Couldn't agree more with Jacob C.M.A.
  3. Contrary to the other comments left above ^ I thought this tutorial was well thought out and well executed. It covered the basics as well as some advanced techniques for working with HTML5 databases.

    The above comments are clearly the product of uneducated users. If they understood HTML5 db's and the webOS they would know that javascript (that so called "unrelated code") does everything as far as the database interaction and user interaction goes and therefore is, not only related, but necessary to make proper use of the database structure and apply it to both the webOS platform and the web in general.

    Kudos to Mr. Ken Young for a great tutorial, I have learned many new things from this article and appreciate the time he took to write it. Also, I apologize for the aforementioned flaming of users, though quite rude I deemed it necessary in order to maintain my sanity and vent some frustration...
  4. Though this is hardly worth being called a "tutorial" and has very little to do with WebOS, it is interesting to read. I also tried just copy-pasting the complete HTML from the webkit app in a WebOS SDK application, simply in the index.html, and it works. Kindof. Can't create new notes, but the one note works.
  5. Unfortunately, this is not a tutorial. In my opinion, this is just a copy and paste off of webkit Sticky Notes Demo. There is nothing here that documents any HTML 5 Database methods and usage. And to make it worse you call it aq "Web OS" tutorial? Like you said it yourself, you haven't even tried WebOS
  6. Hi
    is there any import files such as jar or any files for using html5 Palm WebOS. ?

    where will use the above code

    var db;

    try {
    if (window.openDatabase) {
    db = openDatabase("NoteTest", "1.0", "HTML5 Database API example", 200000);
    if (!db)
    alert("Failed to open the database on disk. This is probably because the version was bad or there is not enough space left in this domain's quota");
    } else
    alert("Couldn't open the database. Please try with a WebKit nightly with this feature enabled");
    } catch(err) { }

    html file or js file..?
    how to call and access database connection ..?
    is there any sample application plz send me some samples...
  7. How about updating this? Ken, your note at the end said you are going to do that....I'd love to see it. Thanks!
  8. I think that the tutorial explains properly the webstorage standard, thanks for it, also i have just one question, where is the database stored ? could i copy it to other place with the webkit enabled ?

    is possible to access the temporally database and copy to other place?

    thanks
  9. I really liked this tutorial. It helped me understand how to make a database work. I have a couple recomendations for the author:
    you left out just a couple of lines that a beginner might not see that you left out. By the way the code at the beginner was placed it was not clear that you need this between the styles and the javascript at the beginning:


    and also left this out at the end before the paragraph:



    plus 2 more lines:


    I would like to know what the tx is that is being passed in this part:
    db.transaction(function(tx) {
    it is not clear from the tutorial.
    also explain what this line means:
    if (!("_saveTimer" in this))
    it looks for a method called _saveTimer attached to self ( or this )
    everything else made sense. And what does this mean:
    ++highestZ;
    I would guess that it does the same as highestZ++; I just never knew you could reverse it.
    Thanks for the great lesson on html5!
  10. remove the coment that is above. It was a mistake because i needed to encode the html.
    I really liked this tutorial. It helped me understand how to make a database work. I have a couple recomendations for the author:
    you left out just a couple of lines that a beginner might not see that you left out. By the way the code at the beginner was placed it was not clear that you need this between the styles and the javascript at the beginning:


    and also left this out at the end before the paragraph:



    plus 2 more lines:


    I would like to know what the tx is that is being passed in this part:
    db.transaction(function(tx) {
    it is not clear from the tutorial.
    also explain what this line means:
    if (!("_saveTimer" in this))
    it looks for a method called _saveTimer attached to self ( or this )
    everything else made sense. And what does this mean:
    ++highestZ;
    I would guess that it does the same as highestZ++; I just never knew you could reverse it.
    Thanks for the great lesson on html5!
  11. sorry, remove the 2 posts above so this one should show the html correctly
    I really liked this tutorial. It helped me understand how to make a database work. I have a couple recomendations for the author:
    you left out just a couple of lines that a beginner might not see that you left out. By the way the code at the beginner was placed it was not clear that you need this between the styles and the javascript at the beginning:

    and also left this out at the end before the paragraph:

    plus 2 more lines:


    I would like to know what the tx is that is being passed in this part:
    db.transaction(function(tx) {
    it is not clear from the tutorial.
  12. the comment I was trying to post wouldn't allow me to show any kind of html code so i will leave the angle brackets out. remove all comments above this please.

    I really liked this tutorial. It helped me understand how to make a database work. I have a couple recomendations for the author:
    you left out just a couple of lines that a beginner might not see that you left out. By the way the code at the beginner was placed it was not clear that you need this between the styles and the javascript at the beginning:
    end style tag (no angle bracket because the synax is not allowed here in comments)
    script tag
    and also left this out at the end before the paragraph:
    script tag
    end head tag
    body tag
    plus 2 more lines at the very end of code:
    end body tag
    end html tag

    I would like to know what the tx is that is being passed in this part:
    db.transaction(function(tx) {
    it is not clear from the tutorial.
  13. it won't allow a comment too long so I split it into a second part
    also explain what this line means:
    if (!("_saveTimer" in this))
    it looks for a method called _saveTimer attached to self ( or this )
    everything else made sense. And what does this mean:
    ++highestZ;
    I would guess that it does the same as highestZ++; I just never knew you could reverse it.
    Thanks for the great lesson on html5!
  14. Hey Mike, thanks for the comments and sticking with it even though the comments system doesn't seem to want to allow HTML code. I'll need to look into that, because the ability to post sample code is pretty huge on a site like this.

    I've been way behind updating the site because of other things going on (e.g. getting a job that pays the bills!), but I'm hoping to get back to it soon!
  15. I like window.openDatabase(). A partly-developed demo is at: https://www.thebrentc.net/programs/db.html
  16. Thank you Ken. I feel as though I have been on the far outskirts of the coding vortex for some time now.
    Lately I've felt as if I am closing in on the center, slowly but surely. Your tutorial has given me a hefty nudge in that direction and the broad brush was exactly what I needed.
    You cleared up a number of those 'I think I know, sorta, kinda...' things that have been bugging me.
    Sincerely,
    Michael
  17. OK, this is a fairly terrible "tutorial." It skips vital steps like putting in script tags, it ignores errors if it won't window.openDatabase, over all poor quality.
  18. I think it might be better to create the table using: "CREATE TABLE IF NOT EXISTS table_name". An exception might be thrown for reasons other than the table not existing.

Add Comment


    • >:o
    • :-[
    • :'(
    • :-(
    • :-D
    • :-*
    • :-)
    • :P
    • :\
    • 8-)
    • ;-)