SCMLife.com

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 2926|回复: 1

[推荐] 扩展 Dojo dijits 来创建自定义小部件

[复制链接]
发表于 2013-2-19 09:52:41 | 显示全部楼层 |阅读模式
本帖最后由 技术狂人 于 2013-2-19 10:40 编辑
+ R* D  H  @- w2 K0 b1 J4 t
7 h1 ^0 {. Z( A% x
简介
Dojo Toolkit 是一个强大的 JavaScript™ 库,支持 Web 开发人员使用面向对象的小部件,用最少的开发时间和工作量来创建富 Internet 应用程序。Dojo Toolkit 提供了 4 个包,它们分别是 Dojo(核心)、Dijit(UI 框架)、dojox(dojo 扩展)和 util。您可以原封不动地使用该工具包提供的功能,也可扩展它们并创建自己的小部件。提供的功能包括 DOM 操作、使用 AJAX 开发、事件、数据存储等。
3 b# d3 p4 j1 ?* RDijit(dojo 小部件)包是 dojo 自己的 UI 库,它包含一组 dojo 类,使开发人员能够以最少的工作创建功能丰富且强大的跨平台 Web 2.0 接口。这些 Dijit 小部件(或 dijit)支持一些易于操作的主题。这个包中的 dijit 示例包括按钮、文本字段、编辑器、进度条等。; _; s% u' k& l$ \: w
举例而言,您可以使用这些 dijit 创建一个提交表单,其中包含用于名称、电子邮件地址和电话号码的文本字段,以及日期字段、复选框、按钮和验证,所有这些在几分钟即可完成,需要的 JavaScript 知识也极少。
3 ~: H" C0 @7 W3 ~1 M提供的一个功能最丰富的 dijit 是 Calendar dijit,它支持在一个月的上下文中显示日历。用户可轻松地逐月、逐年导航,或者跳到同一年中任一个月,以选择特定的日期。
/ R; @/ F* G; B4 b: g* D$ ?" [在开发富 Internet 应用程序 (RIA) 时,通常可以原封不动地使用 dijit。但是,有时您可能需要使用不同的样式(比如更改颜色或主题),或者需要进行更复杂的更改,其中可能需要结合使用某些功能、模板和样式更改。要满足这些需求,则需要从头创建一个新的自定义小部件,也可以创建一个扩展现有 dijit 的自定义小部件。8 z/ D# d  u6 @. Z' A  z
本文提供了一个练习,在这个练习中,您需要在自己的网站上使用 Calendar 小部件的不同变体。为了满足此需求,您需要创建一个新类。此练习使用了 Dojo version 1.7,提供了探索 Calendar dijit 的机会和以极少的改动重用现有 dijit 来节省开发时间的方式。您还会看到在 Dojo 1.7 中声明的一个新类的实用示例,探索一些 Dojo 基础功能,比如数据操作、hitch、发布和订阅等。& `- K, ?  Y& V, ]
问题
在此练习中,您将使用 Calendar dijit 的一个具有以下需求的自定义版本:2 S5 b* ~5 J9 H+ s/ _+ a
  • 日历应仅显示当月的日期(隐藏和禁用不属于当月的日期)。
  • 日历应仅在底部显示当前年份(没有去年或明年)。
  • 日历应在日历小部件底部显示当月的名称。
  • 用户无法跳到任何其他月份(禁用顶部的月份下拉按钮)。
  • 提取日历顶部显示的用于逐月移动(向后或向前)的箭头,将日历旁边的箭头显示为 dijit 按钮。这两个新按钮是用户更改月份的惟一方式。
  • 具有最小和最大边界日期,这意味着所有在此边界外的日期都应该是禁用和不可访问的。
  • 在到达边界日期时,禁用相应的月份导航按钮。
  • 向日历中选定的日期添加特殊的样式。
  • 当用户选择某个日期时,将该日期传递给一个将处理新选择的值的函数。
    1 L2 n2 l# r- w0 y
解决方法是创建一个自定义小部件,这个小部件通过使用 JavaScript 和 CSS 编辑 Calendar dijit 来开发。图 1 显示了应用上面需求之前(左侧)和之后(右侧)的 Calendar 小部件。
) T+ u" C4 f9 h5 o& Z% ^+ X7 S1 t3 x; ?& I2 N
图 1. 标准 Calendar dijit 与自定义 Calendar 小部件的对比& {3 C0 `" [8 s& P0 F- p

3 r, s( Q+ G9 x' _5 e, H为此,您将需要创建 3 个文件:2 y0 |2 g" n( \' S3 J0 F9 F9 S
  • Dijit 模板:一个将显示自定义小部件的组件的标记文件。
  • Dijit 类:一个使用声明 (JavaScript) 创建的小部件类。
  • CSS 文件:包含所有必要的样式表类。
    8 W5 m* n" G7 s: h- e; f) `5 S
图 2 显示了自定义小部件的文件结构和位置。您的起点是 index.html,它在本示例中充当了小部件的控制器。simple.css 文件将包含所有样式。0 W% W" ?7 R- u: @0 W- i
9 x  f% f# C5 p( A3 U! h
图 2. 文件结构1 B: J! Q' c  c) D( E# c$ I  J

* e6 l" ?( i1 ^
$ M7 Q! U* l% o8 t# z* F8 _8 I

/ _, `/ Q. F. \. K
创建小部件
dijit 模板
创建 3 个 JavaScript div 元素:一个用于日历,两个用于向前和向后逐月导航的箭头按钮(清单 1)。这些 div 将使用附加点 (data-dojo-attach-point) 进行引用。使用附加点比使用 id 更好,因为它使您能够在同一个页面上拥有同一个小部件的多个实例,无需担忧 id 冲突。6 d4 K7 X& V# q9 A. [1 f  f" u

, f. Y( y. G& x- G  h0 @4 B清单 1. dijit 模板
, W8 T$ N" `9 u3 J, G/ ~( z
<div class="CalendarArrow">
& v% _! C% s8 x( q3 ]. @3 D- p<div data-dojo-attach-point="calendarPreviousMonthButtonAP"></div>
5 u0 T( n) u7 A5 U</div>" q% j% \- H# I) C7 C8 f( D
. Q6 Q- w9 S0 m; G2 ^
<div class="CalendarDijit">
/ J( o' ^+ N8 }8 Y5 o8 Z<span data-dojo-attach-point="calendarMonthOneAttachPoint"></span>
4 s. {+ a  B& _5 J! C7 Y</div>: ?  J$ v( }6 X
3 j! Y  c6 x  n$ }! ?$ |
<div class="CalendarArrow">
; I8 a7 r5 Y" M0 B* S0 J% g5 e<div data-dojo-attach-point="calendarFollowingMonthButtonAP"></div>
8 I$ N- Z* V! U9 V: n& P" Z</div>
+ k) ]6 I! k$ `% o5 S" \: f+ |: w
dijit 类
根据应用程序需求,您需要定义以下变量:
, R! C/ z/ R; d% p
  • selectedDate:日历的初始值。
  • currentFocusDate:一个值,日历会引用该值来了解要显示的月份;该值最初被设置为等于 selectedDate。
  • calendarInstance:Dijit 日历实例。
  • bookingWindowMaxDate:日历中允许的最晚的日期。
  • bookingWindowMinDate:日历中允许的最早的日期。
  • onValueSelectedPublishIDString:表示发布/订阅频道(或主题)的字符串。
      b! K+ ~+ K9 U# t  O8 `
JavaScript 函数
首先修改以下样式表元素:  f2 J& t; ~3 L& ], V; t, I
  • constructor 修改构造函数以复制从控制器传来的变量。使用 dojo/_base/lang/mixin,它将匹配变量名称,并将值复制到您的自定义小部件变量中(清单 2)。
    6 t3 r) Z" y3 I' A$ y* _, f! k3 Y( {) g
    % T# L5 X. \! m/ ~% A& B
    清单 2. 构造函数
  • constructor: function (args){, V, R# S* X  x0 U- A
            if(args){
    4 }# e4 }% l; m, T& }2 m. x                lang.mixin(this,args);8 j3 K* O) A% \# f
            }2 }  t% {: I4 g9 y
    }
    , L' w1 K1 J1 r3 ]4 k+ K
  • postCreate 所有日期都将以具有 en-us 短格式 mm/dd/yyyy 的字符串形式传递。使用 dojo/date/locale 函数将用于 selectedDate、bookingWindowMaxDate、bookingWindowMinDate 的所有日期字符串转换为日期对象(清单 3)。- I. n* r* ~# D" d+ g9 @

    & D4 w" \% x. ~. O  ~  V
      H) L, c! ^. ?7 F5 n, G清单 3. 使用 dojo/date/locale
  • this.bookingWindowMinDate = locale.parse(this.bookingWindowMinDate, {formatLength:
    2 o8 S; l7 K/ K; B2 @4 ?'short', selector:'date', locale:'en-us'});
    / p- b: r* V  Q
    创建日历对象的一个实例(清单 4)。创建的逻辑在 createCalendar 函数中。以编程方式创建一个 dijit 日历的实例,将它附加到您将使用 dojo/dom-construct(等效于老版 dojo 中的 dojo.create)创建的一个 div 上。一般来讲这是一种很好的做法,因为它允许您销毁日历而不丢失附加点。
      ]2 w/ U- \/ d, ]! j6 B
    8 m4 f6 G; y) I9 J0 d4 b8 E1 v9 z2 [" G) f# d0 Y7 @' ^
    清单 4. 返回 dijit/Calendar 的一个实例
  • return new Calendar({
    7 w3 i% R8 I. F, K        value : selectedDate,+ g4 A' x' h2 a+ F( X
            currentFocus : selectedDate        },  domConstruct.create("div", {}, ) ^6 u  |0 _& \, a
            calendarAttachPoint));6 j$ Q2 [3 E; W+ t" t
    }

    # _  s- P, ]+ m5 _7 w6 s8 n
    请注意,您在Calendar dijit 中设置了 currentFocus 值。Calendar dijit 将始终使用您本地的当前日期来显示其第一个着屏 (landing screen),所以,如果希望日历显示不同的屏幕(日期),则必须设置 currentFocus。因此,对于自定义小部件,您需要将日历的初始值和 currentFocus 设置为 selectedDate(根据需要进行设置)。对于此示例,这个日期为 2012 年 8 月中的一天。
    , ^6 p7 a/ `' \
要满足其他需求,您需要修改 Calendar dijit 中的以下 3 个函数:
' @( p& Z) X$ y6 {
  • isDisabledDate 当 calendar dijit 加载一个视图时,它会逐个迭代当前视图中的日期(所有 42 个日期),并为每一天调用 isDisabledDate 和 getClassForDate(接下来将介绍)函数。9 G5 a- O5 e) m+ l  r2 Y6 Y9 P5 y2 q2 T
    isDisabledDate 函数用于禁用日历中的某些日期(清单 5)。如果函数返回 true,那么将会禁用该日期。每次日历刷新时,都会调用此函数,并且会将日历中的每一天的日期传送给它。对于自定义小部件,您需要:8 P3 [6 H8 {0 ^7 ^7 X
    • 禁用不属于当月的任何日期:为此,需要使用 dojo/date/difference 函数,该函数基于某个间隔来对比两个日期对象,如果两个日期相等,则返回 0。您将使用月份间隔对比 currentFocusDate 变量与当前视图中的每个日期,如果它们不相等,则返回 true,以禁用该日期。
    • 禁用边界日期外部的日期:再次使用 dojo/date/difference,但将间隔设置为 “day”。如果返回值小于 bookingWindowMinDate 或大于 bookingWindowMaxDate,则返回 true,以禁用该日期。
      / ?) o5 e6 y* |+ e# v  P2 U1 u; O0 y0 `* V' k4 T
      清单 5. 修改 isDisabledDate
    •                                                                
      ( C  P9 b  E! F2 Q- e, E: N) |isDisabledDate: function(date) {/ p# L$ P$ r0 g/ h6 R8 H) u
      //disable any day that doesn't belong to current month* f$ |- b( D" X5 m
              if(dojoDate.difference(parent.currentFocusDate, date, "month")!==0){
      ! V  u( G7 s0 d6 d( p  `; ^                return true;8 J7 O# \5 y: Q+ Z- U
              }
        n% ]. T, b# Q2 w, O% o        if(dojoDate.difference(parent.bookingWindowMinDate, date, "day" || & a1 u/ Q& K, n/ X" S
      dojoDate.difference(parent.bookingWindowMaxDate, date, "day")<0){( L" r; }$ e1 [$ W) I9 t' H
                      return true;
      ; t8 [3 w( x+ i1 r* l( X6 W3 u        }5 G% m+ `' B8 V, I2 }
              else {# L$ Q/ I9 n( B- m3 X8 X% K1 |
                      return false;4 I! Y& \9 ~% i/ x
              }3 T7 {# V, T' g: m$ \# `
      }
      7 [! l$ ~4 r/ `. {

      % t9 Z- \) l9 Y( g' K- d9 t0 B/ m6 X
  • getClassForDate 尽管您使用 isDisabledDate 禁用了不属于当月视图的日期,但还需要隐藏它们。可以使用 getClassForDate 函数返回一个 CSS 类名,在日历上以不同形式标记该日期。对于自定义小部件,需要突出显示 selectedDate,向该日期添加一个具有黑色边界的蓝色框(清单 6)。您还需要使用灰色突出显示在最小和最大日期边界之外的日期,隐藏不属于当月的日期。' F4 _3 s& n( ?! o
    要识别需要设置不同样式的日期,可以使用 dojo/date/compare,它将接受两个日期值(日期对象)和天数(字符串),如果相等,则返回 0。这里,您将传递 currentFocusDate、迭代中的日期和表示天数的日期,因为您仅对对比日期感兴趣,所以无需关注时间戳。如果此对比返回 0,那么该函数将返回类 “Available”,这个类是在 CSS 文件中定义的(清单 7)。您将使用 CSS .class 选择权来定位我们希望更改的特定元素。) |3 c0 m' w8 b" V8 N& E

    7 G' x3 }& C2 B/ g# i6 W1 H' {8 y6 G4 ]/ [  Q$ ~
    清单 6. 修改 getClassForDate
  • getClassForDate: function(date) {        
    + ]- a- x" h" r! q9 j' N        if ( dojoDate.compare(date,selectedDate,"date") === 0) {
    % `1 W) i- k* A9 W                return "Available";7 l  ]9 o) S% j
            } // apply special style
    2 _* N, {- ^$ p7 N" S}

    ' j) t" m% u, @3 h0 n8 C
    ! n; X. s) n% H8 X
    清单 7. 标记可用日期的 CSS 类
  • .AvailabilityCalendars .Calendars .CalendarDijit .Available ; v& e& p* _- @: f% w2 L
            .dijitCalendarDateLabel
    5 u' [# I. s& V6 w2 t5 n+ a{0 L2 r) q: }" i7 o4 N; n7 A  {
            background-color: #bccedc !important;
      t' `, K& w2 M5 h3 [$ G; y        border: 1px solid #000000 !important;
    6 a# ]: T8 B7 V. e+ F}

    : ?% O' ^6 F5 V- @$ X
    您将使用来自 isDisabledDate 的相同的 if 条件来识别超出边界的日期和不属于当月的日期,但会返回 CSS 类名(清单 8 和清单 9)。
    1 F2 N7 X& ^2 e! ]9 \, A5 B+ b% r4 N# S1 ~5 B5 K  _* X; v# y
    ! u  L  Z6 p' S5 \+ I; k
    清单 8. 隐藏和禁用日期
  • if(dojoDate.difference(parent.currentFocusDate, date, "month")!==0){
    8 T) j, Y" f& |% f        return "HiddenDay";! g9 D. l. ]' j) a
    }
    7 d( l( s$ y4 Zif(dojoDate.difference(parent.bookingWindowMinDate, date, "day")<0 || ' \' m4 j/ c6 A) a6 u. \4 Y, Y! V: ]
            dojoDate.difference(parent.bookingWindowMaxDate, date, "day")>0){
    & f8 X" p9 G% y2 r9 R! S, S1 l        return "Disabled";
    % u- @9 J1 v4 G0 k; {}
    + R0 A7 K0 G8 e3 {8 k2 I$ }

    / b  M' \0 Q% r1 B; J$ o
    # d5 y: N$ V+ y3 w: s清单 9. 标记隐藏和禁用的日期的 CSS 类
  • .AvailabilityCalendars .Calendars .CalendarDijit .HiddenDay ( Q9 _2 `% B8 [3 c1 t
            .dijitCalendarDateLabel
    " V: O7 u6 F9 q& h9 U{
    6 X/ s" z/ K1 p* f! u    background-color: #ffffff !important;1 |; d2 R5 C# w* h# D
        border-color: #ffffff;
    4 n! W7 P- `' Z- F/ A7 |' t    color: #ffffff;# r/ \# j* v! W4 w
    }' R. x% G1 K: ?, g4 e4 `2 h$ q% U

      t! F; C  f1 ^+ o .AvailabilityCalendars .Calendars .CalendarDijit .Disabled
    $ l( r+ Y) K$ d0 h( Q4 e        .dijitCalendarDateLabel6 O3 \1 H6 e7 U* |1 h0 p# S, f
    {7 U3 F; }3 f4 Q: \) \
            background-color: #9c9c9c;
    ' a, c) k# o2 k. F% O}
    9 D( O# O9 L7 v
  • onChange 此函数仅在为日历设置一个新值或在日历上选择一个启用值时调用(清单 10)。此函数返回所选日期的一个日期对象。您可以使用该对象将日期发布到另一个将处理该日期的方法。调用您的自定义小部件中定义的一个函数 (onValueSelected),在发布到控制器之前,您可以在其中执行任何需要的处理(清单 11)。在本示例中,您将使用 dojo/_base/connect/publish 将日期发布到控制器。频道(或主题)字符串存储在变量 onValueSelectedPublishIDString 中。
    * x) Q6 A' w. q5 Y' @8 U6 W2 U% O8 t! `9 F

    : `- e) |3 o. N* F! L清单 10. 使用 Calendar 的 onChange 和 hitch
  • onChange : lang.hitch(this, function(date){
    7 |" ^- p6 ]5 ^; }  y        this.onValueSelected(date);* B$ ~  n  o. h, C8 L* p
    })

    7 \1 M3 V' B7 e

    # N; E/ x% u9 N) |$ {7 ^% G清单 11. 使用 publish
  •                                                 5 F+ G5 f& c& p' F
    onValueSelected : function (date){: `3 G4 @- H' @7 K6 w) ?9 N6 H) N
            connect.publish(this.onValueSelectedPublishIDString, [date]);6 w+ [; r) V5 t; [1 |
    }
    ; b- _% A1 b( }
    请注意,您使用了 dojo/_base/lang/hitch 来提供调用函数 onValueSelected 的范围(清单 10)。您的控制器(在此场景中为 index.html)将提供一个订阅该频道的订户来处理日期(清单 12)。在此示例中,您仅记录它。可将此替换为任何其他需要的逻辑。- d7 b5 Z5 Q  K3 ?. R
    7 u+ c* U& _7 L7 c. I

    $ Q; x& F' C! n2 e8 x9 y清单 12. 我们的发布的订户
  • connect.subscribe("selectedValueID", function(date){
    ( W+ R, v  k+ j6 o5 f4 ]  //Do some processing
    # `  w8 }9 j7 p$ Q9 i& {; X  console.log("New Selected Date: ", date);5 z' O: Z' U. @9 \
    });
    & F1 [5 w3 |# Z' G% Z" e4 H& J
    ! U3 H/ w6 N6 T: S6 U
Calendar dijit 在页眉中附带了一个 monthDropDownButton。这个按钮显示了所有月份的列表,允许用户跳到任何月份。为了满足需求,您需要将 monthWidget 设置为 “disabled” 来禁用此按钮(清单 13)。
. u* G' E! j' L3 {
9 }9 o. V- X) C6 M8 ?8 ?清单 13. 禁用 Calendar 页眉中的下拉按钮
) d$ A* s6 _& q/ z
this.calendarInstance.monthWidget.set("disabled", true);

