4 <title>WebKit HTML 5 SQL Storage Notes Demo</title>
7 font-family: 'Lucida Grande', 'Helvetica', sans-serif;
11 background-color: rgb(255, 240, 70);
16 -webkit-box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.5);
19 .note:hover .closebutton {
25 background-image: url(deleteButton.png);
34 background-image: url(deleteButtonPressed.png);
47 background-color: #db0;
49 border-top: 1px solid #a80;
58 if (window.openDatabase) {
59 db = openDatabase("NoteTest", "1.0", "HTML5 Database API example", 200000);
61 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");
63 alert("Couldn't open the database. Please try with a WebKit nightly with this feature enabled");
74 var note = document.createElement('div');
75 note.className = 'note';
76 note.addEventListener('mousedown', function(e) { return self.onMouseDown(e) }, false);
77 note.addEventListener('click', function() { return self.onNoteClick() }, false);
80 var close = document.createElement('div');
81 close.className = 'closebutton';
82 close.addEventListener('click', function(event) { return self.close(event) }, false);
83 note.appendChild(close);
85 var edit = document.createElement('div');
86 edit.className = 'edit';
87 edit.setAttribute('contenteditable', true);
88 edit.addEventListener('keyup', function() { return self.onKeyUp() }, false);
89 note.appendChild(edit);
90 this.editField = edit;
92 var ts = document.createElement('div');
93 ts.className = 'timestamp';
94 ts.addEventListener('mousedown', function(e) { return self.onMouseDown(e) }, false);
96 this.lastModified = ts;
98 document.body.appendChild(note);
105 if (!("_id" in this))
117 return this.editField.innerHTML;
122 this.editField.innerHTML = x;
127 if (!("_timestamp" in this))
129 return this._timestamp;
134 if (this._timestamp == x)
138 var date = new Date();
139 date.setTime(parseFloat(x));
140 this.lastModified.textContent = modifiedString(date);
145 return this.note.style.left;
150 this.note.style.left = x;
155 return this.note.style.top;
160 this.note.style.top = x;
165 return this.note.style.zIndex;
170 this.note.style.zIndex = x;
173 close: function(event)
175 this.cancelPendingSave();
178 db.transaction(function(tx)
180 tx.executeSql("DELETE FROM WebKitStickyNotes WHERE id = ?", [note.id]);
183 var duration = event.shiftKey ? 2 : .25;
184 this.note.style.webkitTransition = '-webkit-transform ' + duration + 's ease-in, opacity ' + duration + 's ease-in';
185 this.note.offsetTop; // Force style recalc
186 this.note.style.webkitTransformOrigin = "0 0";
187 this.note.style.webkitTransform = 'skew(30deg, 0deg) scale(0)';
188 this.note.style.opacity = '0';
191 setTimeout(function() { document.body.removeChild(self.note) }, duration * 1000);
196 this.cancelPendingSave();
198 this._saveTimer = setTimeout(function() { self.save() }, 200);
201 cancelPendingSave: function()
203 if (!("_saveTimer" in this))
205 clearTimeout(this._saveTimer);
206 delete this._saveTimer;
211 this.cancelPendingSave();
213 if ("dirty" in this) {
214 this.timestamp = new Date().getTime();
219 db.transaction(function (tx)
221 tx.executeSql("UPDATE WebKitStickyNotes SET note = ?, timestamp = ?, left = ?, top = ?, zindex = ? WHERE id = ?", [note.text, note.timestamp, note.left, note.top, note.zIndex, note.id]);
225 saveAsNew: function()
227 this.timestamp = new Date().getTime();
230 db.transaction(function (tx)
232 tx.executeSql("INSERT INTO WebKitStickyNotes (id, note, timestamp, left, top, zindex) VALUES (?, ?, ?, ?, ?, ?)", [note.id, note.text, note.timestamp, note.left, note.top, note.zIndex]);
236 onMouseDown: function(e)
239 this.startX = e.clientX - this.note.offsetLeft;
240 this.startY = e.clientY - this.note.offsetTop;
241 this.zIndex = ++highestZ;
244 if (!("mouseMoveHandler" in this)) {
245 this.mouseMoveHandler = function(e) { return self.onMouseMove(e) }
246 this.mouseUpHandler = function(e) { return self.onMouseUp(e) }
249 document.addEventListener('mousemove', this.mouseMoveHandler, true);
250 document.addEventListener('mouseup', this.mouseUpHandler, true);
255 onMouseMove: function(e)
257 if (this != captured)
260 this.left = e.clientX - this.startX + 'px';
261 this.top = e.clientY - this.startY + 'px';
265 onMouseUp: function(e)
267 document.removeEventListener('mousemove', this.mouseMoveHandler, true);
268 document.removeEventListener('mouseup', this.mouseUpHandler, true);
274 onNoteClick: function(e)
276 this.editField.focus();
277 getSelection().collapseToEnd();
289 db.transaction(function(tx) {
290 tx.executeSql("SELECT COUNT(*) FROM WebkitStickyNotes", [], function(result) {
292 }, function(tx, error) {
293 tx.executeSql("CREATE TABLE WebKitStickyNotes (id REAL UNIQUE, note TEXT, timestamp REAL, left TEXT, top TEXT, zindex REAL)", [], function(result) {
302 db.transaction(function(tx) {
303 tx.executeSql("SELECT id, note, timestamp, left, top, zindex FROM WebKitStickyNotes", [], function(tx, result) {
304 for (var i = 0; i < result.rows.length; ++i) {
305 var row = result.rows.item(i);
306 var note = new Note();
308 note.text = row['note'];
309 note.timestamp = row['timestamp'];
310 note.left = row['left'];
311 note.top = row['top'];
312 note.zIndex = row['zindex'];
314 if (row['id'] > highestId)
315 highestId = row['id'];
316 if (row['zindex'] > highestZ)
317 highestZ = row['zindex'];
320 if (!result.rows.length)
322 }, function(tx, error) {
323 alert('Failed to retrieve notes from database - ' + error.message);
329 function modifiedString(date)
331 return 'Last Modified: ' + date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ' ' + date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
336 var note = new Note();
337 note.id = ++highestId;
338 note.timestamp = new Date().getTime();
339 note.left = Math.round(Math.random() * 400) + 'px';
340 note.top = Math.round(Math.random() * 500) + 'px';
341 note.zIndex = ++highestZ;
345 addEventListener('load', loaded, false);
349 <p>This page demonstrates the use of the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/section-sql.html">HTML 5 Client-side Database Storage API</a>. Any notes you create will be saved in a database on your local hard drive, and will be reloaded from that database the next time you visit this page. To try it out, use a <a href="http://nightly.webkit.org/">WebKit Nightly Build</a>.</p>
350 <button onclick="newNote()">New Note</button>