Phát triển các widget bằng Dojo 1.x
Marco Lerro, Kỹ sư, IBM
Roberto Longobardi, Thiết kế giải pháp, IBM Tivoli Software
Gianluca Perreca, Kỹ sư, IBM Tivoli Software
Alessandro Scotti, Kỹ sư phần mềm, IBM
Tóm tắt: Tìm hiểu các cơ sở trong việc phát triển các widget HTML bằng bộ
công cụ Dojo JavaScript. Bài viết này chỉ giới thiệu và cung cấp một số ví dụ
nhằm giúp bạn trong quá trình xây dựng – khởi đầu bằng một số widget mẫu ví dụ
và tiến dần tới các widget phức tạp hơn, đồng thời nêu bật và giải quyết các vấn đề
phổ biến mà bạn có thể gặp trong giai đoạn phát triển.
Giới thiệu
Mục tiêu của bài viết này là cung cấp cho bạn các cơ sở để phát triển widget
HTML bằng bộ công cụ Dojo JavaScript, bắt đầu từ phiên bản 1.0. Bài viết này
cũng mô tả nhiều ví dụ, bắt đầu từ các widget đơn giản và tiến dần tới các widget
phức tạp hơn, trong khi giải quyết các vấn đề phổ biến mà bạn có thể gặp trong khi
phát triển widget.
Bộ công cụ Dojo là gì?
Dojo là bộ công cụ mã nguồn mở, dựa trên JavaScript, dành cho việc phát triển
các ứng dụng Web HTML động. Bộ công cụ này cho phép bạn có thể xây dựng
nhanh các widget phức tạp hơn các widget HTML tiêu chuẩn. Việc sử dụng các
thành phần mà Dojo cung cấp sẽ giúp giao diện người dùng Web của bạn thêm
hữu dụng, phản hồi nhanh chóng và thiết thực. API mức thấp và các tầng tương
thích mà Dojo cung cấp sẽ giúp bạn viết ra những ứng dụng tương thích với nhiều
trình duyệt.
Trước khi bạn bắt đầu
Trước khi bắt tay vào, đầu tiên bạn cần phải thiết lập môi trường phát triển. Để
làm điều này cần:
1. Tải phiên bản phát hành mới nhất của bộ công cụ Dojo (dojo-release-1.x.x-
src.zip hay là dojo-release-1.x.x-src.tar.gz) từ trang chủ của dự án Dojo
(xem phần Tài nguyên để tìm địa chỉ)
2. Giải nén nội dung của tệp lưu trữ vào một thư mục, chú ý đến vị trí nơi tệp
dojo.js được giải nén. Hệ thống gói sẽ quản lý việc nạp tất cả các mô đun
sau khi tệp dojo.js được nạp lên trang web.
Khi thực hiện xong, cấu trúc của các thư mục sẽ như trình bày trong Hình 1.
Hình 1. Cấu trúc thư mục sau khi bung tệp dojo.
Dijit là hệ thống widget được đặt trên tầng đỉnh trên cùng của dojo. Thông qua chủ
đề (theme) riêng của mình, gọi là tundra, hệ thống này cung cấp thiết kế và lược
đồ màu sắc chung cho tất cả các widget của nó. Dojox là gói phát triển các phần
mở rộng của bộ công cụ Dojo. Nó dành cho những người cần đến những chức
năng không có trong bộ tập hợp các chức năng chung.
Các widgets Dojo
Khi duyệt các trang Web, bạn sẽ bắt gặp hàng trăm widget trên màn hình làm việc
của mình. Mỗi nút bấm trên trình duyệt Web của bạn là một widget. Mỗi hộp nhập
văn bản cũng là một widget. HTML chuẩn cung cấp một tập giới hạn các widget:
hộp nhập văn bản, nút bấm và siêu liên kết.
Các widget Dojo lấy một mục, ví dụ như hộp nhập văn bản, và thêm các chức
năng dành cho các đối tượng thân thiện với người dùng hơn, ví dụ như thêm lịch
dạng đồ họa để chọn ngày tháng chẳng hạn. Việc này được thực hiện mà không hề
làm hỏng mục gốc mà trên đó có xây dựng thêm chức năng mới.
Một widget Dojo gói gọn các thành phần Web trực quan để dễ dàng tái sử dụng.
Nó được định nghĩa nhờ 3 tệp:
Tệp JavaScript chứa logic của widget.
Tệp HTML (là tùy chọn) cung cấp một khuôn mẫu giống như HTML cho
widget.
Tệp CSS, thường dùng chung cho tất cả các widget (là kiểu dáng chủ đạo -
theme), trong đó chứa các kiểu dáng trực quan được áp dụng cho các khuôn
mẫu HTML của widget.
Nhập khẩu bộ công cụ Dojo
Liệt kê 2 cho thấy một khung sườn HTML cơ sở dùng để nhập khẩu một widget
vào trang Web thông thường.
Liệt kê 1. Mã HTML để nhập khẩu một widget vào trang Web.
<html>
<head>
<title>Dojo Toolkit Test Page</title>
<style type="text/css">
/* CSS style code */
</style>
<script type="text/javascript" src="js/dojo1.2/dojo/dojo.js"
djConfig="parseOnLoad:true, isDebug:true"></script>
<script type="text/javascript">
/* Javascript code */
</script>
</head>
<body>
/* Widgets definition code */
</body>
</html>
Thẻ script đầu tiên khởi tạo bộ công cụ Dojo chỉ đơn giản bằng cách nạp tệp mồi
dojo.js. Các thuộc tính parseOnLoad và isDebug của đối tượng djConfig là hai tùy
chọn cấu hình phổ biến mà Dojo kiểm tra trong lúc chạy. parseOnLoad bật/tắt việc
phân tích cú pháp các thẻ đánh dấu trong lúc nạp lên, trong khi isDebug cho phép
hay không cho phép các thông báo lỗi. Đối tượng djConfig cũng có thể được thiết
lập giống một biến toàn cục trước khi nạp tệp dojo.js:
Liệt kê 2. Mã thiết lập các biến toàn cục với djConfig
<script type="text/javascript">
var djConfig = {
isDebug:true, parseOnLoad:true
};
</script>
<script type="text/javascript" "js/dojo1.2/dojo/dojo.js"></script>
Hệ thống gói của Dojo
Dojo có hệ thống gói để cấu trúc các lớp của ứng dụng thành các tệp và nạp chúng
thông qua hàm dojo.require. Hàm này cho phép nạp từng phần của bộ công cụ
Dojo, còn chưa được cho sẵn trong tệp cơ sở dojo.js.
Để tạo một widget, bạn phải nhập khẩu khai báo widget bằng cách thêm vào các
dòng như trong Liệt kê 3.
Liệt kê 3. Mã để nhập khẩu một khai báo widget.
<script type="text/javascript">
dojo.require("widgets.Button");
</script>
Bây giờ, bạn có thể chèn mã sau đây vào phần thân:
<body>
<div dojoType="widgets.Button">My Button</div>
</body>
Thuộc tính dojoType làm cho bộ công cụ Dojo quản lý các thẻ theo một cách đặc
biệt. Vào thời điểm nạp trang, trình phân tích cú pháp Dojo sẽ tìm kiếm khai báo
widget được xác định rõ trong thuộc tính dojoType , khởi tạo một cá thể widget
này và thay thế thẻ đó bằng một nút DOM chứa widget đã nhận được.
Khai báo một widget
Bây giờ, ta hãy xét một ví dụ widget TextBox, gồm một tệp JavaScript, một tệp
khuôn mẫu và một tệp kiểu dáng CSS.
Đầu tiên, bạn phải tạo một tệp JavaScript, TextBox.js, trong đó có định nghĩa và
logic của widget (xem Liệt kê 4)
Liệt kê 4. Nội dung của tệp JavaScript TextBox.js
dojo.provide("widgets.TextBox");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.declare(
"widgets.TextBox",
[dijit._Widget, dijit._Templated],
{
/** the template path */
templatePath: dojo.moduleUrl("widgets", "templates/TextBox.html"),
/** the input DOM node */
inputNode: null,
/** the label */
label: "",
/** onkeyup handler */
onKeyUp: function() {
// give a chance to the browser to update the DOM
setTimeout(dojo.hitch(this, this.validate), 0);
},
/** validate function */
validate: function() {
if ( this.inputNode.value === "Ok" ) {
// the text is correct
dojo.addClass(this.inputNode, "inputOk");
dojo.removeClass(this.inputNode, "inputError");
} else {
// the text is incorrect
dojo.removeClass(this.inputNode, "inputOk");
dojo.addClass(this.inputNode, "inputError");
}
}
}
);
dojo.provide() định nghĩa tên của widget mới và đăng ký khai báo lớp. Lưu ý
rằng:
dijit._Widget và dijit._Templated là các lớp cha mẹ bậc trên (superclasses)
của widget TextBox.
templatePath, inputNode, và label là các thuộc tính của widget.
onKeyUp() và validate() là các hàm định nghĩa logic của widget.
Bây giờ, bạn có thể định nghĩa tệp khuôn mẫu TextBox.html như biểu diễn trong
Liệt kê 5.
Liệt kê 5. Nội dung tệp TextBox.html
<span class="textBox">
${label}:
<input
type="text"
class="inputOk"
dojoAttachPoint="inputNode"
dojoAttachEvent="onkeyup: onKeyUp">
</input>
</span>
Cụm ${label} sẽ được thay thế bằng thuộc tính label của cá thể widget đó.
Khai báo dojoAttachPoint sẽ khiến cho thuộc tính InputNode của widget được đặt
thành nút DOM tương ứng với thẻ input.
Khai báo dojoAttachEvent sẽ khiến cho các sự kiện onKeyUp (nhận được từ nút
input) kích hoạt lời gọi đến phương thức onKeyUp của widget.
Lớp textBox và inputOk chỉ tới tên của các lớp CSS được định nghĩa trong tệp
TextBox.css. Xem Liệt kê 6.
Liệt kê 6. Tên các lớp CSS trong tệp TextBox.css
.ibm .textBox {
margin: 5px;
padding: 5px;
background-color: #eee;
}
.ibm .inputOk {
border: 1px solid green;
}
.ibm .inputError {
border: 1px solid red;
}
Vì tên các lớp phải là duy nhất trong toàn bộ dự án, nên thường chúng sẽ có một
định tố chọn CSS (ví dụ định tố chọn ở đây là ibm).
Cuối cùng, widget có thể được tạo ra trên một trang HTML, như chỉ ra trong liệt
kê 7.
Liệt kê 7. Mã lệnh tạo widget trên trang HTML
<html>
<head>
<! page title >
<title>TextBox Widget</title>
<! include the DOJO >
<script type="text/javascript" src=" /dojo-1.0.0/dojo/dojo.js"
djConfig="isDebug: true, parseOnLoad: true">
</script>
<! import DOJO base CSS, DIJIT theme, and widget CSS >
<style type="text/css">
@import " /dojo-1.0.0/dojo/resources/dojo.css";
@import " /dojo-1.0.0/dijit/themes/tundra/tundra.css";
@import "templates/TextBox.css";
</style>
<! import DOJO stuff >
<script type="text/javascript">
dojo.require("dojo.parser");
<! register our module path >
dojo.registerModulePath("widgets", " / /widget");
<! import our stuff >
dojo.require("widgets.TextBox");
</script>
</head>
<body class="tundra ibm" style="padding:5px">
<br/>
<! declare the DOJO widget >
<div
dojoType="widgets.TextBox"
label="Name">
</div>
</body>
</html>
Hình 2 hiển thị widget TextBox.
Hình 2. Widget TextBox
Kiểu khai báo đối lập với kiểu chương trình
Dojo hỗ trợ hai mô hình lập trình, khai báo và chương trình. Cả hai mô hình đều
có thể sử dụng trên cùng một trang nếu cần. Trong Liệt kê 7, widget được tạo ra
theo mô hình khai báo.
<div dojoType="widgets.TextBox" label="Name"></div>
Một widget tương tự cũng có thể được tạo ra theo mô hình chương trình, như
trong Liệt kê 8.
Liệt kê 8. Tạo widget TextBox theo mô hình chương trình
<html>
<head>
<! page title >
<title>TextBox Widget</title>
<! include the DOJO >
<script type="text/javascript" src=" /dojo-1.0.0/dojo/dojo.js"
djConfig="isDebug: true, parseOnLoad: true">
</script>
<! import DOJO base CSS, DIJIT theme, and widget CSS >
<style type="text/css">
@import " /dojo-1.0.0/dojo/resources/dojo.css";
@import " /dojo-1.0.0/dijit/themes/tundra/tundra.css";
@import "templates/TextBox.css";
</style>
<! import DOJO stuff >
<script type="text/javascript">
dojo.require("dojo.parser");
<! register our module path >
dojo.registerModulePath("widgets", " / /widget");
<! import our stuff >
dojo.require("widgets.TextBox");
</script>
<script type="text/javascript">
function createWidget()
{
var widget = new widgets.TextBox();
widget.label = "Name";
widget.startup();
}
</script>
</head>
<body class="tundra ibm" style="padding:5px">
<br/>
<! declare the DOJO widget >
<script type="text/javascript">
createWidget();
</script>
</body>
</html>
Bổ sung thêm về các widget Dojo
Như đã đề cập từ đầu, một widget Dojo là một khai báo lớp Dojo được thừa kế từ
một lớp đặc biệt: lớp dijit._Widget. Lớp này định nghĩa các hành vi cơ sở của một
widget và cung cấp các chức năng thông dụng, được chia sẻ chung cho tất cả các
triển khai widget. Các nhiệm vụ quan trọng nhất do lớp _Widget triển khai là:
Định nghĩa phương thức create, phương thức này sẽ được tự động gọi khi
khởi tạo một cá thể widget; phương thức này sẽ thi hành tất cả những bước
tạo lập cần thiết.
Định nghĩa một số phương thức khuôn mẫu (template), chúng cung cấp các
điểm móc nối (hook) đặc biệt dành cho các nhà triển khai widget, mang lại
cho họ khả năng triển khai các hành động khởi tạo đặc biệt trong một pha
kiến tạo cụ thể.
Định nghĩa một loạt các phương thức destroy để dọn sạch các tài nguyên
widget đã được cấp phát.
Định nghĩa phương thức event management, chúng sẽ nối buộc các phương
thức widget với các sự kiện nút DOM/sự kiện gọi phương thức.
Pha tạo lập widget
Phương thức create thực hiện các bước cơ bản sau đây để khởi tạo widget:
Sinh ra ID duy nhất cho widget nếu như không được cung cấp
Tất cả các widget Dojo đều phải được xác định nhờ một ID duy nhất. Khi một đối
tượng widget được khởi tạo ra, nó sẽ được cấp một ID widget. Nếu không có thì
Dojo sẽ sinh một ID theo dạng sau:
packageName_className_number
Ví dụ, một nút nhấn có thể có ID tự động sinh ra là: dijit_form_Button_0.
packageName là gói widget mà dấu chấm (.) đã thay bằng dấu gạch dưới (_) (ví
dụ, dijit_form), và số hiệu sẽ tăng dần theo từng widget.
Đăng ký widget tại sổ đăng ký widget toàn cục
Người ta có thể sử dụng phương thức dijit.byId để tìm kiếm các widget, phương
thức này sẽ trả lại đối tượng widget tương ứng với ID đã cho. Sổ đăng ký là một
đối tượng nằm trong không gian toàn cục ở dijit.registry_hash. Sử dụng các công
cụ gỡ lỗi, ví dụ như FireBug (xem Tài nguyên), thâm nhập sổ đăng ký này có thể
hữu dụng trong việc dò tìm, ví dụ, các widget có lỗ hổng.
Ánh xạ các thuộc tính
Các thuộc tính widget có thể được tái ánh xạ đến các nút do người dùng định
nghĩa trong khuôn mẫu widget. Các thuộc tính để ánh xạ và đích tới của chúng
được liệt kê trong đối tượng attributeMap. Mỗi thuộc tính của những đối tượng
này định nghĩa một ánh xạ theo cách sau:
1. Tên thuộc tính sẽ xác định tên thuộc tính widget, trong đó lưu giá trị để
thiết đặt.
2. Giá trị thuộc tính sẽ xác định tên thuộc tính widget lưu trữ nút DOM đích.
Nếu thấy xâu rỗng thì sử dụng domNode.
Liệt kê 9 cho ta một ví dụ.
Liệt kê 9. Khai báo một widget dojo
dojo.declare(
"MyWidget",
dijit._Widget,
{
// the attribute to map (name and value)
title: "myTitle",
// the DOM node to be used to set the
// title attribute to the "myTitle" value
titleNode: null,
// the attribute map
// the title attribute is mapped to the titleNode
attributeMap: {title: "titleNode"},
// the template string
templateString: "<div><span dojoAttachPoint=\"titleNode\"></span></div>",
Kết quả khuôn mẫu widget sẽ là:
<div><span title="myTitle"></span></div>
Lưu ý rằng vì lớp base _Widget đã ánh xạ một vài thuộc tính HTML cơ bản (như
ID, lớp, kiểu), người triển khai thực hiện không nên ghi đè lên thuộc tính
attributeMap. Thay vào đó, họ phải trộn lẫn thuộc tính attributeMap của lớp cơ sở
với các giá trị của nó. Liệt kê 10 biểu diễn một ví dụ có được từ lớp _FormWidget.
Liệt kê 10. Trộn lẫn thuộc tính atrributeMap lớp cơ sở với các giá trị tùy biến
attributeMap:
dojo.mixin(
dojo.clone(dijit._Widget.prototype.attributeMap),
{id:"focusNode", tabIndex:"focusNode", alt:"focusNode"}
),
Các phương thức khuôn mẫu
Trong pha tạo widget, một vài phương thức sẽ được gọi, cho phép những người
cài đặt thực hiện một số hành động trong các pha khởi tạo cụ thể. Các phương thức
sau đây được gọi:
1. postMixInProperties: phương thức này được gọi sau khi tất cả các tham số
của widget đã được thiết lập (được trộn) thành các thuộc tính của cá thể
widget. Đây là thời điểm thích hợp để tiếp tục khởi tạo thuộc tính, nếu dựa
trên các thuộc tính mà việc khởi tạo cá thể đối tượng sẽ cung cấp.
2. buildRendering: phương thức này được gọi vào thời điểm sinh ra biểu hiện
của widget. Điểm móc nối này được triển khai trong lớp trộn
dijit._Templated, lớp này cũng triển khai các khung sườn widget bằng các
khuôn mẫu HTML. Những người triển khai có thể cung cấp cách thực hiện
của mình nhằm tinh chỉnh công việc của lớp _Templated.
3. postCreate: phương thức này được gọi sau khi DOM của widget đã sẵn
sàng và được chèn vào trang. Người triển khai có thể thao tác trên cấu trúc
DOM của widget tại vị trí này. Các widget con chưa được khởi động.
4. startup: cơ hội cuối để thao tác trên widget. Vào lúc này thì các wiget con
đã được khởi động.
5. uninitialize: được gọi sau khi widget đã bị hủy bỏ. Người triển khai có thể
thực hiện một vài việc dọn dẹp làm sạch không được tự động hóa.
Các phương thức khuôn mẫu có thể do người triển khai cung cấp, và người triển
khai phải nhớ rằng lớp cha mẹ bậc trên có thể đã triển khai thực hiện các phương
thức khuôn mẫu của nó. Để đảm bảo việc khởi tạo chính xác tất cả các lớp trong
chuỗi móc xích này, người triển khai phải mã hóa thủ công lời gọi phương thức
của lớp bậc trên như được chỉ ra trong Liệt kê 11.
Liệt kê 11. Ví dụ về việc gọi phương thức của lớp cha mẹ bậc trên.
startup: function()
{
// call the superclass' method
this.inherited("startup", arguments);
// your code here
}
Như quy ước chung, đối với tất cả các phương thức tạo sinh (tất cả các phương
thức khuôn mẫu ngoại trừ uninitialize), phương thức của lớp bậc trên phải được
gọi đầu tiên để đảm bảo rằng các mục dữ liệu của lớp bậc trên được khởi tạo chính
xác trước khi thao tác với chúng.
Đối với phương thức uninitialize thì lại áp dụng quy tắc ngược lại.
Một lưu ý cuối cùng là về phương thức startup. Đừng quên rằng phương thức
startup được phương thức dojo.parser.parse tự động gọi, trong trường hợp widget
được tạo ra bởi một khai báo. Startup sẽ không được thực hiện nếu widget được
tạo ra bằng các lệnh chương trình và sẽ phải được khởi động thủ công như trong ví
dụ dưới đây.
var w = new MyWidget({});
w.startup();
Pha hủy bỏ widget
Sau khi được tạo ra, các widget sẽ tồn tại cho đến khi có một yêu cầu hủy bỏ
tường minh được thi hành. Người triển khai chịu trách nhiệm quản lý toàn bộ vòng
đời của widget, bao gồm cả việc hủy bỏ widget. Nếu khác đi, sẽ đưa tới kết quả là
có một widget lỗ thủng cho đến khi toàn bộ trang được dọn dẹp sạch sẽ. Widget
cung cấp 4 phương thức hủy bỏ là:
destroyRendering: phương thức này dọn sạch các mục biểu hiện của
widget. Trừ phi người triển khai cần dọn dẹp từng phần, phương thức này
thường được gọi bởi các phương thức hủy bỏ khác.
destroyDescendants: hủy bỏ tất cả các widget con. Trừ phi người triển khai
cần dọn dẹp từng phần, phương thức này được gọi bởi phương thức
destroyRecursive.
destroy: hủy bỏ các mục widget (chứ không phải là các widget con).
destroyRecursive: hủy bỏ các mục của widget và các widget con. Nếu
widget chứa các widget con bên trong thì bắt buộc phải gọi phương thức
này.
Trong trường hợp widget có chứa các widget bên trong (ví dụ, có một vài widget
trong khuôn mẫu), người triển khai phải nhớ kích hoạt các widget con, hủy bỏ
chúng theo cách nào đó mà không bắt người dùng widget phải quyết định xem
phải gọi phương thức hủy bỏ nào. Liệt kê 12 cho thấy một phương án khả thi để
thực hiện điều này.
Liệt kê 12. Ví dụ về việc kích hoạt phương thức hủy bỏ của một widget.
uninitialize: function()
{
// destroy the descendants
this.destroyDescendants();
// call the superclass' method
this.inherited("uninitialize", arguments);
}
Quản lý sự kiện
Một widget dojo có thể phản ứng lại các sự kiện bên ngoài, xuất phát từ cả các nút
DOM lẫn các đối tượng. Những sự kiện này có thể được kết nối thủ công bằng
cách dùng phương thức connect của widget, phương thức này có chữ ký như sau
(hoàn toàn tương tự như phương thức dojo.connect):
connect: function(/*Object|null*/ obj, /*String*/ event, /*String|Function*/
method);
Hoặc nó có thể tự động kết nối nhờ khai báo kết nối trong khuôn mẫu sử dụng
thuộc tính dojoAttachEvent. Trong cả hai trường hợp, kết nối được theo vết bên
trong bởi widget trong mảng _connects. Tất cả các kết nối sẽ được ngắt tự động
lúc thực hiện hủy bỏ. Theo cách này, các tham chiếu giữa widget và nút DOM bị
phá bỏ.
Nếu trong vòng đời của widget, một số kết nối không cần đến nữa thì người triển
khai có thể ngắt kết nối một cách thủ công nhờ gọi phương thức disconnect để
giảm bớt việc xử lý sự kiện.
Khuôn mẫu widget
Như đã thấy trước đây, các widget phải thừa kế từ lớp dijit._Widget, lớp này định
nghĩa và cung cấp các hành vi cơ bản cho một widget Dojo. Một lớp cơ sở như
vậy định nghĩa phương thức buildRendering chịu trách nhiệm xây dựng xây dựng
các phần tử biểu hiện widget. Ví dụ, một người triển khai widget có thể xây dựng
trong phương thức này các thẻ đánh dấu widget và đặt nó vào nút DOM widget.
Một tùy chọn khác là có thể tạo cấu trúc widget bằng API DOM. Trong cả hai
trường hợp, người triển khai phải lập trình phương thức buildRendering theo cách
nào đó.
Dojo cung cấp một mức trừu tượng hóa mạnh, tách riêng định nghĩa việc biểu hiện
widget ra khỏi việc triển khai thực hiện các hành vi của widget: đó là lớp trộn
dijit._Templated. Người triển khai muốn khai thác việc trừu tượng hóa này thì cần
phải thừa kế từ lớp _Templated, như trong Liệt kê 13.
Liệt kê 13. Mã lệnh để thừa kế từ lớp _Templated
dojo.declare(
"widgets.MyWidget",
dijit._Widget, dijit._Templated
{
templatePath: dojo.moduleUrl("widgets", "templates/MyWidget.html"),
}
);
Lớp _Templated cung cấp một cách triển khai thực hiện phương thức
buildRendering của riêng nó, sử dụng định nghĩa kiểu như HTML. Định nghĩa này
có thể có mặt ở hai nơi khác nhau.
1. Một tệp ngoài. Trong trường hợp này, tệp này được tham chiếu bởi thuộc
tính templatePath templatePath.
2. Thuộc tính xâu nội tại. Trong trường hợp này, khuôn mẫu sẽ được định
nghĩa trực tiếp trong widget ở thuộc tính templateString. Nếu có chỉ rõ
thuộc tính templateString thì thuộc tính templatePath sẽ bị bỏ qua, thậm chí
cả khi nó đã được xác định rõ.
Tùy chọn thứ nhất đại diện cho cách sạch sẽ nhất để tổ chức mã nguồn widget, vì
các thẻ đánh dấu (mark-up) có thể được viết trong một tệp khác, mã nguồn này có
thể được định dạng theo cách dễ đọc mà ta không phải lo lắng về việc nối ghép
xâu, và sẽ không phải áp mã thoát các dấu phân cách xâu. Mặt khác, tùy chọn thứ
hai lại là cách có hiệu năng tốt hơn, vì không cần phải nạp một tệp thứ hai từ trình
duyệt. Tuy nhiện, bạn không nên lo lắng về điều đó vì Dojo sẽ cung cấp công cụ
xây dựng để tiếp nhận và nội tại hóa các khuôn mẫu bên ngoài vào trong mã
nguồn widget.
Khuôn mẫu có thể được tham số hóa bằng cách tham chiếu đến các thuộc tính
widget. Điều này rất có ích khi widget trưng ra các tham số cấu hình có ảnh hưởng
trực tiếp đến các thẻ đánh dấu hoặc nếu các thẻ đánh dấu phải được sinh ra tùy
theo điều kiện phụ thuộc vào các lựa chọn ưu tiên ngoài. Các thuộc tính widget
được tham chiếu theo cú pháp sau: ${propertyName}.
Các khuôn mẫu có thể chứa các khai báo widget khác nữa. Tuy nhiên, để chúng
được xem xét, những người phát triển widget phải đặt thuộc tính
widgetsInTemplate là true, mà bình thường thì mặc định đặt là false để bỏ qua việc
xử lý không cần thiết.
Các khuôn mẫu có thể có 2 khai báo thuộc tính đặc biệt sau đây:
dojoAttachPoint: thuộc tính thẻ này, nếu được chỉ rõ, phải được đặt là một
tên thuộc tính widget. DOM tương ứng với thẻ này sẽ được thiết đặt là
thuộc tính của widget. Một vài thẻ khác trong khuôn mẫu có thể có một
hoặc nhiều điểm gắn kết.
dojoAttachEvent: thuộc tính thẻ này liệt kê ra các phương thức widget sẽ
được gọi lại khi một sự kiện DOM được kích hoạt.
Liệt kê 14 chỉ ra một khuôn mẫu ví dụ.
Liệt kê 14. Khuôn mẫu ví dụ về các khai báo thuộc tính đặc biệt
<span
class="textInputDefault"
dojoAttachEvent="onclick:_onClick">
<img
class="textInputIcon"
AULT_ICON}"
dojoAttachPoint="_iconNode"/>
<input
class="textInputNode"
size="${size}"
type="${type}"
value=""
dojoAttachPoint="_inputNode, _focusNode"
dojoAttachEvent="onkeyup:_onKeyUp, onkeypress:_onKeyPress,
onchange:_onChange"
/>
<span
class="textInputRight">
</span>
</span>
Bảng điều khiển tải công việc động của Tivoli và Dojo
Bảng điều khiển tải công việc động của Tivoli (TDWC) là một giao diện người
dùng đồ họa của trình lập lịch tải công việc của Tivoli (TWS). Phần trình bày này
sẽ chỉ ra cách TDWC v.8.5 tận dụng ưu thế các khả năng của Dojo như thế nào.
Giới thiệu về trình lập lịch tải công việc của Tivoli
TWS là một giải pháp tự động hóa triển khai trong sản xuất được thiết kế để trợ
giúp việc quản lý tải công việc được nạp trong những môi trường điều hành phức
tạp hiện nay. Các thành phần lập lịch chính là công việc (job) và luồng công việc
(job stream). Một công việc là một thể hiện của một tác vụ nào đó, như là một tệp
chạy được, một chương trình hay một lệnh nào đó. Một luồng công việc biểu diễn
một thùng chứa các công việc có liên quan và tổ chức chúng về mặt thời gian
chạy, tuần tự hóa, các giới hạn tương tranh (concurrency limitations) và việc lặp
lại nhiều lần. TWS gúp lập kế hoạch để thi hành các công việc, phân giải các phần
phụ thuộc lẫn nhau, khởi chạy và theo vết từng công việc. Đó là vì các công việc
được bắt đầu ngay khi những phụ thuộc của chúng được giải quyết; bởi vậy, sẽ
giảm tối đa thời gian nhàn rỗi và thông lượng sẽ tăng đáng kể. Các công việc
không bao giờ chạy sai so với chuỗi tuần tự và nếu một công việc thất bại thì TWS
sẽ xử lý tiến trình tái lập với ít can thiệp nhất có thể.
Sử dụng Dojo
TDWC phiên bản 8.5 bao gồm một trình soạn thảo tải công việc có đầy đủ tính
năng được viết hoàn toàn bằng JavaScript sử dụng bộ công cụ Dojo. Kiểu triển
khai thực hiện này cho phép di chuyển “thông minh” và hành xử gần gũi hơn với
người sử dụng, bằng cách sử dụng mã lệnh chạy trong trình duyệt web ở mức tối
đa có thể.
Ta hãy xét một ví dụ về bảng (panel) thuộc tính của một luồng công việc TWS
được trình bày bởi TDWC. Hình 3 cho thấy một bảng Web các thuộc tính chung
đã định nghĩa của luồng công việc PAYROLL.