JavaScript開発のGoogle Way
// myapp.js
goog.provide('myapp.MyClass');
goog.require('goog.ui.DatePicker');
// index.html
<script>goog.require('myapp.MyClass');</script>
goog.provide(); で定義するクラス名を宣言goog.require(); で依存ファイルを読み込み
var CONSTANT = 'Hello ';
function hello(name) {
return CONSTANT + name;
}
function bye(name) {
return 'Bye ' + name;
}
alert(hello('world!'));
Closure Compiler でコンパイル
alert("Hello world");
/** @param {string} name Your name. */
function hello(name) {
alert('Hello ' + name);
}
hello(['world!']); // 警告 : 引数の型が違う
hello(); // 警告 : 引数は省略不可
/** @constructor */
function BaseClass() {};
/**
* @param {string} msg A greeting message. */
BaseClass.prototype.greeting = function(msg) { alert(msg); };
/**
* @constructor
* @extends {BaseClass}*/
function HelloClass() {};
goog.inherits(HelloClass, BaseClass);
/** @inheritDoc */
HelloClass.prototype.greeting = function(msg) {
goog.base(this, 'greeting', 'Hello ' + name);
};
/** @type {BaseClass} */
var instance = new HelloClass();
instance.greeting('world!');
instance.undefinedMethod(); // 警告
goog.provide('myapp.MyClass');
goog.require('goog.debug.Logger');
/** @constructor */
myapp.MyClass = function() {}
/** @type {goog.debug.Logger} */
myapp.MyClass.logger = goog.debug.Logger.getLogger('myapp.MyClass');
myapp.MyClass.logger.setLevel(goog.debug.Logger.Level.ALL);
myapp.MyClass.foo = function() {
myapp.MyClass.logger.debug('foo is called');
}
goog.require('goog.debug.ErrorHandler');
goog.require('goog.debug.entryPointRegistry');
var eh = new goog.debug.ErrorHandler(function(e) {
logger.warning('Exception :', e);
});
goog.debug.entryPointRegistry.monitorAll(eh);
// setTimeout, setInterval での例外も補足するには以下を実行
eh.protectWindowSetTimeout();
eh.protectWindowSetInterval();

