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-library
git clone https://github.com/jarib/google-closure-library.git closure-library
curl -O http://closure-compiler.googlecode.com/files/compiler-latest.zip
unzip compiler-latest.zip
cp 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/