7 N! c' V2 g, L% U( C从实用性角度讲,您还需要隐藏箭头,使用户不会受到吸引而去单击它。为此,请添加定位您希望操作的元素的 CSS 类(清单 14)。( `! R8 c5 \3 k: `1 G, Q; y- |

% U3 a9 a5 R$ z5 B: S& m/ @; m清单 14. 隐藏下拉按钮箭头的 CSS 类9 T1 J% C$ U: g. z( s! B
.AvailabilityCalendars .Calendars .CalendarDijit .dijitDropDownButton
0 C; {5 N3 W6 M) D/ j! O        .dijitArrowButtonInner
8 E% d0 ]4 e7 m{: ]6 J+ p) w( \7 b0 c# f7 c
    visibility: hidden;) w( @* n, Y9 g4 }) q* `; }
}

5 a5 Z5 D& K& A6 P, p) g接下来,使用 CSS 类隐藏去年和明年的 digit,禁止将它显示在底部(清单 15)。
* l! z2 X" @, R9 a
* {9 O/ n" P1 u清单 15. 在 Calendar 底部隐藏年份 digit 的 CSS 类
8 b3 K' C5 T* ]  V" W* x; ^8 Q
.AvailabilityCalendars .Calendars .CalendarDijit .dijitCalendarPreviousYear,
3 B9 O- U8 q$ {. V: R        .dijitCalendarNextYear
2 A' X. T7 Z! V    {# _$ }* m) [$ L* z) E% b+ e# q
padding: 1px 6px;& @! g8 D; w! }' t3 `" S
visibility: hidden;
9 t/ g% ]) d8 v1 Y    }
/ k; G$ z) U9 f1 V
您还将隐藏顶部的箭头,否则这些箭头允许用户逐月移动(清单 16)。$ r# h& N- ^, L$ O1 D

