347 lines
10 KiB
HTML
Executable file
347 lines
10 KiB
HTML
Executable file
<!DOCTYPE html>
|
|
<!--
|
|
Copyright 2009 Google Inc.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
-->
|
|
|
|
<!--
|
|
|
|
A simple application showing the use of the web storage portability layer
|
|
code and cache pattern for offline web application.
|
|
|
|
-->
|
|
<html>
|
|
<head>
|
|
<title>SimpleNotes Demo</title>
|
|
<link href="styles.css" rel="stylesheet" type="text/css" />
|
|
<script src="../global_functions.js" language="javascript"
|
|
type="text/javascript"></script>
|
|
<script src="../dbwrapperapi.js" language="javascript"
|
|
type="text/javascript"></script>
|
|
<script src="../dbwrapper_html5.js" language="javascript"
|
|
type="text/javascript"></script>
|
|
<script src="../databasefactory.js" language="javascript"
|
|
type="text/javascript"></script>
|
|
<script src="template.js" language="javascript"
|
|
type="text/javascript"></script>
|
|
<script src="simplenotes.js" language="javascript"
|
|
type="text/javascript"></script>
|
|
</head>
|
|
<body>
|
|
|
|
<div id="list-note" class="screen list-note-screen" >
|
|
<div class="title-bar">Note List</div>
|
|
<div class="top command-bar">
|
|
<button id="view-note-new">New</button>
|
|
</div>
|
|
<div class="status-bar">status bar</div>
|
|
<div class="list-note-container-empty" style="display:none;"></div>
|
|
<div class="list-note-container" style="display:none;">
|
|
<div class="list-note-item">
|
|
<a href="javascript:showNote(%noteKey%);">%subject%</a>
|
|
</div>
|
|
</div>
|
|
<div class="top command-bar">
|
|
<button id="view-note-new">New</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="view-note" class="screen view-note-screen" style="display:none;">
|
|
<div class="title-bar">View Note</div>
|
|
<div class="top command-bar">
|
|
<button id="view-note-back">Back</button>
|
|
<button id="view-note-edit">Edit Note</button>
|
|
</div>
|
|
<div class="status-bar">status bar</div>
|
|
<div class="view-note-container" style="display:none;">
|
|
<div class="subject">%subject%</div>
|
|
<div class="body">%body%</div>
|
|
</div>
|
|
<div class="bottom command-bar">
|
|
<button id="view-note-back">Back</button>
|
|
<button id="view-note-edit">Edit Note</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="edit-note" class="screen edit-note-screen" style="display:none;">
|
|
<div class="title-bar">Edit Note</div>
|
|
<div class="top command-bar">
|
|
<button id="edit-back-save">Save Note</button>
|
|
<button id="edit-back-revert">Revert Note</button>
|
|
</div>
|
|
<div class="status-bar">status bar</div>
|
|
<div>Subject:</div>
|
|
<textarea rows="1" style="width:100%;" id="edit-note-subject"></textarea>
|
|
<br>
|
|
<div>Note:</div>
|
|
<textarea rows="20" style="width:100%;" id="edit-note-body"></textarea>
|
|
<div class="bottom command-bar">
|
|
<button id="edit-back-save">Save Note</button>
|
|
<button id="edit-back-revert">Revert Note</button>
|
|
</div>
|
|
</div>
|
|
|
|
</body>
|
|
<script>
|
|
|
|
/**
|
|
* Tests the given DOM element for a specific CSS class.
|
|
* @param {Object} e A DOM element.
|
|
* @param {string} css A CSS class identifier to match.
|
|
* @return {boolean} true if the element has the CSS class.
|
|
*/
|
|
function hasCssClass(e, css) {
|
|
return e && e.className && e.className.search(css + '( |$)') > -1;
|
|
};
|
|
|
|
/**
|
|
* Finds the parent element of a given element that has
|
|
* the specified CSS class.
|
|
* @param {Object} e A DOM element.
|
|
* @param {string} css A CSS class identifier to match.
|
|
* @param {Object} opt_stop A parent DOM element to stop at.
|
|
* @return {Object} A DOM element parent of e or null.
|
|
*/
|
|
function findParentOfClass(e, css, opt_stop) {
|
|
var stop = opt_stop || document;
|
|
while (e && e != stop && !hasCssClass(e, css)) {
|
|
e = e.parentElement;
|
|
}
|
|
return hasCssClass(e, css) ? e : null;
|
|
};
|
|
|
|
/**
|
|
* Navigates to the note creation screen.
|
|
*/
|
|
function editNote(event) {
|
|
google.logger('editNote: <' + currentNote.subject + '>');
|
|
hideBlock('#edit-note .status-bar');
|
|
|
|
var subject = document.getElementById('edit-note-subject');
|
|
var body = document.getElementById('edit-note-body');
|
|
subject.value = currentNote.subject;
|
|
body.value = currentNote.body;
|
|
|
|
google.logger('end of editNote');
|
|
}
|
|
|
|
/**
|
|
* Saves a note.
|
|
*/
|
|
function saveNote(event) {
|
|
google.logger('saveNote: do database or other activity here');
|
|
// Copy contents from fields and save.
|
|
var subject = document.getElementById('edit-note-subject');
|
|
var body = document.getElementById('edit-note-body');
|
|
|
|
cache.applyUiChange(currentNote.noteKey, subject.value,
|
|
body.value, showNote);
|
|
google.logger('saveNote');
|
|
}
|
|
|
|
/**
|
|
* Abandons the note.
|
|
*/
|
|
function abandonNote(event) {
|
|
google.logger('abandonNote: do database or other activity here');
|
|
showNote(currentNote.noteKey);
|
|
google.logger('abandonNote');
|
|
}
|
|
|
|
/**
|
|
* Prepares to edit a new note.
|
|
*/
|
|
function newNote(event) {
|
|
google.logger('newNote: do database or other activity here');
|
|
alert('not implemented');
|
|
// grab the contents and inject into the database.
|
|
var subject = document.getElementById('edit-note-subject');
|
|
var body = document.getElementById('edit-note-body');
|
|
subject.value = '';
|
|
body.value = '';
|
|
google.logger('newNote');
|
|
}
|
|
|
|
/**
|
|
* Maps button names to customizer functions.
|
|
*/
|
|
var buttonHandlerSpecification = {
|
|
'view-note-new': ['edit-note', newNote],
|
|
'view-note-back': ['list-note', showNoteList],
|
|
'view-note-edit': ['edit-note', editNote],
|
|
'edit-back-save': ['view-note', saveNote],
|
|
'edit-back-revert': ['view-note', abandonNote]
|
|
};
|
|
|
|
/**
|
|
* Hides a block specified by a CSS selector and parent node.
|
|
* @param {string} selector A CSS selector string.
|
|
* @param {Object} opt_el A DOM element.
|
|
*/
|
|
function hideBlock(selector, opt_el) {
|
|
var el = opt_el || document;
|
|
var targetEl = el.querySelector(selector);
|
|
targetEl.style.display = 'none';
|
|
}
|
|
|
|
/**
|
|
* Shows a block specified by a CSS selector and parent node, inserting
|
|
* the specified string as the innerHTML property of the selected block.
|
|
* @param {string} selector A CSS selector
|
|
* @param {string} html String to assign to the innerHTML property.
|
|
* @param {Object} opt_el A DOM element.
|
|
*/
|
|
function showBlock(selector, html, opt_el) {
|
|
var el = opt_el || document;
|
|
var targetEl = el.querySelector(selector);
|
|
if (html) targetEl.innerHTML = html;
|
|
targetEl.style.display = 'block';
|
|
}
|
|
|
|
/**
|
|
* Handles all button events.
|
|
*/
|
|
function buttonHandler(event) {
|
|
google.logger('clicked on: ' + event.target.id);
|
|
|
|
var currentScreen = findParentOfClass(event.target, 'screen');
|
|
var nextScreen = document.getElementById(
|
|
buttonHandlerSpecification[event.target.id][0]);
|
|
var helperFunction = buttonHandlerSpecification[event.target.id][1];
|
|
|
|
// All button handlers have a common implementation.
|
|
// 1. hide current screen
|
|
currentScreen.style.display = 'none';
|
|
|
|
// 2. show new screen
|
|
nextScreen.style.display = 'block';
|
|
|
|
// 3. Activate status
|
|
showBlock('.status-bar', 'Working...', nextScreen);
|
|
|
|
// 4. Call customizer function (which will probably query the model
|
|
// stored in the cache.
|
|
helperFunction(event);
|
|
|
|
// 5. A (possibly asynchronous) callback from the customizer will
|
|
// finish the action by running the appropriate view function.
|
|
google.logger('end of button Handler');
|
|
}
|
|
|
|
/**
|
|
* Call back from a specific JavaScript url to show a specific
|
|
* note.
|
|
* @param {number} noteKey
|
|
* @return {boolean}
|
|
*/
|
|
function showNote(noteKey) {
|
|
hideBlock('#list-note');
|
|
showBlock('#view-note .status-bar', 'Working...');
|
|
showBlock('#view-note');
|
|
cache.getValues('fullnote', [noteKey], renderFullNote);
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Generates HTML for a note and display it.
|
|
* @param {Object} oneNote
|
|
* @param {boolean} complete True if the note has been provided or
|
|
* if an updated note is arriving. (Necessary for future support for
|
|
* sub-note updates.)
|
|
*/
|
|
function renderFullNote(oneNote, complete) {
|
|
google.logger('renderFullNote');
|
|
|
|
showBlock('.view-note-container', noteViewTemplate.process(oneNote));
|
|
if (complete) {
|
|
hideBlock('#view-note .status-bar');
|
|
}
|
|
currentNote = oneNote;
|
|
google.logger('done renderFullNote');
|
|
}
|
|
|
|
/**
|
|
* Generates HTML for a note list and display it.
|
|
* @param {Array.<Object>} noteHeaders
|
|
* @param {boolean} complete True if all in-existence notes that lie
|
|
* in the query range have been provided even if less than what was
|
|
* requested.
|
|
*/
|
|
function renderNoteList(noteHeaders, complete) {
|
|
google.logger('renderNoteList: ' + noteHeaders.length);
|
|
|
|
if (noteHeaders.length == 0) {
|
|
showBlock('.list-note-container-empty', 'No notes');
|
|
} else {
|
|
var notes = noteHeaders.map(function(n) {
|
|
return noteListTemplate.process(n);
|
|
});
|
|
showBlock('.list-note-container', notes.join());
|
|
}
|
|
if (complete) {
|
|
hideBlock('#list-note .status-bar');
|
|
}
|
|
google.logger('done renderNoteList');
|
|
}
|
|
|
|
/**
|
|
* Query for an updated note list.
|
|
*/
|
|
function showNoteList() {
|
|
google.logger('showNoteList');
|
|
cache.getValues('list', [0,20], renderNoteList);
|
|
currentNote = undefined;
|
|
google.logger('end of showNoteList');
|
|
}
|
|
|
|
/**
|
|
* A constructor for the controller. Sets up the UI and
|
|
* queries the cache for initial notelist contents.
|
|
*/
|
|
function createController() {
|
|
google.logger('createController:');
|
|
var buttons = document.querySelectorAll('.command-bar button');
|
|
Array.prototype.forEach.call(buttons, function(b) {
|
|
b.addEventListener('click', buttonHandler);
|
|
});
|
|
google.logger('controller is live');
|
|
showNoteList();
|
|
}
|
|
|
|
google.logger('about to fetch the template');
|
|
var currentNote = undefined;
|
|
|
|
var noteListTemplate = new google.wspl.simplenotes.Template(
|
|
document.querySelector('.list-note-container').innerHTML);
|
|
|
|
var noteViewTemplate = new google.wspl.simplenotes.Template(
|
|
document.querySelector('.view-note-container').innerHTML);
|
|
|
|
// var noteEditTemplate = new google.wspl.simplenotes.Template();
|
|
|
|
google.logger('created the template');
|
|
|
|
// debugging code... tear out...
|
|
// test the template construction...
|
|
// showBlock('.list-note-container', noteListTemplate.process(
|
|
// {noteKey: 123, subject: 'hi rob'}));
|
|
|
|
|
|
google.logger('loaded database');
|
|
var cache = new google.wspl.simplenotes.Cache();
|
|
cache.startCache(createController);
|
|
|
|
google.logger('finished loading page');
|
|
</script>
|
|
</html>
|