middleman 2.0.9.pre.2-x86-mingw32 → 2.0.9.pre.3-x86-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +9 -0
- data/features/builder.feature +6 -0
- data/features/data.feature +16 -1
- data/features/fonts.feature +11 -0
- data/features/relative_assets.feature +8 -2
- data/features/step_definitions/middleman_steps.rb +9 -2
- data/fixtures/data-app/config.rb +3 -0
- data/fixtures/data-app/data/pages.yml +6 -0
- data/fixtures/data-app/source/index.html.haml +1 -0
- data/fixtures/data-app/source/layout.haml +3 -0
- data/fixtures/fonts-app/config.rb +0 -0
- data/fixtures/fonts-app/source/fonts/StMarie-Thin.otf +0 -0
- data/fixtures/fonts-app/source/stylesheets/fonts.css.sass +3 -0
- data/fixtures/glob-app/config.rb +1 -0
- data/fixtures/glob-app/source/index.html.haml +6 -0
- data/fixtures/glob-app/source/stylesheets/site.css.sass +1 -0
- data/fixtures/test-app/config.rb +1 -0
- data/fixtures/test-app/data/test2.json +4 -0
- data/fixtures/test-app/source/data3.html.erb +1 -0
- data/lib/middleman/base.rb +8 -3
- data/lib/middleman/builder.rb +61 -22
- data/lib/middleman/cli.rb +2 -1
- data/lib/middleman/core_extensions/assets.rb +1 -1
- data/lib/middleman/core_extensions/compass.rb +6 -2
- data/lib/middleman/core_extensions/data.rb +20 -3
- data/lib/middleman/templates/html5.rb +1 -0
- data/lib/middleman/templates/mobile.rb +17 -0
- data/lib/middleman/templates/mobile/source/404.html +38 -0
- data/lib/middleman/templates/mobile/source/README.markdown +64 -0
- data/lib/middleman/templates/mobile/source/crossdomain.xml +25 -0
- data/lib/middleman/templates/mobile/source/css/style.css +236 -0
- data/lib/middleman/templates/mobile/source/default.appcache +17 -0
- data/lib/middleman/templates/mobile/source/humans.txt +43 -0
- data/lib/middleman/templates/mobile/source/img/h/apple-touch-icon.png +0 -0
- data/lib/middleman/templates/mobile/source/img/h/splash.png +0 -0
- data/lib/middleman/templates/mobile/source/img/l/apple-touch-icon-precomposed.png +0 -0
- data/lib/middleman/templates/mobile/source/img/l/apple-touch-icon.png +0 -0
- data/lib/middleman/templates/mobile/source/img/l/splash.png +0 -0
- data/lib/middleman/templates/mobile/source/img/m/apple-touch-icon.png +0 -0
- data/lib/middleman/templates/mobile/source/index.html +95 -0
- data/lib/middleman/templates/mobile/source/js/libs/jquery-1.5.1.js +8316 -0
- data/lib/middleman/templates/mobile/source/js/libs/jquery-1.5.1.min.js +16 -0
- data/lib/middleman/templates/mobile/source/js/libs/modernizr-custom.js +14 -0
- data/lib/middleman/templates/mobile/source/js/libs/respond.min.js +7 -0
- data/lib/middleman/templates/mobile/source/js/mylibs/helper.js +147 -0
- data/lib/middleman/templates/mobile/source/js/script.js +0 -0
- data/lib/middleman/templates/mobile/source/robots.txt +5 -0
- data/lib/middleman/templates/mobile/source/sitemap.xml +10 -0
- data/lib/middleman/templates/mobile/source/test/index.html +31 -0
- data/lib/middleman/templates/mobile/source/test/qunit/qunit.css +148 -0
- data/lib/middleman/templates/mobile/source/test/qunit/qunit.js +1265 -0
- data/lib/middleman/templates/mobile/source/test/tests.js +26 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/Readme.PDF +0 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/aspx/aspx1.snippet +31 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/aspx/aspx2.snippet +2 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/aspx/ga.aspx +195 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/aspx/sample.aspx +44 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/jsp/ga.jsp +225 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/jsp/jsp1.snippet +35 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/jsp/jsp2.snippet +2 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/jsp/sample.jsp +51 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/php/ga.php +176 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/php/php1.snippet +30 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/php/php2.snippet +4 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/php/sample.php +44 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/pl/ga.pl +195 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/pl/perl1.snippet +27 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/pl/perl2.snippet +1 -0
- data/lib/middleman/templates/mobile/source/tools/googleanalyticsformobile/pl/sample.pl +38 -0
- data/lib/middleman/templates/mobile/source/tools/mobile-bookmark-bubble/COPYING +202 -0
- data/lib/middleman/templates/mobile/source/tools/mobile-bookmark-bubble/bookmark_bubble.js +559 -0
- data/lib/middleman/templates/mobile/source/tools/mobile-bookmark-bubble/example/example.html +43 -0
- data/lib/middleman/templates/mobile/source/tools/mobile-bookmark-bubble/example/example.js +57 -0
- data/lib/middleman/templates/mobile/source/tools/mobile-bookmark-bubble/images/arrow.png +0 -0
- data/lib/middleman/templates/mobile/source/tools/mobile-bookmark-bubble/images/close.png +0 -0
- data/lib/middleman/templates/mobile/source/tools/mobile-bookmark-bubble/images/generate_base64_images +33 -0
- data/lib/middleman/templates/mobile/source/tools/mobile-bookmark-bubble/images/icon_calendar.png +0 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/README +27 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/databasefactory.js +45 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/dbworker.js +324 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/dbworker_test.html +393 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/dbworkerstarter.js +32 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/dbwrapper_gears.js +595 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/dbwrapper_gears_test.html +404 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/dbwrapper_html5.js +203 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/dbwrapper_html5_test.html +468 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/dbwrapperapi.js +202 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/dbwrapperapi_test.html +51 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/gears_resultset.js +71 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/gears_resultset_test.html +86 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/gears_transaction.js +196 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/gears_transaction_test.html +221 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/gearsutils.js +94 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/gearsutils_test.html +84 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/global_functions.js +72 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/simplenotes/index.html +347 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/simplenotes/simplenotes.js +503 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/simplenotes/styles.css +66 -0
- data/lib/middleman/templates/mobile/source/tools/wspl/simplenotes/template.js +75 -0
- data/lib/middleman/version.rb +1 -1
- data/middleman-x86-mingw32.gemspec +0 -1
- data/middleman.gemspec +3 -2
- metadata +103 -6
- data/lib/middleman/config.ru +0 -2
- data/lib/middleman/features/tiny_src.rb +0 -11
@@ -0,0 +1,347 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<!--
|
3
|
+
Copyright 2009 Google Inc.
|
4
|
+
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
you may not use this file except in compliance with the License.
|
7
|
+
You may obtain a copy of the License at
|
8
|
+
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
See the License for the specific language governing permissions and
|
15
|
+
limitations under the License.
|
16
|
+
-->
|
17
|
+
|
18
|
+
<!--
|
19
|
+
|
20
|
+
A simple application showing the use of the web storage portability layer
|
21
|
+
code and cache pattern for offline web application.
|
22
|
+
|
23
|
+
-->
|
24
|
+
<html>
|
25
|
+
<head>
|
26
|
+
<title>SimpleNotes Demo</title>
|
27
|
+
<link href="styles.css" rel="stylesheet" type="text/css" />
|
28
|
+
<script src="../global_functions.js" language="javascript"
|
29
|
+
type="text/javascript"></script>
|
30
|
+
<script src="../dbwrapperapi.js" language="javascript"
|
31
|
+
type="text/javascript"></script>
|
32
|
+
<script src="../dbwrapper_html5.js" language="javascript"
|
33
|
+
type="text/javascript"></script>
|
34
|
+
<script src="../databasefactory.js" language="javascript"
|
35
|
+
type="text/javascript"></script>
|
36
|
+
<script src="template.js" language="javascript"
|
37
|
+
type="text/javascript"></script>
|
38
|
+
<script src="simplenotes.js" language="javascript"
|
39
|
+
type="text/javascript"></script>
|
40
|
+
</head>
|
41
|
+
<body>
|
42
|
+
|
43
|
+
<div id="list-note" class="screen list-note-screen" >
|
44
|
+
<div class="title-bar">Note List</div>
|
45
|
+
<div class="top command-bar">
|
46
|
+
<button id="view-note-new">New</button>
|
47
|
+
</div>
|
48
|
+
<div class="status-bar">status bar</div>
|
49
|
+
<div class="list-note-container-empty" style="display:none;"></div>
|
50
|
+
<div class="list-note-container" style="display:none;">
|
51
|
+
<div class="list-note-item">
|
52
|
+
<a href="javascript:showNote(%noteKey%);">%subject%</a>
|
53
|
+
</div>
|
54
|
+
</div>
|
55
|
+
<div class="top command-bar">
|
56
|
+
<button id="view-note-new">New</button>
|
57
|
+
</div>
|
58
|
+
</div>
|
59
|
+
|
60
|
+
<div id="view-note" class="screen view-note-screen" style="display:none;">
|
61
|
+
<div class="title-bar">View Note</div>
|
62
|
+
<div class="top command-bar">
|
63
|
+
<button id="view-note-back">Back</button>
|
64
|
+
<button id="view-note-edit">Edit Note</button>
|
65
|
+
</div>
|
66
|
+
<div class="status-bar">status bar</div>
|
67
|
+
<div class="view-note-container" style="display:none;">
|
68
|
+
<div class="subject">%subject%</div>
|
69
|
+
<div class="body">%body%</div>
|
70
|
+
</div>
|
71
|
+
<div class="bottom command-bar">
|
72
|
+
<button id="view-note-back">Back</button>
|
73
|
+
<button id="view-note-edit">Edit Note</button>
|
74
|
+
</div>
|
75
|
+
</div>
|
76
|
+
|
77
|
+
<div id="edit-note" class="screen edit-note-screen" style="display:none;">
|
78
|
+
<div class="title-bar">Edit Note</div>
|
79
|
+
<div class="top command-bar">
|
80
|
+
<button id="edit-back-save">Save Note</button>
|
81
|
+
<button id="edit-back-revert">Revert Note</button>
|
82
|
+
</div>
|
83
|
+
<div class="status-bar">status bar</div>
|
84
|
+
<div>Subject:</div>
|
85
|
+
<textarea rows="1" style="width:100%;" id="edit-note-subject"></textarea>
|
86
|
+
<br>
|
87
|
+
<div>Note:</div>
|
88
|
+
<textarea rows="20" style="width:100%;" id="edit-note-body"></textarea>
|
89
|
+
<div class="bottom command-bar">
|
90
|
+
<button id="edit-back-save">Save Note</button>
|
91
|
+
<button id="edit-back-revert">Revert Note</button>
|
92
|
+
</div>
|
93
|
+
</div>
|
94
|
+
|
95
|
+
</body>
|
96
|
+
<script>
|
97
|
+
|
98
|
+
/**
|
99
|
+
* Tests the given DOM element for a specific CSS class.
|
100
|
+
* @param {Object} e A DOM element.
|
101
|
+
* @param {string} css A CSS class identifier to match.
|
102
|
+
* @return {boolean} true if the element has the CSS class.
|
103
|
+
*/
|
104
|
+
function hasCssClass(e, css) {
|
105
|
+
return e && e.className && e.className.search(css + '( |$)') > -1;
|
106
|
+
};
|
107
|
+
|
108
|
+
/**
|
109
|
+
* Finds the parent element of a given element that has
|
110
|
+
* the specified CSS class.
|
111
|
+
* @param {Object} e A DOM element.
|
112
|
+
* @param {string} css A CSS class identifier to match.
|
113
|
+
* @param {Object} opt_stop A parent DOM element to stop at.
|
114
|
+
* @return {Object} A DOM element parent of e or null.
|
115
|
+
*/
|
116
|
+
function findParentOfClass(e, css, opt_stop) {
|
117
|
+
var stop = opt_stop || document;
|
118
|
+
while (e && e != stop && !hasCssClass(e, css)) {
|
119
|
+
e = e.parentElement;
|
120
|
+
}
|
121
|
+
return hasCssClass(e, css) ? e : null;
|
122
|
+
};
|
123
|
+
|
124
|
+
/**
|
125
|
+
* Navigates to the note creation screen.
|
126
|
+
*/
|
127
|
+
function editNote(event) {
|
128
|
+
google.logger('editNote: <' + currentNote.subject + '>');
|
129
|
+
hideBlock('#edit-note .status-bar');
|
130
|
+
|
131
|
+
var subject = document.getElementById('edit-note-subject');
|
132
|
+
var body = document.getElementById('edit-note-body');
|
133
|
+
subject.value = currentNote.subject;
|
134
|
+
body.value = currentNote.body;
|
135
|
+
|
136
|
+
google.logger('end of editNote');
|
137
|
+
}
|
138
|
+
|
139
|
+
/**
|
140
|
+
* Saves a note.
|
141
|
+
*/
|
142
|
+
function saveNote(event) {
|
143
|
+
google.logger('saveNote: do database or other activity here');
|
144
|
+
// Copy contents from fields and save.
|
145
|
+
var subject = document.getElementById('edit-note-subject');
|
146
|
+
var body = document.getElementById('edit-note-body');
|
147
|
+
|
148
|
+
cache.applyUiChange(currentNote.noteKey, subject.value,
|
149
|
+
body.value, showNote);
|
150
|
+
google.logger('saveNote');
|
151
|
+
}
|
152
|
+
|
153
|
+
/**
|
154
|
+
* Abandons the note.
|
155
|
+
*/
|
156
|
+
function abandonNote(event) {
|
157
|
+
google.logger('abandonNote: do database or other activity here');
|
158
|
+
showNote(currentNote.noteKey);
|
159
|
+
google.logger('abandonNote');
|
160
|
+
}
|
161
|
+
|
162
|
+
/**
|
163
|
+
* Prepares to edit a new note.
|
164
|
+
*/
|
165
|
+
function newNote(event) {
|
166
|
+
google.logger('newNote: do database or other activity here');
|
167
|
+
alert('not implemented');
|
168
|
+
// grab the contents and inject into the database.
|
169
|
+
var subject = document.getElementById('edit-note-subject');
|
170
|
+
var body = document.getElementById('edit-note-body');
|
171
|
+
subject.value = '';
|
172
|
+
body.value = '';
|
173
|
+
google.logger('newNote');
|
174
|
+
}
|
175
|
+
|
176
|
+
/**
|
177
|
+
* Maps button names to customizer functions.
|
178
|
+
*/
|
179
|
+
var buttonHandlerSpecification = {
|
180
|
+
'view-note-new': ['edit-note', newNote],
|
181
|
+
'view-note-back': ['list-note', showNoteList],
|
182
|
+
'view-note-edit': ['edit-note', editNote],
|
183
|
+
'edit-back-save': ['view-note', saveNote],
|
184
|
+
'edit-back-revert': ['view-note', abandonNote]
|
185
|
+
};
|
186
|
+
|
187
|
+
/**
|
188
|
+
* Hides a block specified by a CSS selector and parent node.
|
189
|
+
* @param {string} selector A CSS selector string.
|
190
|
+
* @param {Object} opt_el A DOM element.
|
191
|
+
*/
|
192
|
+
function hideBlock(selector, opt_el) {
|
193
|
+
var el = opt_el || document;
|
194
|
+
var targetEl = el.querySelector(selector);
|
195
|
+
targetEl.style.display = 'none';
|
196
|
+
}
|
197
|
+
|
198
|
+
/**
|
199
|
+
* Shows a block specified by a CSS selector and parent node, inserting
|
200
|
+
* the specified string as the innerHTML property of the selected block.
|
201
|
+
* @param {string} selector A CSS selector
|
202
|
+
* @param {string} html String to assign to the innerHTML property.
|
203
|
+
* @param {Object} opt_el A DOM element.
|
204
|
+
*/
|
205
|
+
function showBlock(selector, html, opt_el) {
|
206
|
+
var el = opt_el || document;
|
207
|
+
var targetEl = el.querySelector(selector);
|
208
|
+
if (html) targetEl.innerHTML = html;
|
209
|
+
targetEl.style.display = 'block';
|
210
|
+
}
|
211
|
+
|
212
|
+
/**
|
213
|
+
* Handles all button events.
|
214
|
+
*/
|
215
|
+
function buttonHandler(event) {
|
216
|
+
google.logger('clicked on: ' + event.target.id);
|
217
|
+
|
218
|
+
var currentScreen = findParentOfClass(event.target, 'screen');
|
219
|
+
var nextScreen = document.getElementById(
|
220
|
+
buttonHandlerSpecification[event.target.id][0]);
|
221
|
+
var helperFunction = buttonHandlerSpecification[event.target.id][1];
|
222
|
+
|
223
|
+
// All button handlers have a common implementation.
|
224
|
+
// 1. hide current screen
|
225
|
+
currentScreen.style.display = 'none';
|
226
|
+
|
227
|
+
// 2. show new screen
|
228
|
+
nextScreen.style.display = 'block';
|
229
|
+
|
230
|
+
// 3. Activate status
|
231
|
+
showBlock('.status-bar', 'Working...', nextScreen);
|
232
|
+
|
233
|
+
// 4. Call customizer function (which will probably query the model
|
234
|
+
// stored in the cache.
|
235
|
+
helperFunction(event);
|
236
|
+
|
237
|
+
// 5. A (possibly asynchronous) callback from the customizer will
|
238
|
+
// finish the action by running the appropriate view function.
|
239
|
+
google.logger('end of button Handler');
|
240
|
+
}
|
241
|
+
|
242
|
+
/**
|
243
|
+
* Call back from a specific JavaScript url to show a specific
|
244
|
+
* note.
|
245
|
+
* @param {number} noteKey
|
246
|
+
* @return {boolean}
|
247
|
+
*/
|
248
|
+
function showNote(noteKey) {
|
249
|
+
hideBlock('#list-note');
|
250
|
+
showBlock('#view-note .status-bar', 'Working...');
|
251
|
+
showBlock('#view-note');
|
252
|
+
cache.getValues('fullnote', [noteKey], renderFullNote);
|
253
|
+
return false;
|
254
|
+
}
|
255
|
+
|
256
|
+
/**
|
257
|
+
* Generates HTML for a note and display it.
|
258
|
+
* @param {Object} oneNote
|
259
|
+
* @param {boolean} complete True if the note has been provided or
|
260
|
+
* if an updated note is arriving. (Necessary for future support for
|
261
|
+
* sub-note updates.)
|
262
|
+
*/
|
263
|
+
function renderFullNote(oneNote, complete) {
|
264
|
+
google.logger('renderFullNote');
|
265
|
+
|
266
|
+
showBlock('.view-note-container', noteViewTemplate.process(oneNote));
|
267
|
+
if (complete) {
|
268
|
+
hideBlock('#view-note .status-bar');
|
269
|
+
}
|
270
|
+
currentNote = oneNote;
|
271
|
+
google.logger('done renderFullNote');
|
272
|
+
}
|
273
|
+
|
274
|
+
/**
|
275
|
+
* Generates HTML for a note list and display it.
|
276
|
+
* @param {Array.<Object>} noteHeaders
|
277
|
+
* @param {boolean} complete True if all in-existence notes that lie
|
278
|
+
* in the query range have been provided even if less than what was
|
279
|
+
* requested.
|
280
|
+
*/
|
281
|
+
function renderNoteList(noteHeaders, complete) {
|
282
|
+
google.logger('renderNoteList: ' + noteHeaders.length);
|
283
|
+
|
284
|
+
if (noteHeaders.length == 0) {
|
285
|
+
showBlock('.list-note-container-empty', 'No notes');
|
286
|
+
} else {
|
287
|
+
var notes = noteHeaders.map(function(n) {
|
288
|
+
return noteListTemplate.process(n);
|
289
|
+
});
|
290
|
+
showBlock('.list-note-container', notes.join());
|
291
|
+
}
|
292
|
+
if (complete) {
|
293
|
+
hideBlock('#list-note .status-bar');
|
294
|
+
}
|
295
|
+
google.logger('done renderNoteList');
|
296
|
+
}
|
297
|
+
|
298
|
+
/**
|
299
|
+
* Query for an updated note list.
|
300
|
+
*/
|
301
|
+
function showNoteList() {
|
302
|
+
google.logger('showNoteList');
|
303
|
+
cache.getValues('list', [0,20], renderNoteList);
|
304
|
+
currentNote = undefined;
|
305
|
+
google.logger('end of showNoteList');
|
306
|
+
}
|
307
|
+
|
308
|
+
/**
|
309
|
+
* A constructor for the controller. Sets up the UI and
|
310
|
+
* queries the cache for initial notelist contents.
|
311
|
+
*/
|
312
|
+
function createController() {
|
313
|
+
google.logger('createController:');
|
314
|
+
var buttons = document.querySelectorAll('.command-bar button');
|
315
|
+
Array.prototype.forEach.call(buttons, function(b) {
|
316
|
+
b.addEventListener('click', buttonHandler);
|
317
|
+
});
|
318
|
+
google.logger('controller is live');
|
319
|
+
showNoteList();
|
320
|
+
}
|
321
|
+
|
322
|
+
google.logger('about to fetch the template');
|
323
|
+
var currentNote = undefined;
|
324
|
+
|
325
|
+
var noteListTemplate = new google.wspl.simplenotes.Template(
|
326
|
+
document.querySelector('.list-note-container').innerHTML);
|
327
|
+
|
328
|
+
var noteViewTemplate = new google.wspl.simplenotes.Template(
|
329
|
+
document.querySelector('.view-note-container').innerHTML);
|
330
|
+
|
331
|
+
// var noteEditTemplate = new google.wspl.simplenotes.Template();
|
332
|
+
|
333
|
+
google.logger('created the template');
|
334
|
+
|
335
|
+
// debugging code... tear out...
|
336
|
+
// test the template construction...
|
337
|
+
// showBlock('.list-note-container', noteListTemplate.process(
|
338
|
+
// {noteKey: 123, subject: 'hi rob'}));
|
339
|
+
|
340
|
+
|
341
|
+
google.logger('loaded database');
|
342
|
+
var cache = new google.wspl.simplenotes.Cache();
|
343
|
+
cache.startCache(createController);
|
344
|
+
|
345
|
+
google.logger('finished loading page');
|
346
|
+
</script>
|
347
|
+
</html>
|
@@ -0,0 +1,503 @@
|
|
1
|
+
/*
|
2
|
+
Copyright 2009 Google Inc.
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
*/
|
16
|
+
|
17
|
+
/**
|
18
|
+
* @fileoverview A concrete example of the cache pattern for building an offline
|
19
|
+
* webapplication: a cache for SimpleNotes.
|
20
|
+
*/
|
21
|
+
|
22
|
+
google.wspl.simplenotes = google.wspl.simplenotes || {};
|
23
|
+
google.logger('start simplenotes.js');
|
24
|
+
|
25
|
+
/**
|
26
|
+
* Status keys for the write buffer.
|
27
|
+
* @enum {number}
|
28
|
+
*/
|
29
|
+
google.wspl.simplenotes.WriteBufferStates = {
|
30
|
+
/**
|
31
|
+
* The update is in flight to the server.
|
32
|
+
*/
|
33
|
+
INFLIGHT: 1,
|
34
|
+
|
35
|
+
/**
|
36
|
+
* The update needs to be (re)sent to the server but is not in flight.
|
37
|
+
*/
|
38
|
+
SEND: 2,
|
39
|
+
|
40
|
+
/**
|
41
|
+
* The update needs to be applied to the cached notes.
|
42
|
+
*/
|
43
|
+
REAPPLY: 8
|
44
|
+
};
|
45
|
+
|
46
|
+
/**
|
47
|
+
* Creates a SimpleNotes cache wrapping a backing database.
|
48
|
+
* @constructor
|
49
|
+
*/
|
50
|
+
google.wspl.simplenotes.Cache = function() {
|
51
|
+
this.dbms_ = google.wspl.DatabaseFactory.createDatabase(
|
52
|
+
'simple-notes', 'http://yourdomain/dbworker.js');
|
53
|
+
|
54
|
+
/**
|
55
|
+
* Cache directory is a two-tuple over a range. (Holes
|
56
|
+
* must be allowed to support delection.)
|
57
|
+
* This is the lower (inclusive) bound of the cached range.
|
58
|
+
* @type {number}
|
59
|
+
* @private
|
60
|
+
*/
|
61
|
+
this.start_ = -1;
|
62
|
+
|
63
|
+
/**
|
64
|
+
*
|
65
|
+
* This is the upper (inclusive) bound of the cached range.
|
66
|
+
* @type {number}
|
67
|
+
* @private
|
68
|
+
*/
|
69
|
+
this.end_ = -1;
|
70
|
+
|
71
|
+
/**
|
72
|
+
* Start of range of notes known to exist on server at time of last
|
73
|
+
* response.
|
74
|
+
* @param {number}
|
75
|
+
*/
|
76
|
+
this.serverStart_ = -1;
|
77
|
+
|
78
|
+
/**
|
79
|
+
* End of range of notes known to exist on server at time of last
|
80
|
+
* response.
|
81
|
+
* @param {number}
|
82
|
+
*/
|
83
|
+
this.serverEnd_ = -1;
|
84
|
+
|
85
|
+
/**
|
86
|
+
* Time of last refresh.
|
87
|
+
* @type {number}
|
88
|
+
* @private
|
89
|
+
*/
|
90
|
+
this.lastRefresh_ = -1;
|
91
|
+
|
92
|
+
/**
|
93
|
+
* Last missing query.
|
94
|
+
* @type {Object}
|
95
|
+
* @private
|
96
|
+
*/
|
97
|
+
this.lastMiss_ = undefined;
|
98
|
+
};
|
99
|
+
|
100
|
+
/**
|
101
|
+
* Interval between refreshes in milliseconds.
|
102
|
+
* @type {number}
|
103
|
+
* @private
|
104
|
+
*/
|
105
|
+
google.wspl.simplenotes.Cache.TIME_BETWEEN_REFRESH_ = 2000;
|
106
|
+
|
107
|
+
google.wspl.simplenotes.Cache.CREATE_CACHED_NOTES_ =
|
108
|
+
new google.wspl.Statement(
|
109
|
+
'CREATE TABLE IF NOT EXISTS cached_notes (' +
|
110
|
+
'noteKey INTEGER UNIQUE PRIMARY KEY,' +
|
111
|
+
'subject TEXT,' +
|
112
|
+
'body TEXT' +
|
113
|
+
');'
|
114
|
+
);
|
115
|
+
|
116
|
+
google.wspl.simplenotes.Cache.CREATE_WRITE_BUFFER_ =
|
117
|
+
new google.wspl.Statement(
|
118
|
+
'CREATE TABLE IF NOT EXISTS write_buffer (' +
|
119
|
+
'sequence INTEGER UNIQUE PRIMARY KEY AUTOINCREMENT,' +
|
120
|
+
'noteKey INTEGER,' +
|
121
|
+
'status INTEGER,' +
|
122
|
+
'subject TEXT,' +
|
123
|
+
'body TEXT' +
|
124
|
+
');'
|
125
|
+
);
|
126
|
+
|
127
|
+
google.wspl.simplenotes.Cache.DETERMINE_MIN_KEY_ =
|
128
|
+
new google.wspl.Statement(
|
129
|
+
'SELECT MIN(noteKey) as minNoteKey FROM cached_notes;');
|
130
|
+
|
131
|
+
google.wspl.simplenotes.Cache.DETERMINE_MAX_KEY_ =
|
132
|
+
new google.wspl.Statement(
|
133
|
+
'SELECT MAX(noteKey) as maxNoteKey FROM cached_notes;');
|
134
|
+
|
135
|
+
/**
|
136
|
+
* Builds a cache and writebuffer combination for notes and then
|
137
|
+
* invokes the given callback.
|
138
|
+
* @param {function) callback.
|
139
|
+
*/
|
140
|
+
google.wspl.simplenotes.Cache.prototype.startCache = function(callback) {
|
141
|
+
google.logger('startCache');
|
142
|
+
var statc = 0;
|
143
|
+
var self = this;
|
144
|
+
|
145
|
+
var perStatCallback = function(tx, result) {
|
146
|
+
google.logger('perStatCallback');
|
147
|
+
if (statc == 4) {
|
148
|
+
self.start_ = (result.isValidRow()) ? result.getRow().minNoteKey : -1;
|
149
|
+
self.serverStart_ = self.start_; // Temporary. Remove when server exists.
|
150
|
+
} else if (statc == 5) {
|
151
|
+
self.end_ = (result.isValidRow()) ? result.getRow().maxNoteKey : -1;
|
152
|
+
self.serverEnd_ = self.end_; // Temporary. Remove when server exists.
|
153
|
+
}
|
154
|
+
statc++;
|
155
|
+
};
|
156
|
+
|
157
|
+
this.dbms_.executeAll([
|
158
|
+
google.wspl.simplenotes.Cache.CREATE_CACHED_NOTES_,
|
159
|
+
google.wspl.simplenotes.Cache.CREATE_WRITE_BUFFER_,
|
160
|
+
google.wspl.simplenotes.Cache.CREATE_UPDATE_TRIGGER_,
|
161
|
+
google.wspl.simplenotes.Cache.CREATE_REPLAY_TRIGGER_,
|
162
|
+
google.wspl.simplenotes.Cache.DETERMINE_MIN_KEY_,
|
163
|
+
google.wspl.simplenotes.Cache.DETERMINE_MAX_KEY_],
|
164
|
+
{onSuccess: perStatCallback, onFailure: this.logError_},
|
165
|
+
{onSuccess: callback, onFailure: this.logError_});
|
166
|
+
google.logger('finished startCache');
|
167
|
+
};
|
168
|
+
|
169
|
+
/**
|
170
|
+
* Stub function to be replaced with a server communication.
|
171
|
+
* @param {Array.<Object>} updates Payload to send to server.
|
172
|
+
*/
|
173
|
+
google.wspl.simplenotes.Cache.prototype.sendXhrPost = function(updates) {
|
174
|
+
google.logger('Should dispatch XHR to server now.');
|
175
|
+
};
|
176
|
+
|
177
|
+
/**
|
178
|
+
* @type {google.wspl.Statement}
|
179
|
+
* @private
|
180
|
+
*/
|
181
|
+
google.wspl.simplenotes.Cache.LIST_CACHED_NOTES_ =
|
182
|
+
new google.wspl.Statement(
|
183
|
+
'SELECT noteKey, subject from cached_notes WHERE ' +
|
184
|
+
'noteKey >= ? AND ' +
|
185
|
+
'noteKey <= ? ' +
|
186
|
+
';'
|
187
|
+
);
|
188
|
+
|
189
|
+
/**
|
190
|
+
* Tests if the given range is stored in the cache.
|
191
|
+
* Note that this mechanism requires extension to handle the
|
192
|
+
* creation of new notes.
|
193
|
+
* @param {number} start Lower bound (inclusive) on range.
|
194
|
+
* @param {number} end Uppder bound (inclusive) on range.
|
195
|
+
* @private
|
196
|
+
*/
|
197
|
+
google.wspl.simplenotes.Cache.prototype.isCacheHit_ = function(start, end) {
|
198
|
+
return start >= this.start_ && end <= this.end_
|
199
|
+
};
|
200
|
+
|
201
|
+
/**
|
202
|
+
* Logs a possibly useful error message.
|
203
|
+
* @param {Object} error An error descriptor.
|
204
|
+
* @private
|
205
|
+
*/
|
206
|
+
google.wspl.simplenotes.Cache.prototype.logError_ = function(error) {
|
207
|
+
google.logger('Simple Notes Cache is sad: ' + error);
|
208
|
+
};
|
209
|
+
|
210
|
+
/**
|
211
|
+
* Queries the cache for a list of note headers.
|
212
|
+
* @param {number} start The lower id in a range of notes.
|
213
|
+
* @param {number} end The higher id in a range of notes.
|
214
|
+
* @param {function(Array.<Object>)} valuesCallback A function to call
|
215
|
+
* with the result set after the transaction has completed.
|
216
|
+
* @private
|
217
|
+
*/
|
218
|
+
google.wspl.simplenotes.Cache.prototype.getNoteList_ = function(start, end,
|
219
|
+
valuesCallback) {
|
220
|
+
var notes = [];
|
221
|
+
|
222
|
+
var accumulateResults = function(tx, result) {
|
223
|
+
for(; result.isValidRow(); result.next()) {
|
224
|
+
notes.push(result.getRow());
|
225
|
+
google.logger('pushed...');
|
226
|
+
}
|
227
|
+
};
|
228
|
+
|
229
|
+
var inTransactionGetNotes = function(tx) {
|
230
|
+
tx.execute(google.wspl.simplenotes.Cache.LIST_CACHED_NOTES_.
|
231
|
+
createStatement([start, end]), {
|
232
|
+
onSuccess: accumulateResults,
|
233
|
+
onFailure: this.logError_});
|
234
|
+
};
|
235
|
+
|
236
|
+
var hit = this.isCacheHit_(start, end);
|
237
|
+
this.dbms_.createTransaction(inTransactionGetNotes, {onSuccess: function() {
|
238
|
+
valuesCallback(notes, hit);
|
239
|
+
}, onFailure: this.logError_});
|
240
|
+
|
241
|
+
if (hit) {
|
242
|
+
this.fetchFromServer(this.start_, this.end_); // Refresh
|
243
|
+
} else {
|
244
|
+
this.fetchFromServer(Math.min(this.start_, start), Math.max(this.end_, end));
|
245
|
+
this.lastMiss_ = {callback: valuesCallback, start: start, end: end};
|
246
|
+
}
|
247
|
+
};
|
248
|
+
|
249
|
+
/**
|
250
|
+
* @type {google.wspl.Statement}
|
251
|
+
* @private
|
252
|
+
*/
|
253
|
+
google.wspl.simplenotes.Cache.GET_ONE_NOTE_ =
|
254
|
+
new google.wspl.Statement(
|
255
|
+
'SELECT noteKey, subject, body from cached_notes WHERE ' +
|
256
|
+
'noteKey = ? ' +
|
257
|
+
';'
|
258
|
+
);
|
259
|
+
|
260
|
+
/**
|
261
|
+
* Queries the cache for a list of note headers.
|
262
|
+
* @param {number} noteId The note to get from the cache.
|
263
|
+
* @param {function(Array.<Object>)} valuesCallback A function to call
|
264
|
+
* with the result set after the transaction has completed.
|
265
|
+
* @private
|
266
|
+
*/
|
267
|
+
google.wspl.simplenotes.Cache.prototype.getOneNote_ = function(noteId,
|
268
|
+
callback) {
|
269
|
+
var note;
|
270
|
+
|
271
|
+
this.dbms_.execute(google.wspl.simplenotes.Cache.GET_ONE_NOTE_.
|
272
|
+
createStatement([noteId]),
|
273
|
+
{onSuccess: function(tx, result) { note = result.getRow(); },
|
274
|
+
onFailure: this.logError_},
|
275
|
+
{onSuccess: function() { callback(note, true); },
|
276
|
+
onFailure: this.logError_});
|
277
|
+
};
|
278
|
+
|
279
|
+
/**
|
280
|
+
* Queries the cache for either a list of notes or a single note including
|
281
|
+
* its body.
|
282
|
+
* @param {string} type The kind of values desired: 'list' or 'fullnote'.
|
283
|
+
* @param {Array.<number>} query The query for the values.
|
284
|
+
* @param {function(Array.<Object>)} valuesCallback A function to call
|
285
|
+
* with the result set after the transaction has completed.
|
286
|
+
*/
|
287
|
+
google.wspl.simplenotes.Cache.prototype.getValues = function(type,
|
288
|
+
query, valuesCallback) {
|
289
|
+
|
290
|
+
// Reduce any query to what would be available from the server
|
291
|
+
query[0] = Math.max(this.serverStart_, query[0]);
|
292
|
+
query[1] = Math.min(this.serverEnd_, query[1]);
|
293
|
+
|
294
|
+
if (type == 'list') {
|
295
|
+
this.getNoteList_(query[0], query[1], valuesCallback);
|
296
|
+
} else if (type == 'fullnote') {
|
297
|
+
this.getOneNote_(query[0], valuesCallback);
|
298
|
+
}
|
299
|
+
};
|
300
|
+
|
301
|
+
/**
|
302
|
+
* SQL trigger to insert a new change from write buffer to
|
303
|
+
* cache.
|
304
|
+
* @private
|
305
|
+
*/
|
306
|
+
google.wspl.simplenotes.Cache.CREATE_UPDATE_TRIGGER_ =
|
307
|
+
new google.wspl.Statement(
|
308
|
+
'CREATE TRIGGER IF NOT EXISTS updateTrigger ' +
|
309
|
+
'AFTER INSERT ON write_buffer ' +
|
310
|
+
'BEGIN ' +
|
311
|
+
' REPLACE INTO cached_notes ' +
|
312
|
+
' SELECT noteKey, subject, body ' +
|
313
|
+
' FROM write_buffer WHERE status & 8 = 8; ' +
|
314
|
+
' UPDATE write_buffer SET status = status & ~ 8; ' +
|
315
|
+
'END;'
|
316
|
+
);
|
317
|
+
|
318
|
+
/**
|
319
|
+
* SQL trigger to replay changes from the write buffer to
|
320
|
+
* the cache.
|
321
|
+
* @private
|
322
|
+
*/
|
323
|
+
google.wspl.simplenotes.Cache.CREATE_REPLAY_TRIGGER_ =
|
324
|
+
new google.wspl.Statement(
|
325
|
+
'CREATE TRIGGER IF NOT EXISTS replayTrigger ' +
|
326
|
+
'AFTER UPDATE ON write_buffer WHEN NEW.status & 8 = 8 ' +
|
327
|
+
'BEGIN ' +
|
328
|
+
' REPLACE INTO cached_notes ' +
|
329
|
+
' SELECT noteKey, subject, body ' +
|
330
|
+
' FROM write_buffer ' +
|
331
|
+
' WHERE noteKey = NEW.noteKey ' +
|
332
|
+
' ORDER BY sequence ASC;' +
|
333
|
+
' UPDATE write_buffer SET status = status & ~ 8; ' +
|
334
|
+
'END;'
|
335
|
+
);
|
336
|
+
|
337
|
+
|
338
|
+
/**
|
339
|
+
* SQL statement to mark actions for replay.
|
340
|
+
*/
|
341
|
+
google.wspl.simplenotes.Cache.MARK_FOR_REPLAY =
|
342
|
+
new google.wspl.Statement(
|
343
|
+
'UPDATE write_buffer SET status = status | 8;');
|
344
|
+
|
345
|
+
/**
|
346
|
+
* SQL statement to insert notes updates.
|
347
|
+
* @type {!google.wspl.Statement}
|
348
|
+
* @private
|
349
|
+
*/
|
350
|
+
google.wspl.simplenotes.Cache.INSERT_UI_UPDATE_ =
|
351
|
+
new google.wspl.Statement(
|
352
|
+
'INSERT INTO write_buffer (' +
|
353
|
+
'noteKey, status, subject, body' +
|
354
|
+
') ' + 'VALUES(?,?,?,?);');
|
355
|
+
|
356
|
+
/**
|
357
|
+
* Updates the given entry and write a new write buffer entry.
|
358
|
+
* @param {number} noteKey
|
359
|
+
* @param {string} subject
|
360
|
+
* @param {string} body
|
361
|
+
* @param {function(number)} ackCallback
|
362
|
+
*/
|
363
|
+
google.wspl.simplenotes.Cache.prototype.applyUiChange = function(noteKey,
|
364
|
+
subject, body, ackCallback) {
|
365
|
+
var self = this;
|
366
|
+
var update = [noteKey, 2 | 8, subject, body];
|
367
|
+
var stat = google.wspl.simplenotes.Cache.INSERT_UI_UPDATE_.createStatement(
|
368
|
+
update);
|
369
|
+
|
370
|
+
this.dbms_.execute(stat, null, {onSuccess: function() {
|
371
|
+
google.logger('applyUiChange cb');
|
372
|
+
ackCallback(noteKey);
|
373
|
+
}, onFailure: function (error) {
|
374
|
+
self.logError_(error);
|
375
|
+
ackCallback(-1);
|
376
|
+
}});
|
377
|
+
};
|
378
|
+
|
379
|
+
/**
|
380
|
+
* SQL statement to insert notes updates.
|
381
|
+
* @type {!google.wspl.Statement}
|
382
|
+
* @private
|
383
|
+
*/
|
384
|
+
google.wspl.simplenotes.Cache.INSERT_NOTE_ =
|
385
|
+
new google.wspl.Statement(
|
386
|
+
'REPLACE INTO cached_notes (noteKey, subject, body) ' +
|
387
|
+
'VALUES(?,?,?);' );
|
388
|
+
|
389
|
+
/**
|
390
|
+
* SQL statement to force replay of pending actions by setting a bit
|
391
|
+
* flag on each write-buffer row indicating that it should be reapplied
|
392
|
+
* to the contents of the cache.
|
393
|
+
* @type {!google.wspl.Statement}
|
394
|
+
* @private
|
395
|
+
*/
|
396
|
+
google.wspl.simplenotes.Cache.FORCE_REPLAY_ =
|
397
|
+
new google.wspl.Statement(
|
398
|
+
'UPDATE write_buffer SET status = status | 8;' );
|
399
|
+
|
400
|
+
/**
|
401
|
+
* SQL statement to delete notes no longer to be cached.
|
402
|
+
* @type {!google.wspl.Statement}
|
403
|
+
* @private
|
404
|
+
*/
|
405
|
+
google.wspl.simplenotes.Cache.EVICT_ =
|
406
|
+
new google.wspl.Statement(
|
407
|
+
'DELETE FROM cached_notes WHERE noteKey < ? OR noteKey > ?;');
|
408
|
+
|
409
|
+
/**
|
410
|
+
* Applies the changes delivered from the server by first inserting
|
411
|
+
* them into the cache and reapplying the write-buffer to the cache.
|
412
|
+
* @param {!Array.<Object>} notes An array of arrays.
|
413
|
+
*/
|
414
|
+
google.wspl.simplenotes.Cache.prototype.insertUpdate = function(notes) {
|
415
|
+
var self = this; var stats = [];
|
416
|
+
var start = notes[0].noteKey;
|
417
|
+
var end = notes[0].noteKey;
|
418
|
+
|
419
|
+
for (var i = 0; i < notes.length; i++) {
|
420
|
+
stats.push(google.wspl.simplenotes.Cache.INSERT_NOTE_.
|
421
|
+
createStatement([notes[i].noteKey, notes[i].subject, notes[i].body]));
|
422
|
+
start = Math.min(start, notes[0].noteKey);
|
423
|
+
end = Math.max(end, notes[0].noteKey);
|
424
|
+
}
|
425
|
+
stats.push(google.wspl.simplenotes.Cache.EVICT_.createStatement([start, end]));
|
426
|
+
stats.push(google.wspl.simplenotes.Cache.FORCE_REPLAY_);
|
427
|
+
|
428
|
+
var inTrans = function(tx) {
|
429
|
+
self.start_ = start;
|
430
|
+
self.end_ = end;
|
431
|
+
tx.executeAll(stats);
|
432
|
+
};
|
433
|
+
|
434
|
+
var afterInsert = function(tx) {
|
435
|
+
if (this.lastMiss_ &&
|
436
|
+
this.isCacheHit_(this.lastMiss_.start, this.lastMiss_.end)) {
|
437
|
+
this.lastMiss_.callback(notes);
|
438
|
+
this.lastMiss_ = undefined;
|
439
|
+
}
|
440
|
+
};
|
441
|
+
|
442
|
+
this.dbms_.createTransaction(inTrans, {onSuccess: afterInsert,
|
443
|
+
onError: this.logError_});
|
444
|
+
};
|
445
|
+
|
446
|
+
/**
|
447
|
+
* SQL statement to force replay of pending actions by setting a bit
|
448
|
+
* flag on each write-buffer row indicating that it should be reapplied
|
449
|
+
* to the contents of the cache.
|
450
|
+
* @type {!google.wspl.Statement}
|
451
|
+
* @private
|
452
|
+
*/
|
453
|
+
google.wspl.simplenotes.Cache.GET_UPDATES_TO_RESEND_ =
|
454
|
+
new google.wspl.Statement(
|
455
|
+
'SELECT noteKey, subject, body FROM write_buffer WHERE status & 2 = 2;');
|
456
|
+
|
457
|
+
|
458
|
+
|
459
|
+
/**
|
460
|
+
* SQL statement to mark write buffer statements as inflight.
|
461
|
+
* @type {!google.wspl.Statement}
|
462
|
+
* @private
|
463
|
+
*/
|
464
|
+
google.wspl.simplenotes.Cache.MARK_AS_INFLIGHT_ =
|
465
|
+
new google.wspl.Statement(
|
466
|
+
'UPDATE write_buffer SET status = status & ~2 | 1 WHERE status & 2 = 2;');
|
467
|
+
|
468
|
+
/**
|
469
|
+
* Fetches new material from the server as required.
|
470
|
+
* @param {number} start
|
471
|
+
* @param {number} end
|
472
|
+
* @param {function} opt_valueCallBack
|
473
|
+
*/
|
474
|
+
google.wspl.simplenotes.Cache.prototype.fetchFromServer = function(start,
|
475
|
+
end) {
|
476
|
+
google.logger('fetchFromServer');
|
477
|
+
var now = this.dbms_.getCurrentTime();
|
478
|
+
if (start >= this.start_ && end <= this.end_ &&
|
479
|
+
now - this.lastRefresh_ <
|
480
|
+
google.wspl.simplenotes.Cache.TIME_BETWEEN_REFRESH_) {
|
481
|
+
return;
|
482
|
+
}
|
483
|
+
|
484
|
+
var updates = []; var self = this; var flag = 1; var sql = []
|
485
|
+
sql.push(google.wspl.simplenotes.Cache.GET_UPDATES_TO_RESEND_);
|
486
|
+
sql.push(google.wspl.simplenotes.Cache.MARK_AS_INFLIGHT_);
|
487
|
+
|
488
|
+
var accumulateUpdates = function(tx, rs) {
|
489
|
+
if (flag == 1) {
|
490
|
+
for(; rs.isValidRow(); rs.next()) { updates.push(['u', rs.getRow()]); }
|
491
|
+
flag++;
|
492
|
+
}
|
493
|
+
};
|
494
|
+
|
495
|
+
var ackAndPost = function() {
|
496
|
+
updates.push(['q', {start: start, end: end}]);
|
497
|
+
self.sendXhrPost(updates);
|
498
|
+
};
|
499
|
+
|
500
|
+
this.dbms_.executeAll(sql,
|
501
|
+
{onSuccess: accumulateUpdates, onFailure: this.logError_},
|
502
|
+
{onSuccess: ackAndPost, onFailure: this.logError_});
|
503
|
+
};
|