/ s& q5 _# L0 g+ F+ b清单 16. 隐藏 Calendar 顶部的月份箭头的 CSS 类
: O, Z* W( L# r: A+ a3 z% O
.AvailabilityCalendars .Calendars .CalendarDijit .dijitCalendarArrow
2 X4 G5 ^8 V/ ^9 ~& U) ~3 e{# [$ @+ v  Y$ t; T* Y$ B
     visibility: hidden;6 F, k( D. F4 M  ]+ A
}

( a) \+ n! F- o4 I( e接下来,创建两个新按钮,以便允许用户导航月份。以编程方式使用 dijit/form/Button 创建这两个按钮。对于第一个按钮(后退),可以将标签设置为 “<<” 并修改 onClick 函数(清单 17)。onClick 的逻辑将包含在 goToPreviousMonth 函数中。% J9 w0 y) F: U' E2 F: C2 S
, M$ W- G5 x4 l4 u3 y. D* N
清单 17. 创建 dijit/form/bottom 的一个实例
, e$ V% S2 N  s6 E5 [
this.calendarPreviousMonthButton = new Button({$ {+ k3 v8 N7 |5 ]: M% f
       label: "<<",        
5 `. k. D, j( w- F" @4 _       onClick: lang.hitch(this, function(){4 ^5 l, {; W" z* I: ^
               this.goToPreviousMonth(this.calendarInstance);6 T1 z1 O* }! ~
       }); E0 G9 R6 C' j. G4 _; R4 ^
}, this.calendarPreviousMonthButtonAP);

0 {4 I  C" A9 s; R$ @: h您希望在用户每次单击该按钮时,日历后退一个月。在 goToPreviousMonth 中,需要先将 currentFocusDate 更改为 currentFocusDate - 1 month,然后刷新日历的视图。最后,必须检查这是否要显示的最后一个月,如果是,则禁用该按钮。3 |  V; x" r8 R' Y* i; M
使用 dojo/date/add 函数,它接受日期对象、间隔(字符串)和数量(整数)。对于您的情形,日期应该是 currentFocusDate 对象,间隔是 “month”,数量是 -1(清单 18)。
$ k( j. K0 n! w+ |5 H% ^4 _* K. S0 q3 J* H& t3 u6 W, Y7 _
清单 18. 日历视图减去一个月( r, f/ G  o- n
this.currentFocusDate = dojoDate.add(this.currentFocusDate,"month",-1);3 N" n5 i9 H+ F  y
calendarInstance.set("currentFocus",this.currentFocusDate);
9 w) E! P; L5 Q" F" f$ x3 W
设置日历的新视图,将 currentFocus 设置为新的日期值。(这将自动刷新日历并显示新视图)。* x- N) `8 ~% Z& n
最后,请检查这是否是最后一个月的视图,方法是对比 currentFocusDate 与最小值边界;如果是最后一个月,则禁用后退按钮。另外,请检查您是否应启用了前进按钮(假如您禁用了该按钮,并且现在您离开了最大值边界)(清单 19)。0 u  i0 _3 R, ]* q: L+ n
+ B) ?: R) k+ h0 U. c, l4 U
清单 19. 检查我们是否应该禁用新导航按钮
0 l9 [3 ?- ~+ I1 F. r+ |
if(this.isLastCalendarMonth(this.bookingWindowMinDate, this.currentFocusDate)){
) F+ j/ h  E& Z        this.calendarPreviousMonthButton.set("disabled", true);) F) W. {% J/ J0 |6 `# P2 ^
}
: h% F' `. i/ t1 Sif(!this.isLastCalendarMonth(this.bookingWindowMaxDate, this.currentFocusDate)){
7 c6 p5 V3 S6 r$ s! F4 }9 r$ Q        this.calendarFollowingMonthButton.set("disabled", false);
9 O" p* }2 [* N' D# s$ ^2 i}

; f6 K* I/ w0 p第二个按钮的工作原理相同。该标签将为 “>>”,onClick 调用 goToNextMonth,后者使用了同一个函数,但您添加了一个月(清单 20)。
& E3 a- M3 }# P6 ~
& M. F5 v% C6 K$ Q1 @7 g  M/ |清单 20. 控制移动到下一个月的按钮的函数
: r/ ^. m  z2 u5 L( b9 l' {
goToNextMonth : function (calendarInstance){
! |$ a; Y1 {. a" d$ F1 {        this.currentFocusDate = dojoDate.add(this.currentFocusDate,"month",1);
' ]* z  e0 A! c1 {9 F% c/ q        calendarInstance.set("currentFocus",this.currentFocusDate);' \- M" z3 ]5 ?+ \
        if(this.isLastCalendarMonth(this.bookingWindowMaxDate, this.currentFocusDate)){0 r' ?! {1 K6 [* u/ _2 s& T
                this.calendarFollowingMonthButton.set("disabled", true);2 S$ R3 d& {7 z% \- R5 ^
        }        
. k4 g0 z" u" `        if(!this.isLastCalendarMonth(this.bookingWindowMinDate, this.currentFocusDate)){4 t2 N: K8 h8 k5 m: N9 q6 \& j
                this.calendarPreviousMonthButton.set("disabled", false);+ }. F" a; O/ m- z, O* F7 n
        }, w' W4 C1 t9 U; E
}
3 x  o, w+ p  w" c8 F0 B0 ^
最后,清单 21 显示了应该在控制器类中的内容的示例,该类将进行相关调用,以便初始化您的新 customCalendar。/ x! Z" A- r0 m# H' N& f, M
7 _' r& q$ P& _, Q! W
清单 21. 创建新的自定义日历小部件的实例的快照5 y- |6 y# k$ M3 v' w1 B) h
require(["myUtil/customCalendar","dojo/_base/connect"], function(myCalendar, connect){1 E& H+ F2 b% N( g3 b% G% ]
        var params = {
5 e) }8 M. e1 y) j& Q. M" @5 m! H                "bookingWindowMinDate":"10/9/2011",
: M6 c, i! r, q6 n% I                "bookingWindowMaxDate":"10/9/2012",
7 O) P. p& V: g                "selectedDate":"8/15/2012",, U. O/ v/ U" S. D- N5 U
                "onValueSelectedPublishIDString":"selectedValueID"2 F) M+ p) s! w( U" k: x; F/ F9 C
        };2 Z/ n$ `2 Y1 q( z
        var myTest = myCalendar(params);$ [1 q3 w) D# P( Y
        myTest.placeAt("nodeId", "last");7 g" c3 ^/ y0 s5 f! s, R: ^$ B
               
; f; Z* Y! g. W        connect.subscribe("selectedValueID", function(date){) a( q% a6 m, K0 ?
          //Do some processing
! y) o3 t9 H8 s0 F' I          console.log("I got: ", date);
; d3 B# U1 Q! d& g        });        
3 _0 A6 D7 O. m1 w3 `' y        $ r- S3 P' L" r3 f$ y7 K  z- l+ v; d
});

3 @$ R5 X9 `! W# J如您所见,您创建了一个对象 params,其中包含需要传递给自定义日历小部件的值,并订阅了该频道。" U2 m5 s) I8 j2 v
更多函数
您可能会发现其他一些函数和属性在此场景中也很有用:1 @& R' X; [$ A) t8 E1 K
  • 当将一个日期对象和区域传递到 dojo/date/locale/isWeekend 时,如果日期是周末(对于 en-us 区域,是星期六和星期日),则会返回 true。如果需要,可以使用该属性来禁用周末日期或为周末设置不同的样式。
  • Calendar dijit 还包含一个 dayWidth 属性,该属性接受一个字符串作为值。默认情况下,会将它设置为 “narrow”,这缩短了显示的日历日期表示,例如使用 “M” 表示星期一。其他值包括表示完整日期名称显示的 “wide” 和表示缩写词的 “abbr”(比如 “Mon”)。
    $ J  ]8 X* u* q( d2 ~1 K
这些自定义小部件需求的一种变体可能要求小部件显示多个日历,然后,在用户通过单击来查看下一个月时,要求两个日历都前进一个月(参见图 3)。这很容易完成,只需更改小部件变量来支持一个数组,而不是单个值变量。9 Z6 x- E) q6 N/ O3 {) m
+ b% t/ |+ j9 [$ @# t& J6 N' F
图 3. 每个视图多个日历
$ {$ @4 v/ W1 c/ }% D! V
, J" `! g* T4 a1 Q
" f3 Q+ A1 ?5 Y7 y
, x: C: z$ A! `; I8 M) U" A9 K
结束语
通过组合 JavaScript 和 CSS 修改,很容易创建一个自定义小部件来更好地满足项目需求。本文演示了这种做法,使用 Dojo 1.7 声明了一个类,该类扩展了 Calendar dijit 并利用了一些 dojo 功能,比如日期操作、hitch、发布和订阅,以及其他一些基础 dojo 函数。希望您将能够应用这些步骤来扩展 Dojo dijit,并创建自己的新小部件。
; e4 b2 U$ J5 ^$ z" u& e4 h; s5 c, D( j0 R! c# P# ^: V

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
 楼主| 发表于 2013-2-19 10:43:23 | 显示全部楼层
本帖最后由 技术狂人 于 2013-2-19 10:44 编辑 * a* J; K! w# `0 _& o

' n- f0 T# k0 ]7 K8 e6 V( ]
下载
描述名字大小3 U6 L4 \1 S# a$ l; M
样例应用程序4 KB; u( e. [2 ~0 q3 X7 r" S" b6 @
8 t" `- |: Q% H" X- z

& x* X, y  @% W/ r/ e& ?- Z: `原文地址:http://www.ibm.com/developerwork ... er/1209_weller.html

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|手机版|无图版|SCMLife.com ( 京ICP备06056490号-1 )

GMT+8, 2018-1-18 00:12 , Processed in 0.079833 second(s), 6 queries , Gzip On, MemCache On.

Powered by SCMLife X3.4 Licensed

© 2001-2017 JoyShare.

快速回复 返回顶部 返回列表