<script src="gears_init.js"></script> <script> if (!window.google || !google.gears) { location.href = "http://gears.google.com/?action=install&message=<your welcome message>" + "&return=<your website url>"; } </script>
enabled = false
.ManagedResourceStore
gears keeps these files uptodate with server. manifest.json
that lists files you want cached:
{ "betaManifestVersion": 1, "version": "1.0", "entries": [ { "url": "go_offline.html"}, { "url": "go_offline.js"}, { "url": "gears_init.js"} ] }
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <script type="text/javascript" src="gears_init.js"></script> <script type="text/javascript" src="go_offline.js"></script> <title>Enable Offline Usage</title> <style type="text/css"> <!-- .style1 { color: #003399; font-style: italic; font-weight: bold; font-size: large; } .style3 { color: #009933; font-weight: bold; font-style: italic; } --> </style> </head> <body onload="init()"> <h2>Getting offline-enabled documents with Gears </h2> <p> </p> <div> <p class="style1">Status Message: <span id="textOut" class="style3"></span></p> </div> <p><strong>Q:</strong> I want to see these documents when I'm not online! What must I do?<br /> <strong>A:</strong> <a href="http://gears.google.com/">Install Gears</a> on your computer and then click "Capture" to store the documents to your computer. You can then access the URLs without a network connection. </p> <p> <button onclick="createStore()" > Capture </button> </p> <p><strong>Q:</strong> I want to remove my offline access to these documents. What must I do?<br /> <strong>A: </strong>Click "Erase" below to removed the "captured" documents from your computer. The documents will no longer be available without a network connection. </p> <p> <button onclick="removeStore()" > Erase </button> </p> </body> </html>
var STORE_NAME = "my_offline_docset"; // Change this to set the URL of tha manifest file, which describe which // URLs to capture. It can be relative to the current page, or an // absolute URL. var MANIFEST_FILENAME = "manifest.json"; var localServer; var store; // Called onload to initialize local server and store variables function init() { if (!window.google || !google.gears) { textOut("NOTE: You must install Gears first."); } else { localServer = google.gears.factory.create("beta.localserver"); store = localServer.createManagedStore(STORE_NAME); textOut("Yeay, Gears is already installed."); } } // Create the managed resource store function createStore() { if (!window.google || !google.gears) { alert("You must install Gears first."); return; } store.manifestUrl = MANIFEST_FILENAME; store.checkForUpdate(); var timerId = window.setInterval(function() { // When the currentVersion property has a value, all of the resources // listed in the manifest file for that version are captured. There is // an open bug to surface this state change as an event. if (store.currentVersion) { window.clearInterval(timerId); textOut("The documents are now available offline.\n" + "With your browser offline, load the document at " + "its normal online URL to see the locally stored " + "version. The version stored is: " + store.currentVersion); } else if (store.updateStatus == 3) { textOut("Error: " + store.lastErrorMessage); } }, 500); } // Remove the managed resource store. function removeStore() { if (!window.google || !google.gears) { alert("You must install Gears first."); return; } localServer.removeManagedStore(STORE_NAME); textOut("Done. The local store has been removed." + "You will now see online versions of the documents."); } // Utility function to output some status text. function textOut(s) { var elm = document.getElementById("textOut"); while (elm.firstChild) { elm.removeChild(elm.firstChild); } elm.appendChild(document.createTextNode(s)); }
ManagedResourceStore
, these are only updated (re-downloaded from server) when you call capture()
.Blog
object holds binary data. length
. slice(offset, length)
<html> <head> <title>Gears Database Demo</title> <link rel="stylesheet" type="text/css" href="sample.css"> </head> <body> <h1>Gears Database Demo</h1> <div id="view-source"> </div> <form onsubmit="handleSubmit(); return false;"> <b>Enter a phrase to store in the database:</b> <br> <table> <tr> <td valign="middle"><input type="text" id="submitValue" style="width:20em;"></td> <td valign="middle"><input type="submit" value="OK"></td> </tr> </table> </form> <p><b>Your last three phrases were:</b> <p><span id="status"> </span> <p><i>This page uses Gears to record your entries on the local disk. If you navigate away and revisit this page, all your data will still be here. Try it!</i> <!-- ====================================== --> <!-- End HTML code. Begin JavaScript code. --> <script type="text/javascript" src="gears_init.js"></script> <script type="text/javascript" src="sample.js"></script> <script type="text/javascript" src="hello_world.js"> </script> </body> </html>
hello_world.js
:
var db; init(); // Open this page's local database. function init() { var success = false; if (window.google && google.gears) { try { db = google.gears.factory.create('beta.database'); if (db) { db.open('database-demo'); db.execute('create table if not exists Demo' + ' (Phrase varchar(255), Timestamp int)'); success = true; // Initialize the UI at startup. displayRecentPhrases(); } } catch (ex) { setError('Could not create database: ' + ex.message); } } // Enable or disable UI elements var inputs = document.forms[0].elements; for (var i = 0, el; el = inputs[i]; i++) { el.disabled = !success; } } function handleSubmit() { if (!google.gears.factory || !db) { return; } var elm = getElementById('submitValue'); var phrase = elm.value; var currTime = new Date().getTime(); // Insert the new item. // The Gears database automatically escapes/unescapes inserted values. db.execute('insert into Demo values (?, ?)', [phrase, currTime]); // Update the UI. elm.value = ''; displayRecentPhrases(); } function displayRecentPhrases() { var recentPhrases = ['', '', '']; // Get the 3 most recent entries. Delete any others. var rs = db.execute('select * from Demo order by Timestamp desc'); var index = 0; while (rs.isValidRow()) { if (index < 3) { recentPhrases[index] = rs.field(0); } else { db.execute('delete from Demo where Timestamp=?', [rs.field(1)]); } ++index; rs.next(); } rs.close(); var status = getElementById('status'); status.innerHTML = ''; for (var i = 0; i < recentPhrases.length; ++i) { var id = 'phrase' + i; status.innerHTML += '<span id="' + id + '"></span><br>'; var bullet = '(' + (i + 1) + ') '; setTextContent(getElementById(id), bullet + recentPhrases[i]); } }
sample.js
:
function isDefined(type) { return (type != 'undefined' && type != 'unknown'); } function childNodes(element) { if (isDefined(typeof element.childNodes)) { return element.childNodes; } else if (isDefined(typeof element.children)) { return element.children; } } function getElementById(element_name) { if (isDefined(typeof document.getElementById)) { return document.getElementById(element_name); } else if(typeof isDefined(document.all)) { return document.all[element_name]; } } function setTextContent(elem, content) { if (isDefined(typeof elem.innerText)) { elem.innerText = content; } else if (isDefined(typeof elem.textContent)) { elem.textContent = content; } } function setupSample() { // Make sure we have Gears. If not, tell the user. if (!window.google || !google.gears) { if (confirm("This demo requires Gears to be installed. Install now?")) { // Use an absolute URL to allow this to work when run from a local file. location.href = "http://code.google.com/apis/gears/install.html"; return; } } var viewSourceElem = getElementById("view-source"); if (!viewSourceElem) { return; } var elm; if (navigator.product == "Gecko") { // If we're gecko, we can show the source of the application with the // view-source protocol. elm = "<a href='view-source:" + location.href + "'>" + "View Demo Source" + "</a>"; } else { // Otherwise, just tell users how to do it manually. elm = "<em>" + "To see how this works, use the <strong>view " + "source</strong> feature of your browser" + "</em>"; } viewSourceElem.innerHTML += elm; } function checkProtocol() { if (location.protocol.indexOf('http') != 0) { setError('This sample must be hosted on an HTTP server'); return false; } else { return true; } } function addStatus(message, opt_class) { var elm = getElementById('status'); var id = 'statusEntry' + (childNodes(elm).length + 1); if (!elm) return; if (opt_class) { elm.innerHTML += '<span id="' + id + '" class="' + opt_class + '"></span>'; } else { elm.innerHTML += '<span id="' + id + '"></span>'; } elm.innerHTML += '<br>'; setTextContent(getElementById(id), message); } function clearStatus() { var elm = getElementById('status'); elm.innerHTML = ''; } function setError(s) { clearStatus(); addStatus(s, 'error'); } setupSample();
var desktop = google.gears.factory.create('beta.desktop'); desktop.createShortcut('Test Application', 'http://example.com/index.html', {'128x128': 'http://example.com/icon128x128.png', '48x48': 'http://example.com/icon48x48.png', '32x32': 'http://example.com/icon32x32.png', '16x16': 'http://example.com/icon16x16.png'}, 'An application at http://example.com/index.html'); function openFilesCallback(files) { //Typically, here you would open the appropriate URL alert('User selected ' + files.length + ' files.'); } desktop.openFiles(openFilesCallback);
watchPosition
to get called whenever the user moves. var geo = google.gears.factory.create('beta.geolocation'); function updatePosition(position) { alert('Current lat/lon is: ' + position.latitude + ',' + position.longitude); } function handleError(positionError) { alert('Attempt to get location failed: ' + positionError.message); } geo.getCurrentPosition(updatePosition, handleError);
var request = google.gears.factory.create('beta.httprequest'); request.open('GET', '/index.html'); request.onreadystatechange = function() { if (request.readyState == 4) { console.write(request.responseText); } }; request.send();
setTimeout
and others for workers var timer = google.gears.factory.create('beta.timer'); timer.setTimeout(function() { alert('Hello, from the future!'); }, 1000);
<!DOCTYPE HTML> <html><head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>Google Gears WorkerPool Demo</title> <link rel="stylesheet" type="text/css" href="hello_world_workerpool_files/sample.css"> <style> p.results { margin: 4px; } </style> </head><body onload="init()" id="theBody"> <h1>Google Gears WorkerPool Demo</h1> <div id="view-source"> <a href="view-source:http://code.google.com/apis/gears/samples/hello_world_workerpool/hello_world_workerpool.html">View Demo Source</a></div> <p id="status"> </p><p> <table> <tbody><tr> <td valign="top">Interact with UI:</td> <td><input value="Interact" onclick="interact();" type="button"> </td> <td></td> </tr> <tr> <td valign="top">Run expensive computation:</td> <td> <input id="syncButton" value="Synchronous" onclick="syncComputation();" type="button"> </td> <td><i>Note the synchronous computation blocks UI interaction (and may even cause an 'unresponsive script' warning).</i> </td> </tr> <tr> <td> </td> <td> <input id="asyncButton" value="Asynchronous" onclick="asyncComputation();" type="button"> </td> <td> <i>But you can still interact while the asynchronous computation runs in a JavaScript worker.</i> </td> </tr> </tbody></table> </p><div id="results" style="font-size: 120%;" ;=""> <p style="font-weight: bold;" class="results">Results </p><p class="results" id="message3">Hello, threaded JavaScript.</p><p class="results" id="message4">Parent initialized.</p></div> <!-- ====================================== --> <!-- End HTML code. Begin JavaScript code. --> <script src="gears_init.js"></script> <script src="sample.js"></script> <script src="wpool.js"></script> </body><div FirebugVersion="1.3.3" style="display: none;" id="_firebugConsole"></div></html>
wpool.js
function init() { insertRow('Hello, threaded JavaScript.'); parentInit(); } function insertRow(message) { var results = getElementById('results'); var id = 'message' + (childNodes(results).length + 1); results.innerHTML += '<p class="results" id="' + id + '">'; setTextContent(getElementById(id), message); } // // WorkerPool code // var workerPool = null; var childId; function parentInit() { if (!window.google || !google.gears) { return; } try { workerPool = google.gears.factory.create('beta.workerpool'); } catch (e) { document.getElementById('asyncButton').disabled = true; setError('Could not create workerpool: ' + e.message); return; } // set the parent's message handler workerPool.onmessage = parentHandler; // create the worker try { childId = workerPool.createWorkerFromUrl('worker.js'); } catch (e) { setError('Could not create worker: ' + e.message); } // Child workers will always set onmessage before createWorker() returns. insertRow('Parent initialized.'); } function parentHandler(messageText, sender, message) { insertRow('Asynchronous result: ' + message.body); } // // UI-related functions // var uiToggleState = 0; function interact() { if (uiToggleState) { getElementById('theBody').style.backgroundColor = '#FFFFFF'; uiToggleState = 0; } else { getElementById('theBody').style.backgroundColor = '#CCCCCC'; uiToggleState = 1; } } function asyncComputation() { if (workerPool) { workerPool.sendMessage(112501234, childId); } } function syncComputation() { var result = identity(112501234); insertRow('Synchronous result: ' + result); function identity(n) { var result = 0; while (n > 0) { result += 1; var tempString = 'abc' + '123'; // for slowdown n--; } return result; } }
worker.js
:
// Copyright 2007, Google Inc. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // 3. Neither the name of Google Inc. nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. google.gears.workerPool.onmessage = function(messageText, senderId, message) { google.gears.workerPool.sendMessage(identity(message.body), senderId); }; function identity(n) { var result = 0; while (n > 0) { result += 1; var tempString = 'abc' + '123'; // for slowdown n--; } return result; }
sample.js
:
// Copyright 2007, Google Inc. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // 3. Neither the name of Google Inc. nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // On some WinCE devices, IE Mobile uses 'unknown' rather than 'undefined'. If // an element has type 'unknown', we can not pass it to a function, so we must // pass its type instead. function isDefined(type) { return (type != 'undefined' && type != 'unknown'); } function childNodes(element) { if (isDefined(typeof element.childNodes)) { return element.childNodes; } else if (isDefined(typeof element.children)) { return element.children; } } function getElementById(element_name) { if (isDefined(typeof document.getElementById)) { return document.getElementById(element_name); } else if(typeof isDefined(document.all)) { return document.all[element_name]; } } function setTextContent(elem, content) { if (isDefined(typeof elem.innerText)) { elem.innerText = content; } else if (isDefined(typeof elem.textContent)) { elem.textContent = content; } } function setupSample() { // Make sure we have Gears. If not, tell the user. if (!window.google || !google.gears) { if (confirm("This demo requires Gears to be installed. Install now?")) { // Use an absolute URL to allow this to work when run from a local file. location.href = "http://code.google.com/apis/gears/install.html"; return; } } var viewSourceElem = getElementById("view-source"); if (!viewSourceElem) { return; } var elm; if (navigator.product == "Gecko") { // If we're gecko, we can show the source of the application with the // view-source protocol. elm = "<a href='view-source:" + location.href + "'>" + "View Demo Source" + "</a>"; } else { // Otherwise, just tell users how to do it manually. elm = "<em>" + "To see how this works, use the <strong>view " + "source</strong> feature of your browser" + "</em>"; } viewSourceElem.innerHTML += elm; } function checkProtocol() { if (location.protocol.indexOf('http') != 0) { setError('This sample must be hosted on an HTTP server'); return false; } else { return true; } } function addStatus(message, opt_class) { var elm = getElementById('status'); var id = 'statusEntry' + (childNodes(elm).length + 1); if (!elm) return; if (opt_class) { elm.innerHTML += '<span id="' + id + '" class="' + opt_class + '"></span>'; } else { elm.innerHTML += '<span id="' + id + '"></span>'; } elm.innerHTML += '<br>'; setTextContent(getElementById(id), message); } function clearStatus() { var elm = getElementById('status'); elm.innerHTML = ''; } function setError(s) { clearStatus(); addStatus(s, 'error'); } setupSample();
This talk available at http://jmvidal.cse.sc.edu/talks/googlegears/
Copyright © 2009 José M. Vidal
.
All rights reserved.
24 March 2009, 08:11AM