├── .gitignore
├── 001-hello-world
├── app
│ ├── main.js
│ └── theme
│ │ └── main.css
└── index.html
├── 002-button-click
├── app
│ ├── main.js
│ └── theme
│ │ └── main.css
└── index.html
├── 003-dialog
├── app
│ ├── main.js
│ ├── theme
│ │ └── main.css
│ └── view
│ │ └── dialog.html
└── index.html
├── 004-menubar
├── app
│ ├── main.js
│ └── theme
│ │ └── main.css
└── index.html
├── 005-contextmenu
├── app
│ ├── main.js
│ └── theme
│ │ └── main.css
└── index.html
├── 006-layout
├── NOTES.md
├── app
│ ├── main.js
│ ├── theme
│ │ └── main.css
│ └── view
│ │ ├── second.html
│ │ └── third.html
└── index.html
├── 007-custom-alert-dialog
├── NOTES.md
├── app
│ ├── dialog
│ │ ├── AlertDialog.html
│ │ └── AlertDialog.js
│ ├── main.js
│ └── theme
│ │ └── main.css
└── index.html
├── 008-custom-confirm-dialog
├── app
│ ├── dialog
│ │ ├── ConfirmDialog.html
│ │ └── ConfirmDialog.js
│ ├── main.js
│ └── theme
│ │ └── main.css
└── index.html
├── 009-form
├── app
│ ├── main.js
│ └── theme
│ │ └── main.css
└── index.html
├── 010-form-validation
├── app
│ ├── main.js
│ ├── theme
│ │ └── main.css
│ └── validate
│ │ └── custom.js
└── index.html
├── 011-form-ajax-validator
├── app
│ ├── form
│ │ └── AjaxValidationTextBox.js
│ ├── main.js
│ └── theme
│ │ └── main.css
├── index.html
└── validate.php
├── 012-login-form-dialog
├── app
│ ├── dialog
│ │ ├── LoginDialog.html
│ │ └── LoginDialog.js
│ ├── main.js
│ └── theme
│ │ └── main.css
├── index.html
└── login.php
├── 013-dojo-amd
├── app
│ ├── asset
│ │ └── wtf.jpg
│ ├── main.js
│ ├── theme
│ │ └── main.css
│ └── view
│ │ └── hello.html
└── index.html
├── 014-mvc-form
├── app
│ ├── controller
│ │ └── FormController.js
│ ├── main.js
│ ├── theme
│ │ └── main.css
│ └── view
│ │ └── form.html
├── form.php
└── index.html
├── 015-grid
├── app
│ ├── main.js
│ └── theme
│ │ └── main.css
└── index.html
├── 016-dynamic-grid
├── app
│ ├── controller
│ │ └── GridController.js
│ ├── grid
│ │ └── Grid.js
│ ├── main.js
│ ├── theme
│ │ └── main.css
│ └── view
│ │ └── grid.html
└── index.html
├── README.md
├── fabfile.py
├── favicon.png
├── index.html
├── reset.css
└── tutorial
├── 001.md
├── 002.md
├── 003.md
├── 004.md
├── 005.md
├── 006.md
├── 007.md
├── 008.md
├── 009.md
├── 010.md
├── 011.md
├── 012.md
├── 013.md
├── 014.md
├── 015.md
├── 016.md
├── about.md
└── index.json
/.gitignore:
--------------------------------------------------------------------------------
1 | /.settings
2 | /.buildpath
3 | /.project
4 | /.pydevproject
5 | /vendor
6 | /dist.tar
7 | /dist.tar.gz
8 | /composer.phar
9 | /composer.lock
10 | /fabfile.pyc
11 | /build.properties
12 | *.pyc
13 |
--------------------------------------------------------------------------------
/001-hello-world/app/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'require',
3 | 'dojo/ready'
4 | ], function(require, ready){
5 |
6 | var app = {};
7 |
8 | ready(function(){
9 | app.alert('Hello World!');
10 | });
11 |
12 | /**
13 | * Display alert dialog.
14 | */
15 | app.alert = function(message){
16 | require(['dijit/Dialog'], function(Dialog){
17 | var dialog = new Dialog({ title: 'Hello!', content: message });
18 | dialog.show();
19 | });
20 | };
21 |
22 | return app;
23 | });
24 |
--------------------------------------------------------------------------------
/001-hello-world/app/theme/main.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body {
4 | width:100%;
5 | height:100%;
6 | margin:0;
7 | padding:0;
8 | overflow:hidden;
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/001-hello-world/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dojo Tutorial
7 |
8 |
9 |
10 |
11 |
23 |
24 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/002-button-click/app/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'require',
3 | 'dojo/ready',
4 | 'dijit/registry'
5 | ], function(require, ready, registry){
6 |
7 | var app = {};
8 |
9 | ready(function(){
10 | dojo.connect(registry.byId('btnClickMe'), 'onClick', app.onButtonClick);
11 | console.log('loaded!');
12 | });
13 |
14 | /**
15 | * Display alert dialog.
16 | */
17 | app.alert = function(message){
18 | require(['dijit/Dialog'], function(Dialog){
19 | var dialog = new Dialog({ title: 'Hello!', content: message });
20 | dialog.show();
21 | });
22 | };
23 |
24 | /**
25 | * Button click action.
26 | */
27 | app.onButtonClick = function(){
28 | app.alert('You just have clicked this button!');
29 | };
30 |
31 | return app;
32 | });
33 |
--------------------------------------------------------------------------------
/002-button-click/app/theme/main.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body {
4 | width:100%;
5 | height:100%;
6 | margin:0;
7 | padding:0;
8 | overflow:hidden;
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/002-button-click/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dojo Tutorial
7 |
8 |
9 |
10 |
11 |
23 |
24 |
37 |
38 |
39 |
40 | Click me!
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/003-dialog/app/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'require',
3 | 'dojo/ready',
4 | 'dijit/registry'
5 | ], function(require, ready, registry){
6 |
7 | var app = {};
8 |
9 | ready(function(){
10 | dojo.connect(registry.byId('btnClickMe'), 'onClick', app.onButtonClick);
11 | console.log('loaded!');
12 | });
13 |
14 | /**
15 | * Button click action.
16 | */
17 | app.onButtonClick = function(){
18 | require(['dijit/Dialog'], function(Dialog){
19 | var dialog = new Dialog({
20 | title: "Some dialog",
21 | href: appConfig.baseUrl + '/app/view/dialog.html',
22 | style: "width:400px"
23 | });
24 | dialog.show();
25 | });
26 | };
27 |
28 | return app;
29 | });
30 |
--------------------------------------------------------------------------------
/003-dialog/app/theme/main.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body {
4 | width:100%;
5 | height:100%;
6 | margin:0;
7 | padding:0;
8 | overflow:hidden;
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/003-dialog/app/view/dialog.html:
--------------------------------------------------------------------------------
1 | Dialog
2 |
3 | This is a custom dialog.
4 | Content was loaded from a remote html file.
5 |
6 |
--------------------------------------------------------------------------------
/003-dialog/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dojo Tutorial
7 |
8 |
9 |
10 |
11 |
23 |
24 |
37 |
38 |
39 |
40 | Click me!
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/004-menubar/app/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'require',
3 | 'dojo/ready',
4 | 'dijit/registry'
5 | ], function(require, ready, registry){
6 |
7 | var app = {};
8 |
9 | ready(function(){
10 | dojo.connect(registry.byId('mbtnHelp'), 'onClick', app.onHelpButtonClick);
11 | console.log('loaded!');
12 | });
13 |
14 | /**
15 | * Display alert dialog.
16 | */
17 | app.alert = function(message){
18 | require(['dijit/Dialog'], function(Dialog){
19 | var dialog = new Dialog({ title: 'Hello!', content: message });
20 | dialog.show();
21 | });
22 | };
23 |
24 | /**
25 | * Help button click action.
26 | */
27 | app.onHelpButtonClick = function(){
28 | app.alert('This is a Dojo MenuBar example.');
29 | };
30 |
31 | return app;
32 | });
33 |
--------------------------------------------------------------------------------
/004-menubar/app/theme/main.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body {
4 | width:100%;
5 | height:100%;
6 | margin:0;
7 | padding:0;
8 | overflow:hidden;
9 | }
10 |
11 | .appIconEditCopy { background-image:url('http://cdn.devgrid.net/icon/nuvola/1.0/16x16/actions/editcopy.png'); }
12 | .appIconEditCut { background-image:url('http://cdn.devgrid.net/icon/nuvola/1.0/16x16/actions/editcut.png'); }
13 | .appIconEditPaste { background-image:url('http://cdn.devgrid.net/icon/nuvola/1.0/16x16/actions/editpaste.png'); }
14 | .appIconExit { background-image:url('http://cdn.devgrid.net/icon/nuvola/1.0/16x16/actions/exit.png'); }
15 | .appIconFileNew { background-image:url('http://cdn.devgrid.net/icon/nuvola/1.0/16x16/actions/filenew.png'); }
16 | .appIconFileOpen { background-image:url('http://cdn.devgrid.net/icon/nuvola/1.0/16x16/actions/fileopen.png'); }
17 | .appIconFileSave { background-image:url('http://cdn.devgrid.net/icon/nuvola/1.0/16x16/actions/filesave.png'); }
18 | .appIconFileSaveAs { background-image:url('http://cdn.devgrid.net/icon/nuvola/1.0/16x16/actions/filesaveas.png'); }
19 | .appIconFileClose { background-image:url('http://cdn.devgrid.net/icon/nuvola/1.0/16x16/actions/fileclose.png'); }
20 | .appIconHelp { background-image:url('http://cdn.devgrid.net/icon/nuvola/1.0/16x16/actions/help.png'); }
21 | .appIconRedo { background-image:url('http://cdn.devgrid.net/icon/nuvola/1.0/16x16/actions/redo.png'); }
22 | .appIconUndo { background-image:url('http://cdn.devgrid.net/icon/nuvola/1.0/16x16/actions/undo.png'); }
23 |
--------------------------------------------------------------------------------
/004-menubar/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dojo Tutorial
7 |
8 |
9 |
10 |
11 |
23 |
24 |
37 |
38 |
39 |
40 |
41 |
42 |
File
43 |
44 |
New
45 |
Open
46 |
Save
47 |
Save As...
48 |
Close
49 |
Exit
50 |
51 |
52 |
53 |
Edit
54 |
55 |
Undo
56 |
Redo
57 |
58 |
Cut
59 |
Copy
60 |
Paste
61 |
62 |
63 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/005-contextmenu/app/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'require',
3 | 'dojo',
4 | 'dojo/ready',
5 | 'dojo/on',
6 | 'dojo/dom'
7 | ], function(require, dojo, ready, on, dom){
8 |
9 | var app = {};
10 |
11 | ready(function(){
12 | on(dom.byId('mbtnAction1'), 'click', function(){ app.alert('Click Action 1'); });
13 | on(dom.byId('mbtnAction2'), 'click', function(){ app.alert('Click Action 2'); });
14 | on(dom.byId('mbtnAction3'), 'click', function(){ app.alert('Click Action 3'); });
15 | console.log('loaded!');
16 | });
17 |
18 | /**
19 | * Display alert dialog.
20 | */
21 | app.alert = function(message){
22 | require(['dijit/Dialog'], function(Dialog){
23 | var dialog = new Dialog({ title: 'Hello!', content: message, style: 'width:200px' });
24 | dialog.show();
25 | });
26 | };
27 |
28 | return app;
29 | });
30 |
--------------------------------------------------------------------------------
/005-contextmenu/app/theme/main.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body {
4 | width:100%;
5 | height:100%;
6 | margin:0;
7 | padding:0;
8 | overflow:hidden;
9 | }
10 |
11 | .appIconEditCopy { background-image:url('http://cdn.devgrid.net/icon/nuvola/1.0/16x16/actions/editcopy.png'); }
12 | .appIconEditCut { background-image:url('http://cdn.devgrid.net/icon/nuvola/1.0/16x16/actions/editcut.png'); }
13 | .appIconEditPaste { background-image:url('http://cdn.devgrid.net/icon/nuvola/1.0/16x16/actions/editpaste.png'); }
14 |
15 | #contextMenu {
16 | position:absolute;
17 | opacity:0;
18 | }
19 |
--------------------------------------------------------------------------------
/005-contextmenu/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dojo Tutorial
7 |
8 |
9 |
10 |
11 |
23 |
24 |
37 |
38 |
39 |
40 |
41 | Click somewhere with right mouse button.
42 |
43 |
44 |
45 |
Cut
46 |
Copy
47 |
Paste
48 |
49 |
50 |
Submenu
51 |
52 |
Action 1
53 |
Action 2
54 |
Action 3
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/006-layout/NOTES.md:
--------------------------------------------------------------------------------
1 | - Border container has to have explicitly set width and height!
2 |
3 |
--------------------------------------------------------------------------------
/006-layout/app/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'require',
3 | 'dojo/ready'
4 | ], function(require, ready){
5 |
6 | var app = {};
7 |
8 | ready(function(){
9 | console.log('loaded!');
10 | });
11 |
12 | /**
13 | * Display alert dialog.
14 | */
15 | app.alert = function(message){
16 | require(['dijit/Dialog'], function(Dialog){
17 | var dialog = new Dialog({ title: 'Hello!', content: message });
18 | dialog.show();
19 | });
20 | };
21 |
22 | return app;
23 | });
24 |
--------------------------------------------------------------------------------
/006-layout/app/theme/main.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body {
4 | width:100%;
5 | height:100%;
6 | margin:0;
7 | padding:0;
8 | overflow:hidden;
9 | }
10 |
11 | .appBorderContainer {
12 | width:100%;
13 | height:100%;
14 | }
15 |
16 | .appLeadingAccordionContainer {
17 | width:300px;
18 | }
19 |
20 | .appTrailingAccordionContainer {
21 | width:200px;
22 | }
--------------------------------------------------------------------------------
/006-layout/app/view/second.html:
--------------------------------------------------------------------------------
1 | This is content from a remote html file.
2 |
--------------------------------------------------------------------------------
/006-layout/app/view/third.html:
--------------------------------------------------------------------------------
1 |
4 | This is content from a remote html file that is being parsed by Dojo.
5 | Click me!
6 |
9 |
10 |
--------------------------------------------------------------------------------
/006-layout/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dojo Tutorial
7 |
8 |
9 |
10 |
11 |
23 |
24 |
37 |
38 |
39 |
40 |
41 |
42 | This is the header content pane.
43 |
44 |
45 |
46 | First pane content.
47 |
48 |
49 | Second pane content.
50 |
51 |
52 | Third pane content.
53 |
54 |
55 |
56 |
57 | First tab inline content.
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | First pane content.
67 |
68 |
69 | Second pane content.
70 |
71 |
72 |
73 | This is the footer content pane.
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/007-custom-alert-dialog/NOTES.md:
--------------------------------------------------------------------------------
1 | - Parser requires explicitly loaded dijit/form/Button
2 |
3 |
--------------------------------------------------------------------------------
/007-custom-alert-dialog/app/dialog/AlertDialog.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | x
6 |
7 |
8 |
11 |
12 | OK
13 |
14 |
--------------------------------------------------------------------------------
/007-custom-alert-dialog/app/dialog/AlertDialog.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'dojo/_base/declare',
3 | 'dijit/Dialog',
4 | 'dijit/_WidgetsInTemplateMixin',
5 | 'dojo/text!./AlertDialog.html',
6 | 'dijit/form/Button'
7 | ], function(declare, Dialog, _WidgetsInTemplateMixin, template){
8 | return declare('app.dialog.AlertDialog', [Dialog, _WidgetsInTemplateMixin], {
9 | title: 'Alert',
10 | templateString: template
11 | });
12 | });
13 |
--------------------------------------------------------------------------------
/007-custom-alert-dialog/app/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'require',
3 | 'dojo/ready'
4 | ], function(require, ready){
5 |
6 | var app = {};
7 |
8 | ready(function(){
9 | app.alert('Hello World!');
10 | });
11 |
12 | /**
13 | * Display alert dialog.
14 | */
15 | app.alert = function(message){
16 | require(['app/dialog/AlertDialog'], function(Dialog){
17 | var dialog = new Dialog({ content: message });
18 | dialog.show();
19 | });
20 | };
21 |
22 | return app;
23 | });
24 |
--------------------------------------------------------------------------------
/007-custom-alert-dialog/app/theme/main.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body {
4 | width:100%;
5 | height:100%;
6 | margin:0;
7 | padding:0;
8 | overflow:hidden;
9 | }
10 |
11 | .appAlertDialog {
12 | min-width:150px;
13 | }
14 | .appAlertDialog .appDialogPaneButtons,
15 | .appAlertDialog .dijitDialogPaneContent {
16 | text-align:center;
17 | background: #fff;
18 | }
19 |
--------------------------------------------------------------------------------
/007-custom-alert-dialog/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dojo Tutorial
7 |
8 |
9 |
10 |
11 |
23 |
24 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/008-custom-confirm-dialog/app/dialog/ConfirmDialog.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | x
6 |
7 |
8 |
11 |
12 | Yes
13 | No
14 |
15 |
--------------------------------------------------------------------------------
/008-custom-confirm-dialog/app/dialog/ConfirmDialog.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'dojo/_base/declare',
3 | 'dijit/Dialog',
4 | 'dijit/_WidgetsInTemplateMixin',
5 | 'dojo/text!./ConfirmDialog.html',
6 | 'dijit/form/Button'
7 | ], function(declare, Dialog, _WidgetsInTemplateMixin, template){
8 | return declare('app.dialog.ConfirmDialog', [Dialog, _WidgetsInTemplateMixin], {
9 |
10 | title: 'Confirm',
11 | templateString: template,
12 |
13 | constructor: function(options){
14 | if (options.message) {
15 | this.content = options.message;
16 | }
17 | }
18 |
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/008-custom-confirm-dialog/app/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'require',
3 | 'dojo/ready',
4 | 'dijit/registry'
5 | ], function(require, ready, registry){
6 |
7 | var app = {};
8 |
9 | ready(function(){
10 | dojo.connect(registry.byId('btnClickMe'), 'onClick', app.onButtonClick);
11 | console.log('loaded!');
12 | });
13 |
14 | /**
15 | * Display confirm dialog.
16 | */
17 | app.confirm = function(options){
18 | require(['app/dialog/ConfirmDialog'], function(Dialog){
19 | var dialog = new Dialog(options);
20 | dialog.show();
21 | });
22 | };
23 |
24 | /**
25 | * Button click action.
26 | */
27 | app.onButtonClick = function(){
28 | app.confirm({
29 | message: 'Do you like this demo?',
30 | onExecute: function(){
31 | console.log('great! :)');
32 | },
33 | onCancel: function(){
34 | console.log('too bad :<');
35 | }
36 | });
37 | };
38 |
39 | return app;
40 | });
41 |
--------------------------------------------------------------------------------
/008-custom-confirm-dialog/app/theme/main.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body {
4 | width:100%;
5 | height:100%;
6 | margin:0;
7 | padding:0;
8 | overflow:hidden;
9 | }
10 |
11 | .appConfirmDialog {
12 | min-width:150px;
13 | }
14 | .appConfirmDialog .appDialogPaneButtons,
15 | .appConfirmDialog .dijitDialogPaneContent {
16 | text-align:center;
17 | background: #fff;
18 | }
19 |
--------------------------------------------------------------------------------
/008-custom-confirm-dialog/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dojo Tutorial
7 |
8 |
9 |
10 |
11 |
23 |
24 |
37 |
38 |
39 |
40 | Click me!
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/009-form/app/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'require',
3 | 'dojo/ready'
4 | ], function(require, ready){
5 |
6 | var app = {};
7 |
8 | ready(function(){
9 | console.log('loaded!');
10 | });
11 |
12 | /**
13 | * Display alert dialog.
14 | */
15 | app.alert = function(message){
16 | require(['dijit/Dialog'], function(Dialog){
17 | var dialog = new Dialog({ title: 'Hello!', content: message });
18 | dialog.show();
19 | });
20 | };
21 |
22 | return app;
23 | });
24 |
--------------------------------------------------------------------------------
/009-form/app/theme/main.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body {
4 | width:100%;
5 | min-height:100%;
6 | margin:0;
7 | padding:0;
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/009-form/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dojo Tutorial
7 |
8 |
9 |
10 |
11 |
23 |
24 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | Johnnie Walker
52 | Jack Daniels
53 | Grant's Scotch
54 |
55 |
56 | Johnnie Walker
57 | Jack Daniels
58 | Grant's Scotch
59 |
60 |
61 | Johnnie Walker
62 | Jack Daniels
63 | Grant's Scotch
64 |
65 |
66 | Johnnie Walker
67 | Jack Daniels
68 | Grant's Scotch
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | 0%
77 |
78 | 50%
79 |
80 | 100%
81 |
82 |
83 |
84 | 25%
85 |
86 | 75%
87 |
88 |
89 |
90 |
91 |
92 | 0%
93 |
94 | 50%
95 |
96 | 100%
97 |
98 |
99 |
100 | 25%
101 |
102 | 75%
103 |
104 |
105 |
106 |
107 |
Submit
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/010-form-validation/app/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'require',
3 | 'dojo/ready',
4 | 'dojox/validate/web',
5 | 'app/validate/custom'
6 | ], function(require, ready){
7 |
8 | var app = {};
9 |
10 | ready(function(){
11 | console.log('loaded!');
12 | });
13 |
14 | /**
15 | * Display alert dialog.
16 | */
17 | app.alert = function(message){
18 | require(['dijit/Dialog'], function(Dialog){
19 | var dialog = new Dialog({ title: 'Hello!', content: message });
20 | dialog.show();
21 | });
22 | };
23 |
24 | return app;
25 | });
26 |
--------------------------------------------------------------------------------
/010-form-validation/app/theme/main.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body {
4 | width:100%;
5 | height:100%;
6 | margin:0;
7 | padding:0;
8 | overflow:hidden;
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/010-form-validation/app/validate/custom.js:
--------------------------------------------------------------------------------
1 | define("app/validate/custom", ["dojo", "dojo/_base/lang"], function(dojo, lang){
2 | var validate = lang.getObject("dojox.validate", true);
3 |
4 | validate.isOver666 = function(value, flags){
5 | console.log('validate');
6 | return (parseInt(value) > 666);
7 | };
8 |
9 | return validate;
10 | });
11 |
--------------------------------------------------------------------------------
/010-form-validation/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dojo Tutorial
7 |
8 |
9 |
10 |
11 |
23 |
24 |
37 |
38 |
39 |
40 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/011-form-ajax-validator/app/form/AjaxValidationTextBox.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'dojo/_base/declare',
3 | 'dojo',
4 | 'dijit/form/ValidationTextBox'
5 | ], function(declare, dojo, ValidationTextBox){
6 | return declare('app.form.AjaxValidationTextBox', [ValidationTextBox], {
7 |
8 | ajaxUrl: null,
9 | ajaxLock: false,
10 | ajaxResult: false,
11 |
12 | isValid: function(){
13 | var widget = this;
14 | if (!this.ajaxLock && this.ajaxUrl) {
15 | this.ajaxLock = true;
16 | dojo.xhrGet({
17 | url: widget.ajaxUrl + '?value=' + widget.get('value'),
18 | handleAs: 'json',
19 | load: function(result){
20 | widget.ajaxResult = result;
21 | widget.validate();
22 | widget.ajaxLock = false;
23 | }
24 | });
25 | }
26 | return this.ajaxResult;
27 | }
28 |
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/011-form-ajax-validator/app/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'require',
3 | 'dojo/ready'
4 | ], function(require, ready){
5 |
6 | var app = {};
7 |
8 | ready(function(){
9 | console.log('loaded!');
10 | });
11 |
12 | /**
13 | * Display alert dialog.
14 | */
15 | app.alert = function(message){
16 | require(['dijit/Dialog'], function(Dialog){
17 | var dialog = new Dialog({ title: 'Hello!', content: message });
18 | dialog.show();
19 | });
20 | };
21 |
22 | return app;
23 | });
24 |
--------------------------------------------------------------------------------
/011-form-ajax-validator/app/theme/main.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body {
4 | width:100%;
5 | height:100%;
6 | margin:0;
7 | padding:0;
8 | overflow:hidden;
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/011-form-ajax-validator/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dojo Tutorial
7 |
8 |
9 |
10 |
11 |
23 |
24 |
37 |
38 |
39 |
40 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/011-form-ajax-validator/validate.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | x
6 |
7 |
8 |
18 |
19 | Login
20 |
21 |
--------------------------------------------------------------------------------
/012-login-form-dialog/app/dialog/LoginDialog.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'dojo/_base/declare',
3 | 'dojo/_base/lang',
4 | 'dojo',
5 | 'dijit/Dialog',
6 | 'dijit/_WidgetsInTemplateMixin',
7 | 'dojo/text!./LoginDialog.html',
8 | 'dijit/form/Button',
9 | 'dijit/form/Form',
10 | 'dijit/form/TextBox',
11 | 'dojox/layout/TableContainer'
12 | ], function(declare, lang, dojo, Dialog, _WidgetsInTemplateMixin, template){
13 | return declare('app.dialog.LoginDialog', [Dialog, _WidgetsInTemplateMixin], {
14 |
15 | title: 'Login required',
16 | style: 'width:400px',
17 | templateString: template,
18 |
19 | constructor: function(options){
20 | lang.mixin(this, options);
21 | },
22 |
23 | onSubmit: function(){
24 | var widget = this;
25 | dojo.xhrPost({
26 | url: this.url,
27 | form: this.loginForm.id,
28 | handleAs: 'json',
29 | load: function(response){
30 | if (response.status == 'success') {
31 | widget.onSuccess(response);
32 | } else {
33 | widget.onFailure(response);
34 | }
35 | }
36 | });
37 | },
38 |
39 | onSuccess: function(response){
40 |
41 | },
42 |
43 | onFailure: function(response){
44 |
45 | }
46 |
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/012-login-form-dialog/app/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'require',
3 | 'dojo/ready',
4 | 'dijit/registry'
5 | ], function(require, ready, registry){
6 |
7 | var app = {};
8 |
9 | ready(function(){
10 | dojo.connect(registry.byId('btnClickMe'), 'onClick', app.onButtonClick);
11 | console.log('loaded!');
12 | });
13 |
14 | /**
15 | * Display alert dialog.
16 | */
17 | app.alert = function(message){
18 | require(['dijit/Dialog'], function(Dialog){
19 | var dialog = new Dialog({ title: 'Alert', content: message });
20 | dialog.show();
21 | });
22 | };
23 |
24 | /**
25 | * Display login dialog.
26 | */
27 | app.login = function(options){
28 | require(['app/dialog/LoginDialog'], function(Dialog){
29 | var dialog = new Dialog(options);
30 | dialog.show();
31 | });
32 | };
33 |
34 | /**
35 | * Button click action.
36 | */
37 | app.onButtonClick = function(){
38 | app.login({
39 | url: appConfig.baseUrl + '/login.php',
40 | onSuccess: function(response){
41 | console.log(response.message);
42 | this.onExecute(); // Hide dialog.
43 | app.alert('You are successfully logged in!');
44 | },
45 | onFailure: function(response){
46 | console.log(response.message);
47 | app.alert('Invalid login or password!');
48 | }
49 | });
50 | };
51 |
52 | return app;
53 | });
54 |
--------------------------------------------------------------------------------
/012-login-form-dialog/app/theme/main.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body {
4 | width:100%;
5 | height:100%;
6 | margin:0;
7 | padding:0;
8 | overflow:hidden;
9 | }
10 |
11 | .appConfirmDialog {
12 | min-width:150px;
13 | }
14 | .appConfirmDialog .appDialogPaneButtons,
15 | .appConfirmDialog .dijitDialogPaneContent {
16 | text-align:center;
17 | background: #fff;
18 | }
19 |
--------------------------------------------------------------------------------
/012-login-form-dialog/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dojo Tutorial
7 |
8 |
9 |
10 |
11 |
23 |
24 |
37 |
38 |
39 |
40 | Username: admin
41 | Password: secret
42 |
43 | Click me!
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/012-login-form-dialog/login.php:
--------------------------------------------------------------------------------
1 | 'success',
5 | 'message' => 'Logged in'
6 | ));
7 |
8 | } else {
9 | echo json_encode(array(
10 | 'status' => 'failure',
11 | 'message' => 'Invalid login or password'
12 | ));
13 | }
14 |
--------------------------------------------------------------------------------
/013-dojo-amd/app/asset/wtf.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cepa/dojo-tutorial/e46a82904b5d16686b1167887a5705aa74385930/013-dojo-amd/app/asset/wtf.jpg
--------------------------------------------------------------------------------
/013-dojo-amd/app/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'require',
3 | 'dojo/ready',
4 | 'dijit/registry',
5 | ], function (require, ready, registry) {
6 |
7 | var app = {};
8 |
9 | ready(function () {
10 | console.log('loaded');
11 | app.renderDemo();
12 | });
13 |
14 | app.renderDemo = function () {
15 | require(['dojo/text!app/view/hello.html', 'jQuery', 'Handlebars'], function (view) {
16 | // Render view.
17 | var template = Handlebars.compile(view);
18 | var html = template({
19 | date: (new Date()).toString(),
20 | imageUrl: appConfig.baseUrl + '/app/asset/wtf.jpg'
21 | });
22 |
23 | var contentPane = registry.byId('contentPane');
24 | contentPane.setContent(html);
25 |
26 | ready(function () {
27 | $('#bClickMe').click(function () {
28 | $('.hiddenImage').show('slow');
29 | console.log('jquery click');
30 | });
31 | });
32 | });
33 | };
34 |
35 | return app;
36 | });
37 |
--------------------------------------------------------------------------------
/013-dojo-amd/app/theme/main.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body {
4 | width:100%;
5 | height:100%;
6 | margin:0;
7 | padding:0;
8 | overflow:hidden;
9 | }
10 |
11 | .appContentPane {
12 | border:0 !important;
13 | padding:0 !important;
14 | }
15 |
16 | .hiddenImage {
17 | display: none;
18 | }
19 |
--------------------------------------------------------------------------------
/013-dojo-amd/app/view/hello.html:
--------------------------------------------------------------------------------
1 | Hello!
2 | today is: {{date}}
3 |
4 | Click me!
5 |
--------------------------------------------------------------------------------
/013-dojo-amd/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dojo Tutorial
7 |
8 |
9 |
10 |
11 |
39 |
40 |
43 |
44 |
45 |
46 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/014-mvc-form/app/controller/FormController.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'dojo/_base/declare',
3 | 'dojo',
4 | 'dijit/registry',
5 | 'dojo/ready',
6 | 'Handlebars'
7 | ], function (declare, dojo, registry, ready) {
8 | return declare('app.controller.FormController', [], {
9 |
10 | entity: {},
11 | formId: null,
12 | postUrl: null,
13 |
14 | constructor: function (options) {
15 | console.log('contstructor');
16 | dojo.safeMixin(this, options);
17 | },
18 |
19 | renderForm: function (contentPane) {
20 | var controller = this;
21 | require(['dojo/text!app/view/form.html'], function (view) {
22 | // Render view in content pane.
23 | var template = Handlebars.compile(view);
24 | contentPane.set('content', template({
25 | formId: controller.formId,
26 | postUrl: controller.postUrl,
27 | entity: controller.entity
28 | }));
29 |
30 | // Connect button onClick action when content pane is rendered.
31 | ready(function () {
32 | dojo.connect(registry.byId('bSubmit'), 'onClick', function () {
33 | dojo.xhrPost({
34 | form: dojo.byId(controller.formId),
35 | handleAs: 'text',
36 | load: function (response) {
37 | console.log('Success!');
38 | controller.renderResponse(response);
39 | },
40 | error: function () {
41 | console.log('Error!');
42 | }
43 | });
44 | });
45 | });
46 | });
47 | },
48 |
49 | renderResponse: function (response) {
50 | var html = '' + response + '
';
51 | var responseContentPane = registry.byId(this.formId + 'Response');
52 | responseContentPane.set('content', html);
53 | }
54 |
55 | });
56 | });
57 |
--------------------------------------------------------------------------------
/014-mvc-form/app/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'require',
3 | 'dojo/ready',
4 | 'dijit/registry',
5 | 'dojox/validate/web'
6 | ], function (require, ready, registry) {
7 |
8 | var app = {};
9 |
10 | ready(function () {
11 | console.log('loaded');
12 | require(['app/controller/FormController'], function (FormController) {
13 | var controller = new FormController({
14 | formId: 'myForm',
15 | postUrl: appConfig.baseUrl + '/form.php',
16 | entity: {
17 | firstName: 'Santa',
18 | lastName: 'Claus',
19 | email: 'santa@claus.com'
20 | }
21 | });
22 | controller.renderForm(registry.byId('contentPane'));
23 | });
24 | });
25 |
26 | return app;
27 | });
28 |
--------------------------------------------------------------------------------
/014-mvc-form/app/theme/main.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body {
4 | width:100%;
5 | height:100%;
6 | margin:0;
7 | padding:0;
8 | overflow:hidden;
9 | }
10 |
11 | .appContentPane {
12 | border:0 !important;
13 | padding:0 !important;
14 | }
15 |
--------------------------------------------------------------------------------
/014-mvc-form/app/view/form.html:
--------------------------------------------------------------------------------
1 | Form
2 |
10 |
11 |
12 | Server response
13 |
14 |
--------------------------------------------------------------------------------
/014-mvc-form/form.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dojo Tutorial
7 |
8 |
9 |
10 |
11 |
34 |
35 |
38 |
39 |
40 |
41 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/015-grid/app/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'require',
3 | 'dojo/ready',
4 | 'dijit/registry'
5 | ], function (require, ready, registry) {
6 |
7 | var app = {};
8 |
9 | app.data = {
10 | identified: 'id',
11 | items: [
12 | {
13 | id: 1,
14 | first_name: 'Johnnie',
15 | last_name: 'Walker',
16 | email_address: 'johnnie@walker.com',
17 | age: 18
18 | },
19 | {
20 | id: 1,
21 | first_name: 'Jack',
22 | last_name: 'Daniels',
23 | email_address: 'jack@daniels.com',
24 | age: 3
25 | },
26 | {
27 | id: 1,
28 | first_name: 'Moonshine',
29 | last_name: 'Booze',
30 | email_address: 'get@wasted.com',
31 | age: 0
32 | },
33 | ]
34 | };
35 |
36 | ready(function () {
37 | console.log('loaded!');
38 | app.showGrid('gridPlaceholder', app.data);
39 | });
40 |
41 | app.showGrid = function (placeholderId, data) {
42 | require(['dojox/grid/EnhancedGrid', 'dojo/data/ItemFileWriteStore'], function (Grid, Store) {
43 | var store = new Store({
44 | data: data
45 | });
46 |
47 | var grid = new Grid({
48 | id: 'myGrid',
49 | store: store,
50 | structure: [[
51 | {
52 | name: 'First name',
53 | field: 'first_name',
54 | width: '200px'
55 | },
56 | {
57 | name: 'Last name',
58 | field: 'last_name',
59 | width: '200px'
60 | },
61 | {
62 | name: 'Email',
63 | field: 'email_address',
64 | width: '350px'
65 | },
66 | {
67 | name: 'Age',
68 | field: 'age',
69 | width: '80px'
70 | },
71 | ]]
72 | });
73 | grid.placeAt(placeholderId);
74 | grid.startup();
75 | });
76 | };
77 |
78 | return app;
79 | });
80 |
--------------------------------------------------------------------------------
/015-grid/app/theme/main.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body {
4 | width:100%;
5 | height:100%;
6 | margin:0;
7 | padding:0;
8 | overflow:hidden;
9 | }
10 |
11 | .appGrid {
12 | width:100%;
13 | height:100%;
14 | }
15 |
--------------------------------------------------------------------------------
/015-grid/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dojo Tutorial
7 |
8 |
9 |
10 |
11 |
12 |
24 |
25 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/016-dynamic-grid/app/controller/GridController.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'dojo/_base/declare',
3 | 'dijit/registry',
4 | 'handlebars'
5 | ], function (declare, registry) {
6 | return declare('app.controller.GridController', [], {
7 |
8 | renderGrid: function (title, data) {
9 | require([
10 | 'dojox/layout/ContentPane',
11 | 'app/grid/Grid',
12 | 'dojo/data/ItemFileWriteStore',
13 | 'dojo/text!app/view/grid.html'
14 | ], function (ContentPane, Grid, Store, view) {
15 | // Generate random id.
16 | var unique = Math.abs(Math.floor(Math.random() * 0xffff));
17 |
18 | // Create handlebars template and render content.
19 | var template = Handlebars.compile(view);
20 | var content = template({ unique: unique });
21 |
22 | // Create content pane for grid.
23 | var contentPane = new ContentPane({
24 | title: title,
25 | closable: true,
26 | content: content
27 | });
28 |
29 | // Render content pane.
30 | var tabContainer = registry.byId('tabContainer');
31 | tabContainer.addChild(contentPane);
32 | tabContainer.selectChild(contentPane);
33 |
34 | // Create grid.
35 | var grid = new Grid({
36 | id: 'grid' + unique,
37 | store: new Store({ data: data })
38 | });
39 | grid.placeAt('gridPlaceholder' + unique);
40 | grid.startup();
41 | });
42 | }
43 |
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/016-dynamic-grid/app/grid/Grid.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'dojo/_base/declare',
3 | 'dojox/grid/EnhancedGrid'
4 | ], function (declare, EnhancedGrid) {
5 | return declare('app.grid.Grid', [EnhancedGrid], {
6 |
7 | structure: [[
8 | {
9 | name: 'First name',
10 | field: 'first_name',
11 | width: '200px'
12 | },
13 | {
14 | name: 'Last name',
15 | field: 'last_name',
16 | width: '200px'
17 | },
18 | {
19 | name: 'Email',
20 | field: 'email_address',
21 | width: '350px'
22 | },
23 | {
24 | name: 'Age',
25 | field: 'age',
26 | width: '80px'
27 | }
28 | ]]
29 |
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/016-dynamic-grid/app/main.js:
--------------------------------------------------------------------------------
1 | define([
2 | 'require',
3 | 'dojo',
4 | 'dojo/ready',
5 | 'dijit/registry'
6 | ], function (require, dojo, ready, registry) {
7 |
8 | var app = {};
9 |
10 | app.idx = 1;
11 |
12 | app.getData = function () {
13 | return {
14 | identified: 'id',
15 | items: [
16 | {
17 | id: 1,
18 | first_name: 'Johnnie',
19 | last_name: 'Walker',
20 | email_address: 'johnnie@walker.com',
21 | age: 18
22 | },
23 | {
24 | id: 1,
25 | first_name: 'Jack',
26 | last_name: 'Daniels',
27 | email_address: 'jack@daniels.com',
28 | age: 3
29 | },
30 | {
31 | id: 1,
32 | first_name: 'Moonshine',
33 | last_name: 'Booze',
34 | email_address: 'get@wasted.com',
35 | age: 0
36 | },
37 | ]
38 | };
39 | };
40 |
41 | ready(function () {
42 | console.log('loaded!');
43 |
44 | dojo.connect(registry.byId('mbShowGrid'), 'onClick', function () {
45 | require(['app/controller/GridController'], function (Controller) {
46 | var controller = new Controller();
47 | controller.renderGrid('Grid ' + app.idx++, app.getData());
48 | });
49 | });
50 | });
51 |
52 | return app;
53 | });
54 |
--------------------------------------------------------------------------------
/016-dynamic-grid/app/theme/main.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body {
4 | width:100%;
5 | height:100%;
6 | margin:0;
7 | padding:0;
8 | overflow:hidden;
9 | }
10 |
11 | .appGrid {
12 | width:100%;
13 | height:100%;
14 | }
15 |
16 | .appContentPane {
17 | border:0 !important;
18 | padding:0 !important;
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/016-dynamic-grid/app/view/grid.html:
--------------------------------------------------------------------------------
1 | Grid will be displayed here.
2 |
--------------------------------------------------------------------------------
/016-dynamic-grid/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dojo Tutorial
7 |
8 |
9 |
10 |
11 |
12 |
35 |
36 |
39 |
40 |
41 |
42 |
43 |
44 |
49 |
50 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Dojo Toolkit 1.9 Tutorial
2 |
3 | _This repository is no longer maintained!_
4 |
5 | This is a tutorial with simple examples how to solve real life scenarios with Dojo and how to create Rich Internet Applications / Singe Page Applications mostly backend oriented.
6 | The tutorial was started because of lack of good examples that can introduce Dojo step by step, which by far is most likely one of the most powerful and comprehensive javascript toolkits in the world offering a lot more ready to use widgets than any other popular javascript framework.
7 |
8 | ## Website & examples
9 | Visit http://dojotutorial.org/ where you can find working examples from each tutorial.
10 |
11 | ## Tutorials
12 | Each lesson is in the _tutorial_ directory.
13 |
14 | * 001 - **Hello world** - Create a boilerplate app with dojo.
15 | * 002 - **Button click** - Handle button click action.
16 | * 003 - **Dialog** - Display basic dialog box.
17 | * 004 - **Menubar** - Display sample menu bar with drop down menus and icons.
18 | * 005 - **Context menu** - Display context menu triggered by mouse right button click.
19 | * 006 - **Layout** - Construct sample dijit layout.
20 | * 007 - **Custom alert dialog** - Create custom alert box widget.
21 | * 008 - **Custom confirm dialog** - Create custom confirm box widget.
22 | * 009 - **Form** - Display various types of dijit form elements.
23 | * 010 - **Form validation** - Validate form values with builtin validators.
24 | * 011 - **Form ajax validator** - Create custom form validator that talks with remote server using Ajax to validate a value.
25 | * 012 - **Login form dialog** - Create login box widget and handle submiting login data.
26 | * 013 - **Dojo AMD** - How to use Dojo AMD, how to integrate external libraries like jQuery and Handlebars.
27 | * 014 - **MVC form** - Create simple MVC app to controll a form.
28 | * 015 - **Grid** - Display basic grid.
29 | * 016 - **Dynamic grid** - Create multiple grid on fly, and embed them in content panes.
30 |
31 | ## Contributing
32 | This tutorial is far from perfect and I'm still learning while writing it, so feel free to send me pull requests if you see any mistakes, and I would love to attach more tutorials if you have any.
33 |
--------------------------------------------------------------------------------
/fabfile.py:
--------------------------------------------------------------------------------
1 | import time
2 | import fabric.api as fapi
3 | import fabric.contrib.files as ffiles
4 |
5 | fapi.env.project_name = 'dojo-tutorial'
6 | fapi.env.distfile = 'dist.tar.gz'
7 | fapi.env.path = '/var/www'
8 |
9 | fapi.env.user = 'root'
10 | fapi.env.disable_known_hosts = True
11 |
12 | @fapi.task
13 | @fapi.parallel
14 | def rollout():
15 | fapi.env.release = time.strftime('%Y%m%d%H%M%S')
16 | project_path = '%(path)s/%(project_name)s' % fapi.env
17 | release_path = project_path + '/' + fapi.env.release
18 | current_path = project_path + '/current'
19 | fapi.run('mkdir -p ' + release_path)
20 | fapi.put('%(distfile)s' % fapi.env, release_path)
21 | fapi.run('cd ' + release_path + ' && tar zxf %(distfile)s' % fapi.env)
22 | if (ffiles.exists(current_path)):
23 | fapi.run('cd ' + project_path + ' && unlink current')
24 | fapi.run('cd ' + project_path + ' && ln -s %(release)s current' % fapi.env)
25 | fapi.run('cd ' + release_path + ' && rm -f %(distfile)s' % fapi.env)
26 |
27 | @fapi.task
28 | @fapi.parallel
29 | def purge():
30 | fapi.run('rm -rf %(path)s/%(project_name)s' % fapi.env)
31 |
32 | if 'rollout' in fapi.env.tasks:
33 | fapi.local('rm -rf {}'.format(fapi.env.distfile))
34 | fapi.local('tar --exclude={} -zcf {} *'.format(fapi.env.distfile, fapi.env.distfile))
35 |
--------------------------------------------------------------------------------
/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cepa/dojo-tutorial/e46a82904b5d16686b1167887a5705aa74385930/favicon.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Dojo Tutorial
4 |
5 |
6 |
7 | Visit dojotutorial.org
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/reset.css:
--------------------------------------------------------------------------------
1 | @CHARSET "UTF-8";
2 |
3 | html, body { border:0; margin:0; padding:0; width:100%; min-height:100%; }
4 | body { font-size:12px; font-family: Helvetica, Arial, "sans-serif" }
5 | h1, h2, h3, h4, h5, h6 { margin:0; padding:0; font-weight:normal; }
6 | ul, ol { margin:0px 0 0px 16px; padding:0; }
7 | blockquote { margin:22px 40px; padding:0; }
8 | img { border:0; }
9 | a, a:visited { text-decoration:none; }
10 | form { margin:0; padding:0; }
11 | input, select, textarea { border:1px solid #888888; padding:1px; margin:0px; }
12 | textarea { line-height:1.25; }
13 | label { cursor:pointer; }
14 | table { border:0; margin:0 0 0 0; padding:0; }
15 | table tr td { padding:2px; }
16 | p { margin:0; padding:0; }
17 | pre, code { line-height:1em; padding:0; margin:0; }
18 |
19 | .left { float:left; }
20 | .right { float:right; }
21 | .clear { clear:both; }
22 |
23 | .text-left { text-align:left; }
24 | .text-right { text-align:right; }
25 | .text-center { text-align:center; }
26 |
27 | .normal { font-weight:normal; }
28 | .bold { font-weight:bold; }
29 |
--------------------------------------------------------------------------------
/tutorial/001.md:
--------------------------------------------------------------------------------
1 | # 001. Hello World
2 |
3 | ## Beginning
4 | This is the first step of how to get into frontend development with Dojo Toolkit.
5 | The very first step presents how to init Dojo and how to separate the html *view* from javascript *logic*.
6 | ***
7 |
8 |
9 | ### Source code & demo
10 |
11 | [Live demo](http://demo.dojotutorial.org/001-hello-world/)
12 |
13 | [Source code](https://github.com/cepa/dojo-tutorial/tree/master/001-hello-world)
14 |
15 | ***
16 |
17 |
18 | ### Application structure
19 | The basic directory structure of the application is very simple and it will evolve later:
20 |
21 | - **/index.html** - The application entry point.
22 | - **/app** - The application module.
23 | - **/app/main.js** - The main script for *app* module.
24 |
25 | ***
26 |
27 |
28 | ### Markup
29 | The entry point of our Dojo application is index.html, here the magic starts.
30 | ~~~ html5
31 |
32 |
33 |
34 |
35 |
36 | Dojo Tutorial
37 |
38 |
39 |
40 |
41 |
53 |
54 |
67 |
68 |
69 |
70 |
71 | ~~~
72 |
73 | First of all we choose the Dojo theme. In this example it is theme named *claro*.
74 | ~~~ html5
75 |
76 | ~~~
77 |
78 | Next we configure the Application, in order to get the *app* module loaded we need to extract the *base path* from the current url.
79 | ~~~ javascript
80 | appConfig = {
81 | baseUrl: location.href.substring(0,location.href.lastIndexOf("/")+1)
82 | };
83 | ~~~
84 |
85 | And now we configure Dojo to *parse* html content on load and add required modules automagically when they are requested.
86 | ~~~ javascript
87 | dojoConfig = {
88 | parseOnLoad: true
89 | };
90 | ~~~
91 |
92 | At last but not least we load Dojo.
93 | ~~~ html5
94 |
95 | ~~~
96 | ***
97 |
98 |
99 | ### Load modules with RequireJS
100 | In this tutorial from the very beginning we will use *RequireJS* to load modules and dependencies. The application will reside in the *app* folder with all of its source code.
101 | To point the location of the application correctly it was required to get the *base path* from the browser.
102 | Loading application module looks like this:
103 | ~~~ javascript
104 | require(
105 | {
106 | packages: [
107 | { name: 'app', location: appConfig.baseUrl + '/app/' }
108 | ]
109 | },
110 | [
111 | "app"
112 | ]
113 | );
114 | ~~~
115 | The *require* function comes from *RequireJS* and the rest is pretty stratightforward.
116 | ***
117 |
118 |
119 | ### app/main.js
120 | The application module starts in file **/app/main.js** which is loaded by default by *RequireJS*.
121 | ~~~ javascript
122 | define([
123 | 'require',
124 | 'dojo/ready'
125 | ], function(require, ready){
126 |
127 | var app = {};
128 |
129 | ready(function(){
130 | app.alert('Hello World!');
131 | });
132 |
133 | /**
134 | * Display alert dialog.
135 | */
136 | app.alert = function(message){
137 | require(['dijit/Dialog'], function(Dialog){
138 | var dialog = new Dialog({ title: 'Hello!', content: message });
139 | dialog.show();
140 | });
141 | };
142 |
143 | return app;
144 | });
145 | ~~~
146 | This piece of code will *define* a new object named **app** visible in the project namespace.
147 | The *app* object is our application *controller* and the closure inside *define* function works as a constructor.
148 |
149 | The first array part requests two dependencies: *require* and *dojo/ready* and they are passed to the closure.
150 |
151 | Inside the *app* object we have one method named *alert* for displaying a *Dialog* widget. When the application is loaded it will trigger the closure inside *ready* function which will load *dijit/Dialog* widget and display a dialog box.
152 | ***
153 |
154 |
155 |
156 |
--------------------------------------------------------------------------------
/tutorial/002.md:
--------------------------------------------------------------------------------
1 | # 002. Button Click
2 |
3 | Display dijit Button and handle onClick event.
4 | ***
5 |
6 |
7 | ### Source code & demo
8 |
9 | [Live demo](http://demo.dojotutorial.org/002-button-click/)
10 |
11 | [Source code](https://github.com/cepa/dojo-tutorial/tree/master/002-button-click)
12 |
13 | ***
14 |
15 |
16 | ### Markup
17 | In the first **001** tutorial you can see how to load and initialize Dojo Toolkit. To display a dojo button you can use the following markup:
18 | ~~~ html5
19 |
20 |
21 | Click me!
22 |
23 |
24 | ~~~
25 | The *data-dojo-type* links the HTML tag with a dojo type, in this example dojo parser will load dijit/form/Button class.
26 |
27 | And thats all! The real logic starts in javascript part.
28 | ***
29 |
30 |
31 | ### app/main.js
32 | Because *main.js* is loaded before *body* DOM element, it is required to wait untill the document is ready before we can bind anything, this is why the *ready* method was used:
33 | ~~~ javascript
34 | ready(function(){
35 | //...
36 | });
37 | ~~~
38 | Anything in this closure will be executed when the document is ready.
39 |
40 | To connect an action to buttons *onClick* event you can use *dojo.connect* method:
41 | ~~~ javascript
42 | dojo.connect(registry.byId('btnClickMe'), 'onClick', app.onButtonClick);
43 | ~~~
44 | This line will try to find a button node in *dijit registry* by id *btnClickMe* and bind *app.onButtonClick* closure from the *app* object.
45 |
46 | When button is clicked the *app.onButtonClick* is executed, in it we have access to the *app* object so it is possible to display a custom alert box:
47 | ~~~ javascript
48 | app.onButtonClick = function(){
49 | app.alert('You just have clicked this button!');
50 | };
51 | ~~~
52 |
53 | Full code:
54 | ~~~ javascript
55 | define([
56 | 'require',
57 | 'dojo/ready',
58 | 'dijit/registry'
59 | ], function(require, ready, registry){
60 |
61 | var app = {};
62 |
63 | ready(function(){
64 | dojo.connect(registry.byId('btnClickMe'), 'onClick', app.onButtonClick);
65 | console.log('loaded!');
66 | });
67 |
68 | /**
69 | * Display alert dialog.
70 | */
71 | app.alert = function(message){
72 | require(['dijit/Dialog'], function(Dialog){
73 | var dialog = new Dialog({ title: 'Hello!', content: message });
74 | dialog.show();
75 | });
76 | };
77 |
78 | /**
79 | * Button click action.
80 | */
81 | app.onButtonClick = function(){
82 | app.alert('You just have clicked this button!');
83 | };
84 |
85 | return app;
86 | });
87 | ~~~
88 | ***
89 |
90 |
91 |
--------------------------------------------------------------------------------
/tutorial/003.md:
--------------------------------------------------------------------------------
1 | # 003. Dialog
2 |
3 | Display dijit Dialog with content loaded from separate html file.
4 | ***
5 |
6 |
7 | ### Source code & demo
8 |
9 | [Live demo](http://demo.dojotutorial.org/003-dialog/)
10 |
11 | [Source code](https://github.com/cepa/dojo-tutorial/tree/master/003-dialog)
12 |
13 | ***
14 |
15 |
16 | ### Markup
17 | In this example the Dialog is created dynamically in JavaScript when the *Click me!* button is clicked, the markup for the button is very simple:
18 | ~~~ html5
19 |
20 |
21 | Click me!
22 |
23 |
24 | ~~~
25 | ***
26 |
27 |
28 | ### Bind dijit Button onClick
29 | Like in the previous tutorial, to bind a function to button's onClick event the *dojo.connect* function is used:
30 | ~~~ javascript
31 | ready(function(){
32 | dojo.connect(registry.byId('btnClickMe'), 'onClick', app.onButtonClick);
33 | });
34 | ~~~
35 | ***
36 |
37 |
38 | ### Display dijit Dialog
39 | First we need to load the *dijit/Dialog* class, it is done with the *require* function, next when the class is loaded the *function(Dialog)* is executed.
40 | The *dijit/Dialog* has two interesting options, first is *content* which can be used to directly display some text on the dialog box, and the second is *href* which will load a remote file with an async http call.
41 | ~~~ javascript
42 | require(['dijit/Dialog'], function(Dialog){
43 | var dialog = new Dialog({
44 | title: "Some dialog",
45 | href: appConfig.baseUrl + '/app/view/dialog.html',
46 | style: "width:400px"
47 | });
48 | dialog.show();
49 | });
50 | ~~~
51 | Content file:
52 | ~~~ html5
53 | Dialog
54 |
55 | This is a custom dialog.
56 | Content was loaded from a remote html file.
57 |
58 | ~~~
59 | ***
60 |
61 |
62 | ### app/main.js
63 | ~~~ javascript
64 | define([
65 | 'require',
66 | 'dojo/ready',
67 | 'dijit/registry'
68 | ], function(require, ready, registry){
69 |
70 | var app = {};
71 |
72 | ready(function(){
73 | dojo.connect(registry.byId('btnClickMe'), 'onClick', app.onButtonClick);
74 | console.log('loaded!');
75 | });
76 |
77 | /**
78 | * Button click action.
79 | */
80 | app.onButtonClick = function(){
81 | require(['dijit/Dialog'], function(Dialog){
82 | var dialog = new Dialog({
83 | title: "Some dialog",
84 | href: appConfig.baseUrl + '/app/view/dialog.html',
85 | style: "width:400px"
86 | });
87 | dialog.show();
88 | });
89 | };
90 |
91 | return app;
92 | });
93 | ~~~
94 | ***
95 |
96 |
--------------------------------------------------------------------------------
/tutorial/004.md:
--------------------------------------------------------------------------------
1 | # 004. Menubar
2 |
3 | Display dijit Menubar with dropdowns and custom icons.
4 | ***
5 |
6 |
7 | ### Source code & demo
8 |
9 | [Live demo](http://demo.dojotutorial.org/004-menubar/)
10 |
11 | [Source code](https://github.com/cepa/dojo-tutorial/tree/master/004-menubar)
12 |
13 | ***
14 |
15 |
16 | ### Markup
17 | ~~~ html5
18 |
19 |
20 |
21 |
22 |
File
23 |
24 |
New
25 |
Open
26 |
Save
27 |
Save As...
28 |
Close
29 |
Exit
30 |
31 |
32 |
33 |
Edit
34 |
35 |
Undo
36 |
Redo
37 |
38 |
Cut
39 |
Copy
40 |
Paste
41 |
42 |
43 |
49 |
50 |
51 |
52 | ~~~
53 | ***
54 |
55 |
56 | ### app/main.js
57 | ~~~ javascript
58 | define([
59 | 'require',
60 | 'dojo/ready',
61 | 'dijit/registry'
62 | ], function(require, ready, registry){
63 |
64 | var app = {};
65 |
66 | ready(function(){
67 | dojo.connect(registry.byId('mbtnHelp'), 'onClick', app.onHelpButtonClick);
68 | console.log('loaded!');
69 | });
70 |
71 | /**
72 | * Display alert dialog.
73 | */
74 | app.alert = function(message){
75 | require(['dijit/Dialog'], function(Dialog){
76 | var dialog = new Dialog({ title: 'Hello!', content: message });
77 | dialog.show();
78 | });
79 | };
80 |
81 | /**
82 | * Help button click action.
83 | */
84 | app.onHelpButtonClick = function(){
85 | app.alert('This is a Dojo MenuBar example.');
86 | };
87 |
88 | return app;
89 | });
90 | ~~~
91 | ***
92 |
93 |
--------------------------------------------------------------------------------
/tutorial/005.md:
--------------------------------------------------------------------------------
1 | # 005. Context Menu
2 |
3 | Create application context menu activated with right mouse button click.
4 | ***
5 |
6 |
7 | ### Source code & demo
8 |
9 | [Live demo](http://demo.dojotutorial.org/005-contextmenu/)
10 |
11 | [Source code](https://github.com/cepa/dojo-tutorial/tree/master/005-contextmenu)
12 |
13 | ***
14 |
15 |
16 | ### Markup
17 | ~~~ html5
18 |
19 |
20 |
21 | Click somewhere with right mouse button.
22 |
23 |
24 |
25 |
Cut
26 |
Copy
27 |
Paste
28 |
29 |
30 |
Submenu
31 |
32 |
Action 1
33 |
Action 2
34 |
Action 3
35 |
36 |
37 |
38 |
39 |
40 | ~~~
41 | Dojo *dijit/Menu* has a special attribute named *contextMenuForWindow* thats binds the right mouse button click, using it you can simply create a context menu without manual handling of all kind of mouse events.
42 | When you open the live demo, you need to click right mouse button to activate the context menu.
43 | ***
44 |
45 |
46 | ### app/main.js
47 | ~~~ javascript
48 | define([
49 | 'require',
50 | 'dojo',
51 | 'dojo/ready',
52 | 'dojo/on',
53 | 'dojo/dom'
54 | ], function(require, dojo, ready, on, dom){
55 |
56 | var app = {};
57 |
58 | ready(function(){
59 | on(dom.byId('mbtnAction1'), 'click', function(){ app.alert('Click Action 1'); });
60 | on(dom.byId('mbtnAction2'), 'click', function(){ app.alert('Click Action 2'); });
61 | on(dom.byId('mbtnAction3'), 'click', function(){ app.alert('Click Action 3'); });
62 | console.log('loaded!');
63 | });
64 |
65 | /**
66 | * Display alert dialog.
67 | */
68 | app.alert = function(message){
69 | require(['dijit/Dialog'], function(Dialog){
70 | var dialog = new Dialog({ title: 'Hello!', content: message, style: 'width:200px' });
71 | dialog.show();
72 | });
73 | };
74 |
75 | return app;
76 | });
77 | ~~~
78 | The buttons on the *Submenu* dropdown are binded to javascript functions using *dojo/on* function.
79 | ***
80 |
81 |
--------------------------------------------------------------------------------
/tutorial/006.md:
--------------------------------------------------------------------------------
1 | # 006. Layout
2 |
3 |
4 | ***
5 |
6 |
7 | ### Source code & demo
8 |
9 | [Live demo](http://demo.dojotutorial.org/006-layout/)
10 |
11 | [Source code](https://github.com/cepa/dojo-tutorial/tree/master/006-layout)
12 |
13 | ***
14 |
15 |
16 | ### Markup
17 | ~~~ html5
18 |
19 |
20 |
21 |
22 | This is the header content pane.
23 |
24 |
25 |
26 | First pane content.
27 |
28 |
29 | Second pane content.
30 |
31 |
32 | Third pane content.
33 |
34 |
35 |
36 |
37 | First tab inline content.
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | First pane content.
47 |
48 |
49 | Second pane content.
50 |
51 |
52 |
53 | This is the footer content pane.
54 |
55 |
56 |
57 |
58 | ~~~
59 | ***
60 |
61 |
62 | ### app/main.js
63 | ~~~ javascript
64 | define([
65 | 'require',
66 | 'dojo/ready'
67 | ], function(require, ready){
68 |
69 | var app = {};
70 |
71 | ready(function(){
72 | console.log('loaded!');
73 | });
74 |
75 | /**
76 | * Display alert dialog.
77 | */
78 | app.alert = function(message){
79 | require(['dijit/Dialog'], function(Dialog){
80 | var dialog = new Dialog({ title: 'Hello!', content: message });
81 | dialog.show();
82 | });
83 | };
84 |
85 | return app;
86 | });
87 | ~~~
88 | ***
89 |
90 |
91 | ### app/view/second.html
92 | ~~~ html5
93 | This is content from a remote html file.
94 | ~~~
95 | ***
96 |
97 |
98 | ### app/view/third.html
99 | ~~~ html5
100 |
103 | This is content from a remote html file that is being parsed by Dojo.
104 | Click me!
105 |
108 |
109 | ~~~
110 | ***
111 |
112 |
113 |
--------------------------------------------------------------------------------
/tutorial/007.md:
--------------------------------------------------------------------------------
1 | # 007. Custom Alert Dialog
2 |
3 | Create a custom alert dialog widget with overriden template.
4 | ***
5 |
6 |
7 | ### Source code & demo
8 |
9 | [Live demo](http://demo.dojotutorial.org/007-custom-alert-dialog/)
10 |
11 | [Source code](https://github.com/cepa/dojo-tutorial/tree/master/007-custom-alert-dialog)
12 |
13 | ***
14 |
15 |
16 | ### Index markup
17 | ~~~ html5
18 |
19 |
20 | ~~~
21 | This time there is no default markup, we will display an alert dialog programatically.
22 | ***
23 |
24 |
25 | ### Custom dijit widget (app/dialog/AlertDialog.js)
26 | Dojo with RequireJS has a powerful capabilities in object oriented programming, the best feature is a simplified structured way to create custom widgets that extends other classes.
27 | Following code is the simplest declaration of a custom widget class named **AlertDialog** and places in **app/dialog/AlertDialog.js**:
28 | ~~~ javascript
29 | define([
30 | 'dojo/_base/declare',
31 | 'dijit/Dialog',
32 | 'dijit/_WidgetsInTemplateMixin',
33 | 'dojo/text!./AlertDialog.html',
34 | 'dijit/form/Button'
35 | ], function(declare, Dialog, _WidgetsInTemplateMixin, template){
36 | return declare('app.dialog.AlertDialog', [Dialog, _WidgetsInTemplateMixin], {
37 | title: 'Alert',
38 | templateString: template
39 | });
40 | });
41 | ~~~
42 | ***
43 |
44 |
45 | ### Dijit widget template (app/dialog/AlertDialog.html)
46 | Layout of each dijit widgets is declared in markup. The difference between a common html file and a template file are properties named *data-dojo-attach-point* and *data-dojo-attach-event* which allows to bind markup to actions declared in javascript. Following template is based on the default one from dijit Dialog, with a small extension made of dijit Button. Template file is placed in **app/dialog/AlertDialog.html**.
47 | ~~~ html5
48 |
49 |
50 |
51 |
52 | x
53 |
54 |
55 |
58 |
59 | OK
60 |
61 |
62 | ~~~
63 | ***
64 |
65 |
66 | ### app/main.js
67 | Again we trigger the alert dialog from the main.js script.
68 | ~~~ javascript
69 | define([
70 | 'require',
71 | 'dojo/ready'
72 | ], function(require, ready){
73 |
74 | var app = {};
75 |
76 | ready(function(){
77 | app.alert('Hello World!');
78 | });
79 |
80 | /**
81 | * Display alert dialog.
82 | */
83 | app.alert = function(message){
84 | require(['app/dialog/AlertDialog'], function(Dialog){
85 | var dialog = new Dialog({ content: message });
86 | dialog.show();
87 | });
88 | };
89 |
90 | return app;
91 | });
92 | ~~~
93 | ***
94 |
95 |
96 |
--------------------------------------------------------------------------------
/tutorial/008.md:
--------------------------------------------------------------------------------
1 | # 008. Custom Confirm Dialog
2 |
3 | Create a custom confirm dialog widget with callbacks.
4 | ***
5 |
6 |
7 | ### Source code & demo
8 |
9 | [Live demo](http://demo.dojotutorial.org/008-custom-confirm-dialog/)
10 |
11 | [Source code](https://github.com/cepa/dojo-tutorial/tree/master/008-custom-confirm-dialog)
12 |
13 | ***
14 |
15 |
16 | ### Index markup
17 | ~~~ html5
18 |
19 |
20 | Click me!
21 |
22 |
23 | ~~~
24 | ***
25 |
26 |
27 | ### Confirm dialog widget (app/dialog/ConfirmDialog.js)
28 | ~~~ javascript
29 | define([
30 | 'dojo/_base/declare',
31 | 'dijit/Dialog',
32 | 'dijit/_WidgetsInTemplateMixin',
33 | 'dojo/text!./ConfirmDialog.html',
34 | 'dijit/form/Button'
35 | ], function(declare, Dialog, _WidgetsInTemplateMixin, template){
36 | return declare('app.dialog.ConfirmDialog', [Dialog, _WidgetsInTemplateMixin], {
37 |
38 | title: 'Confirm',
39 | templateString: template,
40 |
41 | constructor: function(options){
42 | if (options.message) {
43 | this.content = options.message;
44 | }
45 | }
46 |
47 | });
48 | });
49 | ~~~
50 | ***
51 |
52 |
53 | ### Confirm dialog template (app/dialog/ConfirmDialog.html)
54 | ~~~ html5
55 |
56 |
57 |
58 |
59 | x
60 |
61 |
62 |
65 |
66 | Yes
67 | No
68 |
69 |
70 | ~~~
71 | ***
72 |
73 |
74 | ### app/main.js
75 | ~~~ javascript
76 | define([
77 | 'require',
78 | 'dojo/ready',
79 | 'dijit/registry'
80 | ], function(require, ready, registry){
81 |
82 | var app = {};
83 |
84 | ready(function(){
85 | dojo.connect(registry.byId('btnClickMe'), 'onClick', app.onButtonClick);
86 | console.log('loaded!');
87 | });
88 |
89 | /**
90 | * Display confirm dialog.
91 | */
92 | app.confirm = function(options){
93 | require(['app/dialog/ConfirmDialog'], function(Dialog){
94 | var dialog = new Dialog(options);
95 | dialog.show();
96 | });
97 | };
98 |
99 | /**
100 | * Button click action.
101 | */
102 | app.onButtonClick = function(){
103 | app.confirm({
104 | message: 'Do you like this demo?',
105 | onExecute: function(){
106 | console.log('great! :)');
107 | },
108 | onCancel: function(){
109 | console.log('too bad :<');
110 | }
111 | });
112 | };
113 |
114 | return app;
115 | });
116 | ~~~
117 | ***
118 |
119 |
120 |
--------------------------------------------------------------------------------
/tutorial/009.md:
--------------------------------------------------------------------------------
1 | # 009. Form
2 |
3 | Create dijit form.
4 | ***
5 |
6 |
7 | ### Source code & demo
8 |
9 | [Live demo](http://demo.dojotutorial.org/009-form/)
10 |
11 | [Source code](https://github.com/cepa/dojo-tutorial/tree/master/009-form)
12 |
13 | ***
14 |
15 |
16 | ### Index markup
17 | ~~~ html5
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | Johnnie Walker
32 | Jack Daniels
33 | Grant's Scotch
34 |
35 |
36 | Johnnie Walker
37 | Jack Daniels
38 | Grant's Scotch
39 |
40 |
41 | Johnnie Walker
42 | Jack Daniels
43 | Grant's Scotch
44 |
45 |
46 | Johnnie Walker
47 | Jack Daniels
48 | Grant's Scotch
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | 0%
57 |
58 | 50%
59 |
60 | 100%
61 |
62 |
63 |
64 | 25%
65 |
66 | 75%
67 |
68 |
69 |
70 |
71 |
72 | 0%
73 |
74 | 50%
75 |
76 | 100%
77 |
78 |
79 |
80 | 25%
81 |
82 | 75%
83 |
84 |
85 |
86 |
87 |
Submit
88 |
89 |
90 |
91 | ~~~
92 | ***
93 |
94 |
95 |
--------------------------------------------------------------------------------
/tutorial/010.md:
--------------------------------------------------------------------------------
1 | # 010. Form validation
2 |
3 | Validate values on dijit form and create a custom validator.
4 | ***
5 |
6 |
7 | ### Source code & demo
8 |
9 | [Live demo](http://demo.dojotutorial.org/010-form-validation/)
10 |
11 | [Source code](https://github.com/cepa/dojo-tutorial/tree/master/010-form-validation)
12 |
13 | ***
14 |
15 |
16 | ### Index markup
17 | ~~~ html5
18 |
19 |
20 |
29 |
30 |
31 | ~~~
32 | ***
33 |
34 |
35 | ### Custom form validator (app/validate/custom.js)
36 | ~~~ javascript
37 | define("app/validate/custom", ["dojo", "dojo/_base/lang"], function(dojo, lang){
38 | var validate = lang.getObject("dojox.validate", true);
39 |
40 | validate.isOver666 = function(value, flags){
41 | console.log('validate');
42 | return (parseInt(value) > 666);
43 | };
44 |
45 | return validate;
46 | });
47 | ~~~
48 | ***
49 |
50 |
51 |
--------------------------------------------------------------------------------
/tutorial/011.md:
--------------------------------------------------------------------------------
1 | # 011. Ajax form validator
2 |
3 | Custom Ajax based validation.
4 | ***
5 |
6 |
7 | ### Source code & demo
8 |
9 | [Live demo](http://demo.dojotutorial.org/011-form-ajax-validator/)
10 |
11 | [Source code](https://github.com/cepa/dojo-tutorial/tree/master/011-form-ajax-validator)
12 |
13 | ***
14 |
15 |
16 | ### Index markup
17 | ~~~ html5
18 |
19 |
20 |
26 |
27 |
28 | ~~~
29 | ***
30 |
31 |
32 | ### Ajax validation TextBox widget (app/form/AjaxValidationTextBox.js)
33 | ~~~ javascript
34 | define([
35 | 'dojo/_base/declare',
36 | 'dojo',
37 | 'dijit/form/ValidationTextBox'
38 | ], function(declare, dojo, ValidationTextBox){
39 | return declare('app.form.AjaxValidationTextBox', [ValidationTextBox], {
40 |
41 | ajaxUrl: null,
42 | ajaxLock: false,
43 | ajaxResult: false,
44 |
45 | isValid: function(){
46 | var widget = this;
47 | if (!this.ajaxLock && this.ajaxUrl) {
48 | this.ajaxLock = true;
49 | dojo.xhrGet({
50 | url: widget.ajaxUrl + '?value=' + widget.get('value'),
51 | handleAs: 'json',
52 | load: function(result){
53 | widget.ajaxResult = result;
54 | widget.validate();
55 | widget.ajaxLock = false;
56 | }
57 | });
58 | }
59 | return this.ajaxResult;
60 | }
61 |
62 | });
63 | });
64 | ~~~
65 | ***
66 |
67 |
68 | ### Server side (validate.php)
69 | ~~~ php
70 |
19 |
20 | Click me!
21 |
22 |