svn co http://closure-library.googlecode.com/svn/trunk/ closure-librarygit clone https://github.com/jarib/google-closure-library.git closure-librarycurl -O http://closure-compiler.googlecode.com/files/compiler-latest.zipunzip compiler-latest.zipcp compiler.jar /some/where
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>サンプル</title>
<link rel="stylesheet" type="text/css" href="editor.css">
</head>
<body>
<div id="frame">
<div id="toolbar"></div>
<div id="editor"></div>
</div>
<script src="closure-library/closure/goog/base.js"></script>
<script src="deps.js"></script>
<script>
goog.require('editor.App');
</script>
</body>
</html>
goog.provide('editor.App');
goog.require('goog.editor.Field');
goog.require('goog.editor.plugins.BasicTextFormatter');
goog.require('goog.ui.editor.ToolbarController');
goog.require('goog.ui.editor.DefaultToolbar');
goog.scope(function() {
var Field = goog.editor.Field;
var Toolbar = goog.ui.editor.DefaultToolbar;
var Controller = goog.ui.editor.ToolbarController;
/** @constructor */
editor.App = function() {
var editor = new Field('editor', document);
var toolbarEl = goog.dom.getElement('toolbar');
var toolbar = Toolbar.makeDefaultToolbar(toolbarEl);
var controller = new Controller(editor, toolbar);
editor.registerPlugin(new goog.editor.plugins.BasicTextFormatter());
editor.makeEditable();
};
});
new editor.App();
@import "closure-library/closure/goog/css/common.css";
@import "closure-library/closure/goog/css/colormenubutton.css";
@import "closure-library/closure/goog/css/palette.css";
@import "closure-library/closure/goog/css/colorpalette.css";
@import "closure-library/closure/goog/css/editortoolbar.css";
@import "closure-library/closure/goog/css/button.css";
@import "closure-library/closure/goog/css/menu.css";
@import "closure-library/closure/goog/css/menuitem.css";
@import "closure-library/closure/goog/css/toolbar.css";
#frame {
border: solid 1px black;
}
#editor {
display:block; width:100%; height:400px;
}
python closure-library/closure/bin/build/depswriter.py --root_with_prefix="scripts ../../../scripts" --output_file=deps.js
deps.js に以下の内容が生成される
// This file was autogenerated by closure-library/closure/bin/build/depswriter.py. // Please do not edit. goog.addDependency( '../../../scripts/app.js', ['editor.App'], ['goog.editor.Field', 'goog.editor.plugins.BasicTextFormatter', 'goog.ui.editor.DefaultToolbar', 'goog.ui.editor.ToolbarController']);
python closure-library/closure/bin/build/closurebuilder.py --root=closure-library --root=scripts -n editor.App -o compiled --output_file=compiled.js -c /path/to/compiler.jar -f "--compilation_level=ADVANCED_OPTIMIZATIONS" -f "--define=goog.DEBUG=false"
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>サンプル</title>
<link rel="stylesheet" type="text/css" href="editor.css">
</head>
<body>
<div id="frame">
<div id="toolbar"></div>
<div id="editor"></div>
</div>
<script src="compiled.js"></script>
</body>
</html>
goog.require('goog.storage.Storage');
goog.require('goog.storage.mechanism.mechanismfactory');
var mechanism = goog.storage.mechanism.mechanismFactory.create('namespace');
if(!mechanism) {
var storage = new goog.storage.Storage(mechanism);
storage.set('item1', 'Hello world!');
storage.set('item2', [0, 1, 2]);
storage.set('item3', { 'a':'A', 'b':'B' });
var a = storage.get('item1'); // a == 'Hello world!'
var b = storage.get('item2'); // b == [0, 1, 2]
var c = storage.get('item3'); // c == { 'a':'A', 'b':'B' }
storage.remove('item1');
storage.remove('item2');
storage.remove('item3');
}
goog.require('goog.fs');
goog.fs.getPersistent(10*1024).addCallback(function(fs) {
return fs.getRoot().getFile(
'test.txt', goog.fs.DirectoryEntry.Behavior.CREATE);
}).addCallback(function(entry) {
return entry.createWriter();
}).addCallback(function(writer) {
writer.write(goog.fs.getBlob('Hello world!'));
});
goog.require('goog.net.xpc.CrossPageChannel');
goog.require('goog.events');
goog.scope(function() {
var xpc = goog.net.xpc;
var cfg = {};
cfg[xpc.CfgField.LOCAL_RELAY_URI] = 'http://example1.com/relay.html';
cfg[xpc.CfgField.PEER_RELAY_URI] = 'http://example2.com/relay.html';
cfg[xpc.CfgField.LOCAL_POLL_URI] = 'http://example1.com/blank.html';
cfg[xpc.CfgField.PEER_POLL_URI] = 'http://example2.com/blank.html';
cfg[xpc.CfgField.PEER_URI] = 'http://example2.com/index.html';
var channel = new xpc.CrossPageChannel(cfg);
channel.createPeerIframe(document.body);
channel.registerService('message', messageHandler);
channel.connect(function() {
channel.send('message', 'Hello');
});
function messageHandler(payload) {
console.log(payload);
}
});
goog.require('goog.net.xpc.CrossPageChannel');
goog.require('goog.events');
goog.require('goog.Uri');
goog.require('goog.json');
goog.scope(function() {
var xpc = goog.net.xpc;
var cfg = goog.json.parse(
(new goog.Uri(window.location.href)).getParameterValue('xpc'));
// cfgの内容は検証するべき
var channel = new xpc.CrossPageChannel(cfg);
channel.registerService('message', messageHandler);
channel.connect(function() {});
function messageHandler(payload) {
console.log(payload);
channel.send('message', 'World!');
}
});
ローカルファイルのドラッグ&ドロップをサポート
goog.require('goog.dom');
goog.require('goog.events');
goog.require('goog.events.FileDropHandler');
var handler = new goog.events.FileDropHandler(
goog.dom.getElement('droptarget'), true);
goog.events.listen(
handler, goog.events.FileDropHandler.EventType.DROP, onFileDrop);
function onFileDrop(e) {
// FileList オブジェクトを取得
var files = e.getBrowserEvent().dataTransfer.files;
};
goog.require('goog.events');
goog.require('goog.net.WebSocket');
goog.scope(function() {
var events = goog.events;
var WebSocket = goog.net.WebSocket;
var ws = new WebSocket();
events.listen(ws, WebSocket.EventType.OPENED, onOpen);
events.listen(ws, WebSocket.EventType.MESSAGE, onMessage);
try {
ws.open('ws://example.com/websocket');
} catch(e) {
alert('WebSocketをサポートしていません');
}
function onOpen(e) {
e.target.send('hello');
};
function onMessage(e) {
console.log(e.message);
};
});
goog.require('goog.debug.ErrorHandler');
// WebSocketのイベントハンドラ内で発生した例外は、
// すべてこの関数に転送される
var errHdl = new goog.debug.ErrorHandler(function(e) {
console.log(e);
});
goog.net.WebSocket.protectEntryPoints(errHdl);
// base.js があるディレクトリの相対パス
CLOSURE_BASE_PATH = 'closure-library/closure/goog/';
// bootstrap/webworkers.js, base.js の順に読み込む
importScripts(
CLOSURE_BASE_PATH + 'bootstrap/webworkers.js',
CLOSURE_BASE_PATH + 'base.js');
// goog.require() で必要なスクリプトを読み込む
goog.require('goog.array');
goog.require('goog.json');
//...
Closure Library
http://code.google.com/intl/ja/closure/library/
Closure Compiler
http://code.google.com/intl/ja/closure/compiler/
Closure Template
http://code.google.com/intl/ja/closure/templates/
Closure Linter
http://code.google.com/intl/ja/closure/utilities/
Google JavaScript Style Guide
http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
plovr
http://plovr.com/
Closure Script
http://www.closure-script.com/
ClosureBuilder
http://pypi.python.org/pypi/ClosureBuilder/
node-goog
https://github.com/hsch/node-goog
Closure Kitchen
http://closure-kitchen.appspot.com/