openerp 6.1 - web framework tutorial
DESCRIPTION
Technical Presentation of the new Web client and framework of OpenERP 6.1: architecture, technologies, API, best practices, Javascript pitfalls, etc. DON'T FORGET to scroll each slide to read the NOTES. See also the related presentation about the changes at the server API/framework level: http://www.slideshare.net/openobject/openerp-61-framework-changesTRANSCRIPT
![Page 1: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/1.jpg)
Upgrade Training Web Client
![Page 2: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/2.jpg)
Migrating 6.0 web addons to 6.1
![Page 3: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/3.jpg)
Migrating 6.0 web addons to 6.1
![Page 4: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/4.jpg)
Rewriting 6.0 web addons to 6.1
![Page 5: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/5.jpg)
There is no migrationEverything has been rewritten from scratch
Been at the community days, probably seen it. Not been and looked at OpenERP Web (6.1), probably noticed.
I doubt there’s a line left from the 6.0 codebase (we even split the project itself out), meaning there isn’t a single API left either, meaning you’ll have to rewrite everything as well.
![Page 6: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/6.jpg)
Technological changes
6.0 6.1
Python (+ javascript) Javascript
Mako QWeb
CherryPy Werkzeug
Pages Single Page Interface
Page requests JSON-RPC
Client used to be mostly Python and HTML-ish templates, bulk of logic moved to javascript.* Template language QWeb, reminiscent of Kid/Genshi (though not inspired by them), XML-based
More applicative interaction, more stateful, no page requests and full reloads.
![Page 7: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/7.jpg)
cloc: 6.0
Python
Javascript
Templates
16059
9782
5905
![Page 8: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/8.jpg)
cloc: 6.1
Javascript
Templates
CSS
Python
16925
3693
3064
1874
![Page 9: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/9.jpg)
Deployment changes
• Embedded mode, primary M.O.
• Stand-alone mode for dev/testing
• Official OpenERP bundle embeds
* Web Client has become “just another” OpenERP addon, though remains a different project* Standalone mostly to avoid full server reload when writing Python code** Or to put proxy inbetween
![Page 10: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/10.jpg)
Architecture
![Page 11: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/11.jpg)
Network
OpenERP Web Client Browser
HTTP
HTML
XML-RPC JSON-RPC
6.0’s network arch: typical web frontend, communicates with server via XML-RPC, with client via regular HTTP requests (e.g. link clicks) and HTML pages * Most client logic in the Web Client layer, not really a good fit as OpenERP has lots of client state * Tentative to migrate to more stateful browser-side (iframe then ~pjax), half-hearted and unsuccesful6.1 merges server and web’s python: web’s python becomes a JSON-RPC interface to OpenERP (+ some specific services), vast majority of logic moves to browser
![Page 12: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/12.jpg)
Network
OpenERP Web Client Browser
HTTP
HTML
XML-RPCJSON-RPC
6.0’s network arch: typical web frontend, communicates with server via XML-RPC, with client via regular HTTP requests (e.g. link clicks) and HTML pages * Most client logic in the Web Client layer, not really a good fit as OpenERP has lots of client state * Tentative to migrate to more stateful browser-side (iframe then ~pjax), half-hearted and unsuccesful6.1 merges server and web’s python: web’s python becomes a JSON-RPC interface to OpenERP (+ some specific services), vast majority of logic moves to browser
![Page 13: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/13.jpg)
Layout
![Page 14: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/14.jpg)
Layout
Web Client
![Page 15: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/15.jpg)
LayoutHeaderMenu
Menu (secondary)
![Page 16: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/16.jpg)
Layout
Action Manager
OpenERP’s actions (ir.actions) -> primary drivers of everything (pretty much)No visuals, dispatches to various children based on action executed (window, client) or does work itself and handles result (act_url, server, report_xml)
![Page 17: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/17.jpg)
Layout
View Manager
That slide was hard work
Actual handling of window actions: parses view descriptions, initializes views and handles inter-view communications, view switching, ...
![Page 18: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/18.jpg)
Layout
View (form)
![Page 19: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/19.jpg)
Layout
View (not form either)
View (not form)
![Page 20: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/20.jpg)
Layout: summary• WebClient
• Action Manager
• View Manager (?)
• Views (n)
• Client Action (?)
• ...
![Page 21: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/21.jpg)
Reusable pieces
Dashboard (form view)
![Page 22: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/22.jpg)
Reusable pieces
action manager& client action
action manager&
view manager& list view
![Page 23: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/23.jpg)
Widgets
Base unit of (visual) work. All the blue boxes are “widgets” (a class of openerp web)
Widget ~ MVC view
~ Backbone.View~ NSView~ QAbstractItemView~ Spine.Controller
Couldn’t use “View” due to confusion potential with OpenERP views (list, form, ...)
![Page 24: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/24.jpg)
Widget Responsibilities
• Drawing on-screen (template rendering)
• User events handling (DOM events)
• Delegation
![Page 25: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/25.jpg)
Widgets: templates
• Built-in handling
• Only trivial information
• Widget DOM root set up during rendering
![Page 26: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/26.jpg)
Widgets: events
• No special provisions
• Use regular DOM events handling
![Page 27: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/27.jpg)
Widgets: delegation
• Create children widgets to manage sub-sections
• Implementation detail of the widget
• Cooperative behavior between parent and children
![Page 28: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/28.jpg)
Widgets lifecycle
• Synchronous initialization (construction)
• Template rendering
• DOM insertion
• Asynchronous initialization (secondary)
• [life]
• Cooperative destruction
See code (and detail of APIs) later
* Difficulty of parent/child relationships is not leaving “dangling” events or children** Recursively stops children widgets** Removes widget from DOM** Removes widget from parent** Must explicitly stop children when “killing” them during normal parent life (e.g. ActionManager)
![Page 29: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/29.jpg)
JavaScript
Your new frienemy.
![Page 30: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/30.jpg)
$ var a;$ a = 3.42;$ a = "42";$ a = true;
$ var array = [];$ var obj = {};
$ "foo".indexOf('o');1$ (3).toString();"3"$ [1, 2, 3, 4, 5].slice(1, 3);[2, 3]
Base language has Python similarities:* Dynamic typing* Literal booleans, strings, numbers, arrays, ~hashmap* Object-oriented, methods on a lot of things
![Page 31: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/31.jpg)
> if (condition) {> // action> }
> while (condition) {> // body> }
> for(init; end; each) {> // stuff> }
Statements-heavy, close to C in its core syntax: if, while, for, return (explicit), ...
![Page 32: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/32.jpg)
$ function f1 () {> // things> }$ b = f1;
$ var anon = function () {> // body> };
$ [1, 2, 3].forEach(function (item) {> console.log(item);> });
$ var a = 4;$ var fn = function () {> a = 5;> };$ a;4$ fn();$ a;5
* First-class functions (& higher-order functions)* Anonymous functions* Full closure (read/write)
![Page 33: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/33.jpg)
$ var r = /foo/;$ r.test("a foo");true$ r.exec("a foo");["foo"]
Additional stuff:* Regex literals (~Perl)** RegExp#test(String) -> Boolean** RegExp#exec(String) -> MatchArray** String#match(RegExp) -> MatchArray** String#search(RegExp) -> IndexNumber** String#replace(RegExp|String, String|Function) -> String** String#split([String|RexExp], [Number]) -> Array<String>
![Page 34: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/34.jpg)
Not Python
* Empty array, object is true (empty string is false)* objects only have string keys, few methods (and no map-like methods)* “for (i in array)” does not work “correctly”, “for (o in object)” is tricky, only iterates on key* ‘key in object’?* “weak” types (+/-; ==; ?)* objects v primitives; typeof v instanceof* Very small “standard library”: 10 global functions, 8 global constructors and the Math and JSON namespaces... and the DOM (in browsers)
![Page 35: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/35.jpg)
DOM
* Nodes & Elements
![Page 36: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/36.jpg)
$ var root = document.getElementById('root');$ root[object HTMLDivElement]$ var p = document.createElement('p');$ p.setAttribute('title', "This is a paragraph");$ root.appendChild(p);$ p.appendChild(document.createTextNode("Text Content"));$ p.textContent = "text content";
$ root.childNodes[0];[object Text]$ root.childNodes[1] === p;true$ root.childNodes[0].nodeType;3$ root.childNodes[1].nodeType;1$ p.textContent;"text content"$ p.childNodes[0].data;"text content"
* Very verbose creation and query API [insert node/JSDOM examples** HTML5 APIs/modest improvements (querySelector, querySelectorAll)
![Page 37: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/37.jpg)
$ p.onclick = function () {> writeln("clicked paragraph");> };$ click(p);;clicked paragraph
$ p.onclick = function () {> writeln("clicked paragraph 2");> };$ click(p);clicked paragraph 2
$ p.addEventListener('click', function () {> writeln("clicked paragraph");> });$ click(p);clicked paragraph$ p.addEventListener('click', function () {> writeln("clicked paragraph 2");> });$ click(p);clicked paragraphclicked paragraph 2
* Events** “DOM0” simple but broken** DOM level 2 meh (add) to horrible (trigger)** MSIE < 9 incompatible (global event object, element.fireEvent(name[, options]))
![Page 38: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/38.jpg)
$ var $root = $('#root').empty();$ $root;[[object HTMLDivElement]]$ var $p = $("<p>", {'title': "This is a paragraph"});$ $p;[[object HTMLParagraphElement]]$ $root.append($p);$ $p.text("text content");$ $root.children("p");$ $root.find("p");$ $p.text();"text content"
$ $p.click(function () { writeln("clicked paragraph"); });$ $p.click();clicked paragraph[[object HTMLParagraphElement]]$ $p.click(function () { writeln("clicked paragraph 2"); });$ $p.click();clicked paragraphclicked paragraph 2[[object HTMLParagraphElement]]
![Page 39: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/39.jpg)
Pitfallshttp://bonsaiden.github.com/JavaScript-Garden/
![Page 40: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/40.jpg)
$ {> var glob = 3;> }$ glob;3$ (function () {> var loc = 42;> })();$ loc;Error: Can't find variable: loc
$ var shadow = 3;$ (function () {> var shadow = 4;> writeln(shadow);> })();4$ shadow;3$ (function () {> writeln(local);> var local = 3;> writeln(local);> })();undefined3
$ does_not_exist;Error: Can't find variable: does_not_exist$ (function () {> does_not_exist = 42;> })();$ does_not_exist;42
$ var undef;$ writeln(undef);undefined
Declared but not defined -> undefined (oddly makes sense)Function scope (!C, !java)* Python has UnboundLocalError v NameError, JS has undefined v ErrorImplicit declaration -> global
![Page 41: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/41.jpg)
$ var somevar = 3;$ somevar;3$ somevar = 4;$ somevar;4$ (function () {> somevar = 5;> })();$ somevar;5$ (function () {> var somevar = 42;> (function () {> somevar = 36;> writeln(somevar);> })();> writeln(somevar);> })();3636$ somevar;5
$ var fns = [];$ for (var i=0; i != 10; ++i) {> fns.push(function () { writeln(i); });> }$ fns.forEach(function (f) { f(); });10101010101010101010
* Writable closures (not possible in Python 2)* Danger! closures in loops
![Page 42: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/42.jpg)
$ writeln(null);null$ typeof null;"object"$ null instanceof Object;false
$ writeln(undefined);undefined$ typeof undefined;"undefined"$ undefined === null;false$ undefined == null;true$ writeln((function () {})());undefined$ writeln((function () { return; })());undefined$ (function (a) { writeln(a); })();undefined$ writeln(({}).does_not_exist);undefined$ var no_such_variable;$ writeln(no_such_variable);undefined
$ NaN;NaN$ typeof NaN;"number"$ NaN === NaN;false$ NaN == NaN;false$ isNaN(NaN);true$ parseInt("foo");NaN$ parseInt("1foo");1$ 1 - "foo";NaN$ +"foo";NaN
Python -> None and exceptions (errors)JS -> null (None), undefined, NaN and exceptions.
* null !== undefined, but null == undefined* typeof null === “object”* Access undefined property -> undefined** Access property set to undefined -> also undefined* NaN exists in Python but very rare, more common in JS due to weak typing e.g. +”foo”** NaN != NaN, use isNaN** typeof NaN === ‘number’
![Page 43: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/43.jpg)
$ function Foo() {};$ var foo = new Foo();$ foo instanceof Foo;true$ var bar = Foo();$ writeln(bar);undefined$ var a = function () { this.b = "b"; };$ a.b = function () { this.c = "c"; };$ a.b.c = function () {};$ new a.b.c instanceof (a.b.c);true$ new a.b().c instanceof (a.b.c);false$ (new (function () { this.ok = true; })).ok;true$ var baz = new Foo;
JavaScript OO is “interesting” (mostly bad kind)Not going to dwelve far into it, but knowledge of *constructors* useful as object layers are generally sugar over JS OO.* Constructors are functions used in special context** Any function can be used as a constructor (!= is useful a constructor)* new $type() vs $type()* $type an expression, ends at first parens by default (kinda weird)** new a.b.c -> new (a.b.c); new a.b().c -> (new a.b()).c** parens optional
![Page 44: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/44.jpg)
$ this;[object DOMWindow]Actual output:[]$ this === window;true
$ var fn = function (f) { f(this); }$ var a = {b: fn};$ fn(function (t) {> writeln(t === window);> });true$ a.b(function (t) {> writeln(t === a);> });true$ new fn(function (t) {> writeln(t instanceof fn);> });true{}$ var c = {};$ c.b = a.b;$ c.b(function (t) {> writeln(t === c);> });true
$ var o = {};$ fn.call(o, function (t) {> writeln(t === o);> });true$ fn.apply(o, [function (t) {> writeln(t === o);> }]);true
* Call site decides of `this` in callee* default (global, function): “global object” (browsers: window)* Not transitive** b() -> `this` is window** a.b() -> `this` is a** new a.b -> `this` is instance of `a.b`** c.b = a.b; c.b() -> `this` is c** Function#call, Function#apply -> `this` is arg0
![Page 45: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/45.jpg)
$ var a = {> attr: 1,> b: function () {> writeln(this.attr);> return function () {> writeln(this.attr);> };> }> };$ var f = a.b();1$ f();undefined
$ a = {> attr: 1,> b: function () {> var self = this;> return function () {> writeln(self.attr);> };> }> };$ var f = a.b();$ f();1
$ a = {> attr: 1,> b: function () {> var fn = function () {> writeln(this.attr);> };> return fn.bind(this);> }> };$ var f = a.b();$ f();1
* In closures, use alias (`var self = this`)** Function#bind, _.bind** Widget#proxy
![Page 46: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/46.jpg)
JavaScript concurrency
![Page 47: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/47.jpg)
• JS runtime is a reactor (pattern)
• Event loop
• Single threaded
• Blocking (synchronous)
![Page 48: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/48.jpg)
Actually not what you’ll have with network requests: page (or even browser) frozen, no dialog no nothing.
![Page 49: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/49.jpg)
• Continuation Passing Style (CPS)
• Call long-running operation
• Pass “continuation” callback
• Called whenever operation completes
![Page 50: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/50.jpg)
1. Forwarding (all methods must take 1/2 callbacks)
2. Composition (waiting on multiple events)
3. Post-hoc decisions (act on an event which may or may not have happened)
Callback Mess
* Lower evolutivity** Many methods need extra 2 params, harder to read &use** Harder to add new params (callback @end)** Params post-callbacks hard to read/unreadable** Costlier for methods which may become async*** sync -> async transformation horrible so want to have API correct early* Ad-hoc mess of flags &stuff* Need to complement with flags as well
![Page 51: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/51.jpg)
Deferred
![Page 52: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/52.jpg)
• AKA Futures, promises
• (Success, Error)
• Pipelining
• Composition
• Promises/A
• jQuery.Deferred, #pipe, jQuery.when
* Stateful, tri-state (pending, resolved, rejected)* Callback queues** Deferred#then** Deferred#done/Deferred#fail/Deferred#always* Single state change* $.Deferred#pipe: pipelining (async chains)* $.when: composition** Original: wrap value in deferred
![Page 53: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/53.jpg)
Tooling
![Page 54: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/54.jpg)
• Webkit Developer Tools / CDT
• Firebug
• Dragonfly
• IE Developer Tools
Actual capabilities vary, some things might work better in some tools than in other
1. WDT/CDT ~ Firebug2. Dragonfly3. IE9 DevTools4. IE8 DevTools
![Page 55: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/55.jpg)
Console
* Can actually get CLI JS console (à la `python`): spidermonkey or nodejs* Access to page content (and libraries)* Test code snippets** jsfiddle** jsbin** tinker.io** ...* Interactively inspect objects
![Page 56: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/56.jpg)
Console API
``console`` object, functions for programmatic printing of information* Basic logging (log, debug, info, warn, error, exception)* Formatting (group/groupEnd)* Timers (time/timeEnd)* Profiling (profile/profileEnd)* trace* dir* count
![Page 57: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/57.jpg)
Visual Debugger
* Breakpoints (visual or programmatic)* Conditional breakpoints* call stack* Locals** CONSOLE
![Page 58: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/58.jpg)
DOM Inspector
* “Inspect Element” entry point* Edit DOM (as HTML text, add/remove/change attributes)* Visualize margin/padding/borders* CSS adjustments** Metrics section (overview)** enable/disable rules* DOM breakpoints (flaky?)
![Page 59: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/59.jpg)
Network
* List requests, time, latency, payload size* Request & response header* Request payload* Response payload (formatted JSON)
![Page 60: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/60.jpg)
Profiler
Nothing much to say, usual visual profiler, have to learn on your own
![Page 61: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/61.jpg)
Console (again)
command-line API http://getfirebug.com/wiki/index.php/Command_Line_API
![Page 62: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/62.jpg)
OpenERP Web APIs
![Page 63: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/63.jpg)
6.1 Caveat
• API stability (and the lack thereof)
![Page 64: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/64.jpg)
• Python controller
• RPC (connection, dataset)
• QWeb
• Widget
• View
• form.Widget
• Client actions
• Translations
• underscore.js
• Dialog
• CrashManager
![Page 65: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/65.jpg)
Classes & subclassing
* JS OO somewhat similar to Python’s* Single-inheritance* No sugar for classes, plumbing a bit hard to get your head around and verbose** Helper: Class & Class.extend** this._super, doesn’t play well with async
![Page 66: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/66.jpg)
QWeb
![Page 67: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/67.jpg)
• openerp.web.qweb
• QWeb.render(template, context) => String
• t-name
• t-call
Usage
![Page 68: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/68.jpg)
Logic
• t-set t-value
• t-if
• t-foreach t-as
![Page 69: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/69.jpg)
Output• t-esc
• t-escf
• t-raw
• t-rawf
• t-att
• t-att-*
• t-attf-*
![Page 70: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/70.jpg)
API: Widget
Client actionsregistries (instance.web.client_actions)<iframe class="youtube-player" type="text/html" width="640" height="385" t-attf-src="http://youtube.com/embed/#{widget.params.id}" frameborder="0"></iframe>* sn2l2_v6Ur8 * pOA9PGYeP3E* oHg5SJYRHA0 * wmkoJGm6y6k* ZZ5LpwO-An4 * eQemvyyJ--g* qWkUFxItWmU * hXlzci1rKNM
![Page 71: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/71.jpg)
• Web-oriented keys: css, js, qweb
• ‘static’ folder
• module pattern: private namespace, initialization code
![Page 72: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/72.jpg)
• Widget#init :: * => ()
• Widget#render :: () => String
• Widget#start :: () => Deferred
• Widget#stop :: () => ()
![Page 73: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/73.jpg)
API: Search Fields
meetings
![Page 74: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/74.jpg)
• Field
• non-standard cycle
• get_context, get_domain
{instance.web.search.fields}* Weird cycle** Render everything (recursive, defaults)** Bind (element_id, in template context)** Start* dygraphs.com** dygraphs.com/dygraph-combined.js** new Dygraph(element, CSV_string)
![Page 75: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/75.jpg)
API: Form Fields
hr -> email field{instance.web.form.widgets}Also weird cycle/management* $element set to parent (table cell), in start() (_super() call required)
![Page 76: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/76.jpg)
• Field#value :: *
• Field#set_value :: * => Deferred
• Field#on_ui_change :: () => ()
• Field#update_dom :: () => ()
• Field#validate :: () => ()
#value -> current value for the widget#set_value -> form sets value on widget#on_ui_change -> signal value change via UI to form* Should have set #value# update_dom -> resync non-value DOM (readonly, invalid, required)# validate -> set/unset “invalid”
![Page 77: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/77.jpg)
Debugging
![Page 78: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/78.jpg)
Debugging with OpenERP Web
![Page 79: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/79.jpg)
Debugging OpenERP Web
![Page 80: OpenERP 6.1 - Web Framework Tutorial](https://reader034.vdocuments.site/reader034/viewer/2022042614/555ad9f2d8b42a024a8b4eb8/html5/thumbnails/80.jpg)
Third-party Embedding
Install “share”Share button “link or embed”Put in HTML file on diskpython -mSimpleHTTPServer